Merge "Fix is installed check condition in DevicePolicyManagerService"
diff --git a/Android.mk b/Android.mk
index 109f610..f544620 100644
--- a/Android.mk
+++ b/Android.mk
@@ -408,10 +408,10 @@
location/java/android/location/INetInitiatedListener.aidl \
location/java/com/android/internal/location/ILocationProvider.aidl \
media/java/android/media/IAudioService.aidl \
- media/java/android/media/ICas.aidl \
- media/java/android/media/ICasListener.aidl \
- media/java/android/media/IDescrambler.aidl \
- media/java/android/media/IMediaCasService.aidl \
+ ../av/drm/libmediadrm/aidl/android/media/ICas.aidl \
+ ../av/drm/libmediadrm/aidl/android/media/ICasListener.aidl \
+ ../av/drm/libmediadrm/aidl/android/media/IDescrambler.aidl \
+ ../av/drm/libmediadrm/aidl/android/media/IMediaCasService.aidl \
media/java/android/media/IAudioFocusDispatcher.aidl \
media/java/android/media/IAudioRoutesObserver.aidl \
media/java/android/media/IMediaHTTPConnection.aidl \
@@ -441,6 +441,7 @@
media/java/android/media/projection/IMediaProjectionManager.aidl \
media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl \
media/java/android/media/session/IActiveSessionsListener.aidl \
+ media/java/android/media/session/ICallback.aidl \
media/java/android/media/session/IOnMediaKeyListener.aidl \
media/java/android/media/session/IOnVolumeKeyLongPressListener.aidl \
media/java/android/media/session/ISession.aidl \
@@ -537,6 +538,7 @@
LOCAL_AIDL_INCLUDES += \
frameworks/av/camera/aidl \
+ frameworks/av/drm/libmediadrm/aidl \
frameworks/native/aidl/gui \
system/netd/server/binder
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_10.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_10.xml
index a8d3de0..4a4b3b4 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_10.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_10.xml
@@ -35,7 +35,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="20px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_100.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_100.xml
index d991862..0b326e8 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_100.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_100.xml
@@ -19,7 +19,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="110px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_1000.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_1000.xml
index 3b55b6c..2f4239d 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_1000.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_1000.xml
@@ -19,7 +19,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="1010px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_10000.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_10000.xml
index 64a25c2..b6be10a 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_10000.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_10000.xml
@@ -19,7 +19,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="10010px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_100000.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_100000.xml
index 1f60783..aed339c 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_100000.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_100000.xml
@@ -19,7 +19,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="100010px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_300.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_300.xml
index 54c7e71..62522ba 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_300.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_300.xml
@@ -19,7 +19,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="310px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_5.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_5.xml
index 525b2c8..f383fa4 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_5.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_5.xml
@@ -35,7 +35,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="15px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_50.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_50.xml
index 470c4da..04dd6c2 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_50.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_50.xml
@@ -19,7 +19,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="60px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_500.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_500.xml
index b8a6e0a..a8e2b38 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_500.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_500.xml
@@ -19,7 +19,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="510px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java b/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java
index 6ee6f70..c310166 100644
--- a/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java
@@ -89,7 +89,7 @@
while (state.keepRunning()) {
TextView textView = new TextView(activity);
- // TextView#onMeasure() gets called, which triggers TextView#autoSizeText()
+ // TextView#onLayout() gets called, which triggers TextView#autoSizeText()
// which is the method we want to benchmark.
textView.requestLayout();
}
diff --git a/api/current.txt b/api/current.txt
index 62365cc..445c576 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -305,7 +305,7 @@
field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
field public static final int autoSizePresetSizes = 16844087; // 0x1010537
field public static final int autoSizeStepGranularity = 16844086; // 0x1010536
- field public static final int autoSizeText = 16844085; // 0x1010535
+ field public static final int autoSizeTextType = 16844085; // 0x1010535
field public static final int autoStart = 16843445; // 0x10102b5
field public static final deprecated int autoText = 16843114; // 0x101016a
field public static final int autoUrlDetect = 16843404; // 0x101028c
@@ -410,6 +410,7 @@
field public static final int colorControlHighlight = 16843820; // 0x101042c
field public static final int colorControlNormal = 16843817; // 0x1010429
field public static final int colorEdgeEffect = 16843982; // 0x10104ce
+ field public static final int colorError = 16844100; // 0x1010544
field public static final int colorFocusedHighlight = 16843663; // 0x101038f
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
@@ -1316,7 +1317,6 @@
field public static final int textCheckMarkInverse = 16842823; // 0x1010047
field public static final int textColor = 16842904; // 0x1010098
field public static final int textColorAlertDialogListItem = 16843526; // 0x1010306
- field public static final int textColorError = 16844100; // 0x1010544
field public static final int textColorHighlight = 16842905; // 0x1010099
field public static final int textColorHighlightInverse = 16843599; // 0x101034f
field public static final int textColorHint = 16842906; // 0x101009a
@@ -6718,6 +6718,7 @@
method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
method public boolean isPeriodic();
method public boolean isPersisted();
+ method public boolean isRequireBatteryNotLow();
method public boolean isRequireCharging();
method public boolean isRequireDeviceIdle();
method public void writeToParcel(android.os.Parcel, int);
@@ -6744,6 +6745,7 @@
method public android.app.job.JobInfo.Builder setPeriodic(long, long);
method public android.app.job.JobInfo.Builder setPersisted(boolean);
method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
+ method public android.app.job.JobInfo.Builder setRequiresBatteryNotLow(boolean);
method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean);
method public android.app.job.JobInfo.Builder setTransientExtras(android.os.Bundle);
@@ -9041,6 +9043,7 @@
field public static final java.lang.String ACTION_CALL = "android.intent.action.CALL";
field public static final java.lang.String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON";
field public static final java.lang.String ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON";
+ field public static final java.lang.String ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
field public static final java.lang.String ACTION_CHOOSER = "android.intent.action.CHOOSER";
field public static final java.lang.String ACTION_CLEAR_PACKAGE = "android.intent.action.CLEAR_PACKAGE";
field public static final java.lang.String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
@@ -10102,10 +10105,12 @@
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
+ method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
+ field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10644,6 +10649,9 @@
method public int describeContents();
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
+ method public android.content.ComponentName[] getChooserComponentNames();
+ method public android.os.PersistableBundle getChooserExtras();
+ method public android.content.IntentFilter[] getChooserIntentFilters();
method public java.lang.CharSequence getDisabledMessage();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
@@ -10656,6 +10664,7 @@
method public java.lang.CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
+ method public boolean isChooser();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -10668,9 +10677,11 @@
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
+ method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
+ method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -12575,6 +12586,7 @@
method public static android.graphics.ColorSpace.Adaptation valueOf(java.lang.String);
method public static final android.graphics.ColorSpace.Adaptation[] values();
enum_constant public static final android.graphics.ColorSpace.Adaptation BRADFORD;
+ enum_constant public static final android.graphics.ColorSpace.Adaptation CIECAT02;
enum_constant public static final android.graphics.ColorSpace.Adaptation VON_KRIES;
}
@@ -14011,6 +14023,8 @@
public class ArcShape extends android.graphics.drawable.shapes.RectShape {
ctor public ArcShape(float, float);
+ method public final float getStartAngle();
+ method public final float getSweepAngle();
}
public class OvalShape extends android.graphics.drawable.shapes.RectShape {
@@ -20646,6 +20660,26 @@
field public static final int TYPE_WIRED_HEADSET = 3; // 0x3
}
+ public final class AudioFocusRequest {
+ method public boolean acceptsDelayedFocusGain();
+ method public android.media.AudioAttributes getAudioAttributes();
+ method public int getFocusGain();
+ method public android.media.AudioManager.OnAudioFocusChangeListener getOnAudioFocusChangeListener();
+ method public android.os.Handler getOnAudioFocusChangeListenerHandler();
+ method public boolean willPauseWhenDucked();
+ }
+
+ public static final class AudioFocusRequest.Builder {
+ ctor public AudioFocusRequest.Builder(int);
+ ctor public AudioFocusRequest.Builder(android.media.AudioFocusRequest);
+ method public android.media.AudioFocusRequest build();
+ method public android.media.AudioFocusRequest.Builder setAcceptsDelayedFocusGain(boolean);
+ method public android.media.AudioFocusRequest.Builder setAudioAttributes(android.media.AudioAttributes);
+ method public android.media.AudioFocusRequest.Builder setFocusGain(int);
+ method public android.media.AudioFocusRequest.Builder setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener, android.os.Handler);
+ method public android.media.AudioFocusRequest.Builder setWillPauseWhenDucked(boolean);
+ }
+
public final class AudioFormat implements android.os.Parcelable {
method public int describeContents();
method public int getChannelCount();
@@ -20722,6 +20756,7 @@
public class AudioManager {
method public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
+ method public int abandonAudioFocusRequest(android.media.AudioFocusRequest);
method public void adjustStreamVolume(int, int, int);
method public void adjustSuggestedStreamVolume(int, int, int);
method public void adjustVolume(int, int);
@@ -20758,6 +20793,7 @@
method public deprecated void registerRemoteControlClient(android.media.RemoteControlClient);
method public deprecated boolean registerRemoteController(android.media.RemoteController);
method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
+ method public int requestAudioFocus(android.media.AudioFocusRequest);
method public deprecated void setBluetoothA2dpOn(boolean);
method public void setBluetoothScoOn(boolean);
method public void setMicrophoneMute(boolean);
@@ -20801,6 +20837,7 @@
field public static final int AUDIOFOCUS_LOSS_TRANSIENT = -2; // 0xfffffffe
field public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = -3; // 0xfffffffd
field public static final int AUDIOFOCUS_NONE = 0; // 0x0
+ field public static final int AUDIOFOCUS_REQUEST_DELAYED = 2; // 0x2
field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0
field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1
field public static final int AUDIO_SESSION_ID_GENERATE = 0; // 0x0
@@ -20997,13 +21034,14 @@
field public long nanoTime;
}
- public class AudioTrack implements android.media.AudioRouting {
+ public class AudioTrack implements android.media.AudioRouting android.media.VolumeAutomation {
ctor public deprecated AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public deprecated AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
method public int attachAuxEffect(int);
+ method public android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
method public void flush();
method public int getAudioFormat();
method public int getAudioSessionId();
@@ -22161,6 +22199,7 @@
field public static final java.lang.String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle";
field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval";
field public static final java.lang.String KEY_LANGUAGE = "language";
+ field public static final java.lang.String KEY_LATENCY = "latency";
field public static final java.lang.String KEY_LEVEL = "level";
field public static final java.lang.String KEY_MAX_HEIGHT = "max-height";
field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size";
@@ -22344,7 +22383,7 @@
field public static final int MUXER_OUTPUT_WEBM = 1; // 0x1
}
- public class MediaPlayer {
+ public class MediaPlayer implements android.media.VolumeAutomation {
ctor public MediaPlayer();
method public void addTimedTextSource(java.lang.String, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void addTimedTextSource(android.content.Context, android.net.Uri, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
@@ -22356,6 +22395,7 @@
method public static android.media.MediaPlayer create(android.content.Context, android.net.Uri, android.view.SurfaceHolder, android.media.AudioAttributes, int);
method public static android.media.MediaPlayer create(android.content.Context, int);
method public static android.media.MediaPlayer create(android.content.Context, int, android.media.AudioAttributes, int);
+ method public android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
method public void deselectTrack(int) throws java.lang.IllegalStateException;
method public int getAudioSessionId();
method public android.media.BufferingParams getBufferingParams();
@@ -23183,6 +23223,10 @@
ctor public UnsupportedSchemeException(java.lang.String);
}
+ public abstract interface VolumeAutomation {
+ method public abstract android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
+ }
+
public abstract class VolumeProvider {
ctor public VolumeProvider(int, int, int);
method public final int getCurrentVolume();
@@ -23196,6 +23240,53 @@
field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
}
+ public final class VolumeShaper implements java.lang.AutoCloseable {
+ method public void apply(android.media.VolumeShaper.Operation);
+ method public void close();
+ method public float getVolume();
+ method public void replace(android.media.VolumeShaper.Configuration, android.media.VolumeShaper.Operation, boolean);
+ }
+
+ public static final class VolumeShaper.Configuration implements android.os.Parcelable {
+ method public int describeContents();
+ method public double getDurationMs();
+ method public int getInterpolatorType();
+ method public static int getMaximumCurvePoints();
+ method public float[] getTimes();
+ method public float[] getVolumes();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.media.VolumeShaper.Configuration> CREATOR;
+ field public static final android.media.VolumeShaper.Configuration CUBIC_RAMP;
+ field public static final int INTERPOLATOR_TYPE_CUBIC = 2; // 0x2
+ field public static final int INTERPOLATOR_TYPE_CUBIC_MONOTONIC = 3; // 0x3
+ field public static final int INTERPOLATOR_TYPE_LINEAR = 1; // 0x1
+ field public static final int INTERPOLATOR_TYPE_STEP = 0; // 0x0
+ field public static final android.media.VolumeShaper.Configuration LINEAR_RAMP;
+ field public static final android.media.VolumeShaper.Configuration SCURVE_RAMP;
+ field public static final android.media.VolumeShaper.Configuration SINE_RAMP;
+ }
+
+ public static final class VolumeShaper.Configuration.Builder {
+ ctor public VolumeShaper.Configuration.Builder();
+ ctor public VolumeShaper.Configuration.Builder(android.media.VolumeShaper.Configuration);
+ method public android.media.VolumeShaper.Configuration build();
+ method public android.media.VolumeShaper.Configuration.Builder invertVolumes();
+ method public android.media.VolumeShaper.Configuration.Builder reflectTimes();
+ method public android.media.VolumeShaper.Configuration.Builder scaleToEndVolume(float);
+ method public android.media.VolumeShaper.Configuration.Builder scaleToStartVolume(float);
+ method public android.media.VolumeShaper.Configuration.Builder setCurve(float[], float[]);
+ method public android.media.VolumeShaper.Configuration.Builder setDurationMs(double);
+ method public android.media.VolumeShaper.Configuration.Builder setInterpolatorType(int);
+ }
+
+ public static final class VolumeShaper.Operation implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.media.VolumeShaper.Operation> CREATOR;
+ field public static final android.media.VolumeShaper.Operation PLAY;
+ field public static final android.media.VolumeShaper.Operation REVERSE;
+ }
+
}
package android.media.audiofx {
@@ -26075,8 +26166,6 @@
public class DiscoverySession {
method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
method public void destroy();
- method public static int getMaxSendRetryCount();
- method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[], int);
method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
}
@@ -36321,10 +36410,10 @@
public static final class FillResponse.Builder {
ctor public FillResponse.Builder();
method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
- method public android.service.autofill.FillResponse.Builder addSavableFields(android.view.autofill.AutoFillId...);
method public android.service.autofill.FillResponse build();
method public android.service.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender, android.widget.RemoteViews);
method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+ method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
}
public final class SaveCallback {
@@ -36332,6 +36421,23 @@
method public void onSuccess();
}
+ public final class SaveInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+ field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
+ field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3
+ field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
+ field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
+ }
+
+ public static final class SaveInfo.Builder {
+ ctor public SaveInfo.Builder(int);
+ method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
+ method public android.service.autofill.SaveInfo build();
+ method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
+ }
+
}
package android.service.carrier {
@@ -42447,30 +42553,51 @@
method public abstract void setValue(T, float);
}
- public final class Half {
+ public final class Half extends java.lang.Number implements java.lang.Comparable {
+ ctor public Half(short);
+ ctor public Half(float);
+ ctor public Half(double);
+ ctor public Half(java.lang.String) throws java.lang.NumberFormatException;
method public static short abs(short);
method public static short ceil(short);
+ method public static int compare(short, short);
+ method public int compareTo(android.util.Half);
method public static short copySign(short, short);
+ method public double doubleValue();
method public static boolean equals(short, short);
+ method public float floatValue();
method public static short floor(short);
method public static int getExponent(short);
method public static int getSign(short);
method public static int getSignificand(short);
method public static boolean greater(short, short);
method public static boolean greaterEquals(short, short);
+ method public static int halfToIntBits(short);
+ method public static int halfToRawIntBits(short);
+ method public static short halfToShortBits(short);
+ method public short halfValue();
+ method public static int hashCode(short);
+ method public static short intBitsToHalf(int);
+ method public int intValue();
method public static boolean isInfinite(short);
+ method public boolean isNaN();
method public static boolean isNaN(short);
method public static boolean isNormalized(short);
method public static boolean less(short, short);
method public static boolean lessEquals(short, short);
+ method public long longValue();
method public static short max(short, short);
method public static short min(short, short);
+ method public static short parseHalf(java.lang.String) throws java.lang.NumberFormatException;
method public static short round(short);
method public static float toFloat(short);
+ method public static short toHalf(float);
method public static java.lang.String toHexString(short);
method public static java.lang.String toString(short);
method public static short trunc(short);
- method public static short valueOf(float);
+ method public static android.util.Half valueOf(short);
+ method public static android.util.Half valueOf(float);
+ method public static android.util.Half valueOf(java.lang.String);
field public static final short EPSILON = 5120; // 0x1400
field public static final short LOWEST_VALUE = -1025; // 0xfffffbff
field public static final int MAX_EXPONENT = 15; // 0xf
@@ -44574,8 +44701,8 @@
method public void drawableHotspotChanged(float, float);
method protected void drawableStateChanged();
method public android.view.View findFocus();
- method public final android.view.View findViewById(int);
- method public final android.view.View findViewWithTag(java.lang.Object);
+ method public final <T extends android.view.View> T findViewById(int);
+ method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
method public android.view.View focusSearch(int);
diff --git a/api/removed.txt b/api/removed.txt
index e467811..c5dbf8d 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -20,25 +20,14 @@
package android.content {
public abstract class Context {
- method public deprecated android.content.Context createCredentialEncryptedStorageContext();
- method public deprecated android.content.Context createDeviceEncryptedStorageContext();
method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
method public abstract java.io.File getSharedPreferencesPath(java.lang.String);
- method public deprecated boolean isCredentialEncryptedStorage();
- method public deprecated boolean isDeviceEncryptedStorage();
- method public deprecated boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
- method public deprecated boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
}
}
package android.content.pm {
- public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
- field public deprecated java.lang.String credentialEncryptedDataDir;
- field public deprecated java.lang.String deviceEncryptedDataDir;
- }
-
public class ComponentInfo extends android.content.pm.PackageItemInfo {
field public deprecated boolean encryptionAware;
}
@@ -47,12 +36,6 @@
field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
}
- public abstract class PackageManager {
- field public static final deprecated int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
- field public static final deprecated int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
- field public static final deprecated int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
- }
-
}
package android.database {
@@ -169,10 +152,6 @@
method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
- method public deprecated boolean isUserRunningAndLocked();
- method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
- method public deprecated boolean isUserRunningAndUnlocked();
- method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
}
}
@@ -190,15 +169,6 @@
}
-package android.preference {
-
- public class PreferenceManager {
- method public deprecated void setStorageCredentialEncrypted();
- method public deprecated void setStorageDeviceEncrypted();
- }
-
-}
-
package android.provider {
public class Browser {
diff --git a/api/system-current.txt b/api/system-current.txt
index 8626f1b..e00507e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -418,7 +418,7 @@
field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
field public static final int autoSizePresetSizes = 16844087; // 0x1010537
field public static final int autoSizeStepGranularity = 16844086; // 0x1010536
- field public static final int autoSizeText = 16844085; // 0x1010535
+ field public static final int autoSizeTextType = 16844085; // 0x1010535
field public static final int autoStart = 16843445; // 0x10102b5
field public static final deprecated int autoText = 16843114; // 0x101016a
field public static final int autoUrlDetect = 16843404; // 0x101028c
@@ -523,6 +523,7 @@
field public static final int colorControlHighlight = 16843820; // 0x101042c
field public static final int colorControlNormal = 16843817; // 0x1010429
field public static final int colorEdgeEffect = 16843982; // 0x10104ce
+ field public static final int colorError = 16844100; // 0x1010544
field public static final int colorFocusedHighlight = 16843663; // 0x101038f
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
@@ -1433,7 +1434,6 @@
field public static final int textCheckMarkInverse = 16842823; // 0x1010047
field public static final int textColor = 16842904; // 0x1010098
field public static final int textColorAlertDialogListItem = 16843526; // 0x1010306
- field public static final int textColorError = 16844100; // 0x1010544
field public static final int textColorHighlight = 16842905; // 0x1010099
field public static final int textColorHighlightInverse = 16843599; // 0x101034f
field public static final int textColorHint = 16842906; // 0x101009a
@@ -7110,6 +7110,7 @@
method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
method public boolean isPeriodic();
method public boolean isPersisted();
+ method public boolean isRequireBatteryNotLow();
method public boolean isRequireCharging();
method public boolean isRequireDeviceIdle();
method public void writeToParcel(android.os.Parcel, int);
@@ -7136,6 +7137,7 @@
method public android.app.job.JobInfo.Builder setPeriodic(long, long);
method public android.app.job.JobInfo.Builder setPersisted(boolean);
method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
+ method public android.app.job.JobInfo.Builder setRequiresBatteryNotLow(boolean);
method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean);
method public android.app.job.JobInfo.Builder setTransientExtras(android.os.Bundle);
@@ -9515,6 +9517,7 @@
field public static final java.lang.String ACTION_CALL = "android.intent.action.CALL";
field public static final java.lang.String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON";
field public static final java.lang.String ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON";
+ field public static final java.lang.String ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
field public static final java.lang.String ACTION_CHOOSER = "android.intent.action.CHOOSER";
field public static final java.lang.String ACTION_CLEAR_PACKAGE = "android.intent.action.CLEAR_PACKAGE";
field public static final java.lang.String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
@@ -10639,10 +10642,12 @@
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
+ method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
+ field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -11266,6 +11271,9 @@
method public int describeContents();
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
+ method public android.content.ComponentName[] getChooserComponentNames();
+ method public android.os.PersistableBundle getChooserExtras();
+ method public android.content.IntentFilter[] getChooserIntentFilters();
method public java.lang.CharSequence getDisabledMessage();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
@@ -11278,6 +11286,7 @@
method public java.lang.CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
+ method public boolean isChooser();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -11290,9 +11299,11 @@
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
+ method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
+ method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -13211,6 +13222,7 @@
method public static android.graphics.ColorSpace.Adaptation valueOf(java.lang.String);
method public static final android.graphics.ColorSpace.Adaptation[] values();
enum_constant public static final android.graphics.ColorSpace.Adaptation BRADFORD;
+ enum_constant public static final android.graphics.ColorSpace.Adaptation CIECAT02;
enum_constant public static final android.graphics.ColorSpace.Adaptation VON_KRIES;
}
@@ -14647,6 +14659,8 @@
public class ArcShape extends android.graphics.drawable.shapes.RectShape {
ctor public ArcShape(float, float);
+ method public final float getStartAngle();
+ method public final float getSweepAngle();
}
public class OvalShape extends android.graphics.drawable.shapes.RectShape {
@@ -22304,6 +22318,26 @@
field public static final android.os.Parcelable.Creator<android.media.AudioFocusInfo> CREATOR;
}
+ public final class AudioFocusRequest {
+ method public boolean acceptsDelayedFocusGain();
+ method public android.media.AudioAttributes getAudioAttributes();
+ method public int getFocusGain();
+ method public android.media.AudioManager.OnAudioFocusChangeListener getOnAudioFocusChangeListener();
+ method public android.os.Handler getOnAudioFocusChangeListenerHandler();
+ method public boolean willPauseWhenDucked();
+ }
+
+ public static final class AudioFocusRequest.Builder {
+ ctor public AudioFocusRequest.Builder(int);
+ ctor public AudioFocusRequest.Builder(android.media.AudioFocusRequest);
+ method public android.media.AudioFocusRequest build();
+ method public android.media.AudioFocusRequest.Builder setAcceptsDelayedFocusGain(boolean);
+ method public android.media.AudioFocusRequest.Builder setAudioAttributes(android.media.AudioAttributes);
+ method public android.media.AudioFocusRequest.Builder setFocusGain(int);
+ method public android.media.AudioFocusRequest.Builder setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener, android.os.Handler);
+ method public android.media.AudioFocusRequest.Builder setWillPauseWhenDucked(boolean);
+ }
+
public final class AudioFormat implements android.os.Parcelable {
method public int describeContents();
method public int getChannelCount();
@@ -22381,6 +22415,7 @@
public class AudioManager {
method public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
method public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
+ method public int abandonAudioFocusRequest(android.media.AudioFocusRequest);
method public void adjustStreamVolume(int, int, int);
method public void adjustSuggestedStreamVolume(int, int, int);
method public void adjustVolume(int, int);
@@ -22419,6 +22454,7 @@
method public deprecated void registerRemoteControlClient(android.media.RemoteControlClient);
method public deprecated boolean registerRemoteController(android.media.RemoteController);
method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
+ method public int requestAudioFocus(android.media.AudioFocusRequest);
method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException;
method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy) throws java.lang.IllegalArgumentException;
method public deprecated void setBluetoothA2dpOn(boolean);
@@ -22468,6 +22504,7 @@
field public static final int AUDIOFOCUS_LOSS_TRANSIENT = -2; // 0xfffffffe
field public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = -3; // 0xfffffffd
field public static final int AUDIOFOCUS_NONE = 0; // 0x0
+ field public static final int AUDIOFOCUS_REQUEST_DELAYED = 2; // 0x2
field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0
field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1
field public static final int AUDIO_SESSION_ID_GENERATE = 0; // 0x0
@@ -22685,13 +22722,14 @@
field public long nanoTime;
}
- public class AudioTrack implements android.media.AudioRouting {
+ public class AudioTrack implements android.media.AudioRouting android.media.VolumeAutomation {
ctor public deprecated AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public deprecated AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
method public int attachAuxEffect(int);
+ method public android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
method public void flush();
method public int getAudioFormat();
method public int getAudioSessionId();
@@ -23849,6 +23887,7 @@
field public static final java.lang.String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle";
field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval";
field public static final java.lang.String KEY_LANGUAGE = "language";
+ field public static final java.lang.String KEY_LATENCY = "latency";
field public static final java.lang.String KEY_LEVEL = "level";
field public static final java.lang.String KEY_MAX_HEIGHT = "max-height";
field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size";
@@ -24032,7 +24071,7 @@
field public static final int MUXER_OUTPUT_WEBM = 1; // 0x1
}
- public class MediaPlayer {
+ public class MediaPlayer implements android.media.VolumeAutomation {
ctor public MediaPlayer();
method public void addTimedTextSource(java.lang.String, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void addTimedTextSource(android.content.Context, android.net.Uri, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
@@ -24044,6 +24083,7 @@
method public static android.media.MediaPlayer create(android.content.Context, android.net.Uri, android.view.SurfaceHolder, android.media.AudioAttributes, int);
method public static android.media.MediaPlayer create(android.content.Context, int);
method public static android.media.MediaPlayer create(android.content.Context, int, android.media.AudioAttributes, int);
+ method public android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
method public void deselectTrack(int) throws java.lang.IllegalStateException;
method public int getAudioSessionId();
method public android.media.BufferingParams getBufferingParams();
@@ -24882,6 +24922,10 @@
ctor public UnsupportedSchemeException(java.lang.String);
}
+ public abstract interface VolumeAutomation {
+ method public abstract android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
+ }
+
public abstract class VolumeProvider {
ctor public VolumeProvider(int, int, int);
method public final int getCurrentVolume();
@@ -24895,6 +24939,53 @@
field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
}
+ public final class VolumeShaper implements java.lang.AutoCloseable {
+ method public void apply(android.media.VolumeShaper.Operation);
+ method public void close();
+ method public float getVolume();
+ method public void replace(android.media.VolumeShaper.Configuration, android.media.VolumeShaper.Operation, boolean);
+ }
+
+ public static final class VolumeShaper.Configuration implements android.os.Parcelable {
+ method public int describeContents();
+ method public double getDurationMs();
+ method public int getInterpolatorType();
+ method public static int getMaximumCurvePoints();
+ method public float[] getTimes();
+ method public float[] getVolumes();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.media.VolumeShaper.Configuration> CREATOR;
+ field public static final android.media.VolumeShaper.Configuration CUBIC_RAMP;
+ field public static final int INTERPOLATOR_TYPE_CUBIC = 2; // 0x2
+ field public static final int INTERPOLATOR_TYPE_CUBIC_MONOTONIC = 3; // 0x3
+ field public static final int INTERPOLATOR_TYPE_LINEAR = 1; // 0x1
+ field public static final int INTERPOLATOR_TYPE_STEP = 0; // 0x0
+ field public static final android.media.VolumeShaper.Configuration LINEAR_RAMP;
+ field public static final android.media.VolumeShaper.Configuration SCURVE_RAMP;
+ field public static final android.media.VolumeShaper.Configuration SINE_RAMP;
+ }
+
+ public static final class VolumeShaper.Configuration.Builder {
+ ctor public VolumeShaper.Configuration.Builder();
+ ctor public VolumeShaper.Configuration.Builder(android.media.VolumeShaper.Configuration);
+ method public android.media.VolumeShaper.Configuration build();
+ method public android.media.VolumeShaper.Configuration.Builder invertVolumes();
+ method public android.media.VolumeShaper.Configuration.Builder reflectTimes();
+ method public android.media.VolumeShaper.Configuration.Builder scaleToEndVolume(float);
+ method public android.media.VolumeShaper.Configuration.Builder scaleToStartVolume(float);
+ method public android.media.VolumeShaper.Configuration.Builder setCurve(float[], float[]);
+ method public android.media.VolumeShaper.Configuration.Builder setDurationMs(double);
+ method public android.media.VolumeShaper.Configuration.Builder setInterpolatorType(int);
+ }
+
+ public static final class VolumeShaper.Operation implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.media.VolumeShaper.Operation> CREATOR;
+ field public static final android.media.VolumeShaper.Operation PLAY;
+ field public static final android.media.VolumeShaper.Operation REVERSE;
+ }
+
}
package android.media.audiofx {
@@ -25876,6 +25967,12 @@
method public static final boolean isChannelUriForTunerInput(android.net.Uri);
method public static final boolean isProgramUri(android.net.Uri);
field public static final java.lang.String AUTHORITY = "android.media.tv";
+ field public static final java.lang.String EXTRA_COLUMN_NAME = "android.media.tv.extra.COLUMN_NAME";
+ field public static final java.lang.String EXTRA_DATA_TYPE = "android.media.tv.extra.DATA_TYPE";
+ field public static final java.lang.String EXTRA_DEFAULT_VALUE = "android.media.tv.extra.DEFAULT_VALUE";
+ field public static final java.lang.String EXTRA_EXISTING_COLUMN_NAMES = "android.media.tv.extra.EXISTING_COLUMN_NAMES";
+ field public static final java.lang.String METHOD_ADD_COLUMN = "add_column";
+ field public static final java.lang.String METHOD_GET_COLUMNS = "get_columns";
}
public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
@@ -27124,7 +27221,8 @@
}
public abstract class NetworkRecommendationProvider {
- ctor public NetworkRecommendationProvider(android.os.Handler);
+ ctor public deprecated NetworkRecommendationProvider(android.os.Handler);
+ ctor public NetworkRecommendationProvider(android.content.Context, java.util.concurrent.Executor);
method public final android.os.IBinder getBinder();
method public abstract void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback);
method public abstract void onRequestScores(android.net.NetworkKey[]);
@@ -28653,8 +28751,6 @@
public class DiscoverySession {
method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
method public void destroy();
- method public static int getMaxSendRetryCount();
- method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[], int);
method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
}
@@ -39234,10 +39330,10 @@
public static final class FillResponse.Builder {
ctor public FillResponse.Builder();
method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
- method public android.service.autofill.FillResponse.Builder addSavableFields(android.view.autofill.AutoFillId...);
method public android.service.autofill.FillResponse build();
method public android.service.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender, android.widget.RemoteViews);
method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+ method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
}
public final class SaveCallback {
@@ -39245,6 +39341,23 @@
method public void onSuccess();
}
+ public final class SaveInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+ field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
+ field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3
+ field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
+ field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
+ }
+
+ public static final class SaveInfo.Builder {
+ ctor public SaveInfo.Builder(int);
+ method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
+ method public android.service.autofill.SaveInfo build();
+ method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
+ }
+
}
package android.service.carrier {
@@ -45785,30 +45898,51 @@
method public abstract void setValue(T, float);
}
- public final class Half {
+ public final class Half extends java.lang.Number implements java.lang.Comparable {
+ ctor public Half(short);
+ ctor public Half(float);
+ ctor public Half(double);
+ ctor public Half(java.lang.String) throws java.lang.NumberFormatException;
method public static short abs(short);
method public static short ceil(short);
+ method public static int compare(short, short);
+ method public int compareTo(android.util.Half);
method public static short copySign(short, short);
+ method public double doubleValue();
method public static boolean equals(short, short);
+ method public float floatValue();
method public static short floor(short);
method public static int getExponent(short);
method public static int getSign(short);
method public static int getSignificand(short);
method public static boolean greater(short, short);
method public static boolean greaterEquals(short, short);
+ method public static int halfToIntBits(short);
+ method public static int halfToRawIntBits(short);
+ method public static short halfToShortBits(short);
+ method public short halfValue();
+ method public static int hashCode(short);
+ method public static short intBitsToHalf(int);
+ method public int intValue();
method public static boolean isInfinite(short);
+ method public boolean isNaN();
method public static boolean isNaN(short);
method public static boolean isNormalized(short);
method public static boolean less(short, short);
method public static boolean lessEquals(short, short);
+ method public long longValue();
method public static short max(short, short);
method public static short min(short, short);
+ method public static short parseHalf(java.lang.String) throws java.lang.NumberFormatException;
method public static short round(short);
method public static float toFloat(short);
+ method public static short toHalf(float);
method public static java.lang.String toHexString(short);
method public static java.lang.String toString(short);
method public static short trunc(short);
- method public static short valueOf(float);
+ method public static android.util.Half valueOf(short);
+ method public static android.util.Half valueOf(float);
+ method public static android.util.Half valueOf(java.lang.String);
field public static final short EPSILON = 5120; // 0x1400
field public static final short LOWEST_VALUE = -1025; // 0xfffffbff
field public static final int MAX_EXPONENT = 15; // 0xf
@@ -47912,8 +48046,8 @@
method public void drawableHotspotChanged(float, float);
method protected void drawableStateChanged();
method public android.view.View findFocus();
- method public final android.view.View findViewById(int);
- method public final android.view.View findViewWithTag(java.lang.Object);
+ method public final <T extends android.view.View> T findViewById(int);
+ method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
method public android.view.View focusSearch(int);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 6773112..a3093e2 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -18,25 +18,14 @@
package android.content {
public abstract class Context {
- method public deprecated android.content.Context createCredentialEncryptedStorageContext();
- method public deprecated android.content.Context createDeviceEncryptedStorageContext();
method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
method public abstract java.io.File getSharedPreferencesPath(java.lang.String);
- method public deprecated boolean isCredentialEncryptedStorage();
- method public deprecated boolean isDeviceEncryptedStorage();
- method public deprecated boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
- method public deprecated boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
}
}
package android.content.pm {
- public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
- field public deprecated java.lang.String credentialEncryptedDataDir;
- field public deprecated java.lang.String deviceEncryptedDataDir;
- }
-
public class ComponentInfo extends android.content.pm.PackageItemInfo {
field public deprecated boolean encryptionAware;
}
@@ -45,12 +34,6 @@
field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
}
- public abstract class PackageManager {
- field public static final deprecated int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
- field public static final deprecated int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
- field public static final deprecated int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
- }
-
}
package android.database {
@@ -163,10 +146,6 @@
method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
- method public deprecated boolean isUserRunningAndLocked();
- method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
- method public deprecated boolean isUserRunningAndUnlocked();
- method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
}
}
@@ -184,15 +163,6 @@
}
-package android.preference {
-
- public class PreferenceManager {
- method public deprecated void setStorageCredentialEncrypted();
- method public deprecated void setStorageDeviceEncrypted();
- }
-
-}
-
package android.provider {
public class Browser {
diff --git a/api/test-current.txt b/api/test-current.txt
index 44386be..500a056 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -305,7 +305,7 @@
field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
field public static final int autoSizePresetSizes = 16844087; // 0x1010537
field public static final int autoSizeStepGranularity = 16844086; // 0x1010536
- field public static final int autoSizeText = 16844085; // 0x1010535
+ field public static final int autoSizeTextType = 16844085; // 0x1010535
field public static final int autoStart = 16843445; // 0x10102b5
field public static final deprecated int autoText = 16843114; // 0x101016a
field public static final int autoUrlDetect = 16843404; // 0x101028c
@@ -410,6 +410,7 @@
field public static final int colorControlHighlight = 16843820; // 0x101042c
field public static final int colorControlNormal = 16843817; // 0x1010429
field public static final int colorEdgeEffect = 16843982; // 0x10104ce
+ field public static final int colorError = 16844100; // 0x1010544
field public static final int colorFocusedHighlight = 16843663; // 0x101038f
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
@@ -1316,7 +1317,6 @@
field public static final int textCheckMarkInverse = 16842823; // 0x1010047
field public static final int textColor = 16842904; // 0x1010098
field public static final int textColorAlertDialogListItem = 16843526; // 0x1010306
- field public static final int textColorError = 16844100; // 0x1010544
field public static final int textColorHighlight = 16842905; // 0x1010099
field public static final int textColorHighlightInverse = 16843599; // 0x101034f
field public static final int textColorHint = 16842906; // 0x101009a
@@ -6744,6 +6744,7 @@
method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
method public boolean isPeriodic();
method public boolean isPersisted();
+ method public boolean isRequireBatteryNotLow();
method public boolean isRequireCharging();
method public boolean isRequireDeviceIdle();
method public void writeToParcel(android.os.Parcel, int);
@@ -6770,6 +6771,7 @@
method public android.app.job.JobInfo.Builder setPeriodic(long, long);
method public android.app.job.JobInfo.Builder setPersisted(boolean);
method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
+ method public android.app.job.JobInfo.Builder setRequiresBatteryNotLow(boolean);
method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean);
method public android.app.job.JobInfo.Builder setTransientExtras(android.os.Bundle);
@@ -9070,6 +9072,7 @@
field public static final java.lang.String ACTION_CALL = "android.intent.action.CALL";
field public static final java.lang.String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON";
field public static final java.lang.String ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON";
+ field public static final java.lang.String ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
field public static final java.lang.String ACTION_CHOOSER = "android.intent.action.CHOOSER";
field public static final java.lang.String ACTION_CLEAR_PACKAGE = "android.intent.action.CLEAR_PACKAGE";
field public static final java.lang.String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
@@ -10134,10 +10137,12 @@
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
+ method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
+ field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10680,6 +10685,9 @@
method public int describeContents();
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
+ method public android.content.ComponentName[] getChooserComponentNames();
+ method public android.os.PersistableBundle getChooserExtras();
+ method public android.content.IntentFilter[] getChooserIntentFilters();
method public java.lang.CharSequence getDisabledMessage();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
@@ -10692,6 +10700,7 @@
method public java.lang.CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
+ method public boolean isChooser();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -10704,9 +10713,11 @@
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
+ method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
+ method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -12612,6 +12623,7 @@
method public static android.graphics.ColorSpace.Adaptation valueOf(java.lang.String);
method public static final android.graphics.ColorSpace.Adaptation[] values();
enum_constant public static final android.graphics.ColorSpace.Adaptation BRADFORD;
+ enum_constant public static final android.graphics.ColorSpace.Adaptation CIECAT02;
enum_constant public static final android.graphics.ColorSpace.Adaptation VON_KRIES;
}
@@ -14049,6 +14061,8 @@
public class ArcShape extends android.graphics.drawable.shapes.RectShape {
ctor public ArcShape(float, float);
+ method public final float getStartAngle();
+ method public final float getSweepAngle();
}
public class OvalShape extends android.graphics.drawable.shapes.RectShape {
@@ -20742,6 +20756,26 @@
field public static final int TYPE_WIRED_HEADSET = 3; // 0x3
}
+ public final class AudioFocusRequest {
+ method public boolean acceptsDelayedFocusGain();
+ method public android.media.AudioAttributes getAudioAttributes();
+ method public int getFocusGain();
+ method public android.media.AudioManager.OnAudioFocusChangeListener getOnAudioFocusChangeListener();
+ method public android.os.Handler getOnAudioFocusChangeListenerHandler();
+ method public boolean willPauseWhenDucked();
+ }
+
+ public static final class AudioFocusRequest.Builder {
+ ctor public AudioFocusRequest.Builder(int);
+ ctor public AudioFocusRequest.Builder(android.media.AudioFocusRequest);
+ method public android.media.AudioFocusRequest build();
+ method public android.media.AudioFocusRequest.Builder setAcceptsDelayedFocusGain(boolean);
+ method public android.media.AudioFocusRequest.Builder setAudioAttributes(android.media.AudioAttributes);
+ method public android.media.AudioFocusRequest.Builder setFocusGain(int);
+ method public android.media.AudioFocusRequest.Builder setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener, android.os.Handler);
+ method public android.media.AudioFocusRequest.Builder setWillPauseWhenDucked(boolean);
+ }
+
public final class AudioFormat implements android.os.Parcelable {
method public int describeContents();
method public int getChannelCount();
@@ -20818,6 +20852,7 @@
public class AudioManager {
method public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
+ method public int abandonAudioFocusRequest(android.media.AudioFocusRequest);
method public void adjustStreamVolume(int, int, int);
method public void adjustSuggestedStreamVolume(int, int, int);
method public void adjustVolume(int, int);
@@ -20854,6 +20889,7 @@
method public deprecated void registerRemoteControlClient(android.media.RemoteControlClient);
method public deprecated boolean registerRemoteController(android.media.RemoteController);
method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
+ method public int requestAudioFocus(android.media.AudioFocusRequest);
method public deprecated void setBluetoothA2dpOn(boolean);
method public void setBluetoothScoOn(boolean);
method public void setMicrophoneMute(boolean);
@@ -20897,6 +20933,7 @@
field public static final int AUDIOFOCUS_LOSS_TRANSIENT = -2; // 0xfffffffe
field public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = -3; // 0xfffffffd
field public static final int AUDIOFOCUS_NONE = 0; // 0x0
+ field public static final int AUDIOFOCUS_REQUEST_DELAYED = 2; // 0x2
field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0
field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1
field public static final int AUDIO_SESSION_ID_GENERATE = 0; // 0x0
@@ -21093,13 +21130,14 @@
field public long nanoTime;
}
- public class AudioTrack implements android.media.AudioRouting {
+ public class AudioTrack implements android.media.AudioRouting android.media.VolumeAutomation {
ctor public deprecated AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public deprecated AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
method public int attachAuxEffect(int);
+ method public android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
method public void flush();
method public int getAudioFormat();
method public int getAudioSessionId();
@@ -22257,6 +22295,7 @@
field public static final java.lang.String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle";
field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval";
field public static final java.lang.String KEY_LANGUAGE = "language";
+ field public static final java.lang.String KEY_LATENCY = "latency";
field public static final java.lang.String KEY_LEVEL = "level";
field public static final java.lang.String KEY_MAX_HEIGHT = "max-height";
field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size";
@@ -22440,7 +22479,7 @@
field public static final int MUXER_OUTPUT_WEBM = 1; // 0x1
}
- public class MediaPlayer {
+ public class MediaPlayer implements android.media.VolumeAutomation {
ctor public MediaPlayer();
method public void addTimedTextSource(java.lang.String, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void addTimedTextSource(android.content.Context, android.net.Uri, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
@@ -22452,6 +22491,7 @@
method public static android.media.MediaPlayer create(android.content.Context, android.net.Uri, android.view.SurfaceHolder, android.media.AudioAttributes, int);
method public static android.media.MediaPlayer create(android.content.Context, int);
method public static android.media.MediaPlayer create(android.content.Context, int, android.media.AudioAttributes, int);
+ method public android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
method public void deselectTrack(int) throws java.lang.IllegalStateException;
method public int getAudioSessionId();
method public android.media.BufferingParams getBufferingParams();
@@ -23279,6 +23319,10 @@
ctor public UnsupportedSchemeException(java.lang.String);
}
+ public abstract interface VolumeAutomation {
+ method public abstract android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
+ }
+
public abstract class VolumeProvider {
ctor public VolumeProvider(int, int, int);
method public final int getCurrentVolume();
@@ -23292,6 +23336,53 @@
field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
}
+ public final class VolumeShaper implements java.lang.AutoCloseable {
+ method public void apply(android.media.VolumeShaper.Operation);
+ method public void close();
+ method public float getVolume();
+ method public void replace(android.media.VolumeShaper.Configuration, android.media.VolumeShaper.Operation, boolean);
+ }
+
+ public static final class VolumeShaper.Configuration implements android.os.Parcelable {
+ method public int describeContents();
+ method public double getDurationMs();
+ method public int getInterpolatorType();
+ method public static int getMaximumCurvePoints();
+ method public float[] getTimes();
+ method public float[] getVolumes();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.media.VolumeShaper.Configuration> CREATOR;
+ field public static final android.media.VolumeShaper.Configuration CUBIC_RAMP;
+ field public static final int INTERPOLATOR_TYPE_CUBIC = 2; // 0x2
+ field public static final int INTERPOLATOR_TYPE_CUBIC_MONOTONIC = 3; // 0x3
+ field public static final int INTERPOLATOR_TYPE_LINEAR = 1; // 0x1
+ field public static final int INTERPOLATOR_TYPE_STEP = 0; // 0x0
+ field public static final android.media.VolumeShaper.Configuration LINEAR_RAMP;
+ field public static final android.media.VolumeShaper.Configuration SCURVE_RAMP;
+ field public static final android.media.VolumeShaper.Configuration SINE_RAMP;
+ }
+
+ public static final class VolumeShaper.Configuration.Builder {
+ ctor public VolumeShaper.Configuration.Builder();
+ ctor public VolumeShaper.Configuration.Builder(android.media.VolumeShaper.Configuration);
+ method public android.media.VolumeShaper.Configuration build();
+ method public android.media.VolumeShaper.Configuration.Builder invertVolumes();
+ method public android.media.VolumeShaper.Configuration.Builder reflectTimes();
+ method public android.media.VolumeShaper.Configuration.Builder scaleToEndVolume(float);
+ method public android.media.VolumeShaper.Configuration.Builder scaleToStartVolume(float);
+ method public android.media.VolumeShaper.Configuration.Builder setCurve(float[], float[]);
+ method public android.media.VolumeShaper.Configuration.Builder setDurationMs(double);
+ method public android.media.VolumeShaper.Configuration.Builder setInterpolatorType(int);
+ }
+
+ public static final class VolumeShaper.Operation implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.media.VolumeShaper.Operation> CREATOR;
+ field public static final android.media.VolumeShaper.Operation PLAY;
+ field public static final android.media.VolumeShaper.Operation REVERSE;
+ }
+
}
package android.media.audiofx {
@@ -26171,8 +26262,6 @@
public class DiscoverySession {
method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
method public void destroy();
- method public static int getMaxSendRetryCount();
- method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[], int);
method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
}
@@ -36460,10 +36549,10 @@
public static final class FillResponse.Builder {
ctor public FillResponse.Builder();
method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
- method public android.service.autofill.FillResponse.Builder addSavableFields(android.view.autofill.AutoFillId...);
method public android.service.autofill.FillResponse build();
method public android.service.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender, android.widget.RemoteViews);
method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+ method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
}
public final class SaveCallback {
@@ -36471,6 +36560,23 @@
method public void onSuccess();
}
+ public final class SaveInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+ field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
+ field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3
+ field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
+ field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
+ }
+
+ public static final class SaveInfo.Builder {
+ ctor public SaveInfo.Builder(int);
+ method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
+ method public android.service.autofill.SaveInfo build();
+ method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
+ }
+
}
package android.service.carrier {
@@ -42636,30 +42742,51 @@
method public abstract void setValue(T, float);
}
- public final class Half {
+ public final class Half extends java.lang.Number implements java.lang.Comparable {
+ ctor public Half(short);
+ ctor public Half(float);
+ ctor public Half(double);
+ ctor public Half(java.lang.String) throws java.lang.NumberFormatException;
method public static short abs(short);
method public static short ceil(short);
+ method public static int compare(short, short);
+ method public int compareTo(android.util.Half);
method public static short copySign(short, short);
+ method public double doubleValue();
method public static boolean equals(short, short);
+ method public float floatValue();
method public static short floor(short);
method public static int getExponent(short);
method public static int getSign(short);
method public static int getSignificand(short);
method public static boolean greater(short, short);
method public static boolean greaterEquals(short, short);
+ method public static int halfToIntBits(short);
+ method public static int halfToRawIntBits(short);
+ method public static short halfToShortBits(short);
+ method public short halfValue();
+ method public static int hashCode(short);
+ method public static short intBitsToHalf(int);
+ method public int intValue();
method public static boolean isInfinite(short);
+ method public boolean isNaN();
method public static boolean isNaN(short);
method public static boolean isNormalized(short);
method public static boolean less(short, short);
method public static boolean lessEquals(short, short);
+ method public long longValue();
method public static short max(short, short);
method public static short min(short, short);
+ method public static short parseHalf(java.lang.String) throws java.lang.NumberFormatException;
method public static short round(short);
method public static float toFloat(short);
+ method public static short toHalf(float);
method public static java.lang.String toHexString(short);
method public static java.lang.String toString(short);
method public static short trunc(short);
- method public static short valueOf(float);
+ method public static android.util.Half valueOf(short);
+ method public static android.util.Half valueOf(float);
+ method public static android.util.Half valueOf(java.lang.String);
field public static final short EPSILON = 5120; // 0x1400
field public static final short LOWEST_VALUE = -1025; // 0xfffffbff
field public static final int MAX_EXPONENT = 15; // 0xf
@@ -44929,8 +45056,8 @@
method public void drawableHotspotChanged(float, float);
method protected void drawableStateChanged();
method public android.view.View findFocus();
- method public final android.view.View findViewById(int);
- method public final android.view.View findViewWithTag(java.lang.Object);
+ method public final <T extends android.view.View> T findViewById(int);
+ method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
method public android.view.View focusSearch(int);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index e467811..c5dbf8d 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -20,25 +20,14 @@
package android.content {
public abstract class Context {
- method public deprecated android.content.Context createCredentialEncryptedStorageContext();
- method public deprecated android.content.Context createDeviceEncryptedStorageContext();
method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
method public abstract java.io.File getSharedPreferencesPath(java.lang.String);
- method public deprecated boolean isCredentialEncryptedStorage();
- method public deprecated boolean isDeviceEncryptedStorage();
- method public deprecated boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
- method public deprecated boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
}
}
package android.content.pm {
- public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
- field public deprecated java.lang.String credentialEncryptedDataDir;
- field public deprecated java.lang.String deviceEncryptedDataDir;
- }
-
public class ComponentInfo extends android.content.pm.PackageItemInfo {
field public deprecated boolean encryptionAware;
}
@@ -47,12 +36,6 @@
field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
}
- public abstract class PackageManager {
- field public static final deprecated int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
- field public static final deprecated int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
- field public static final deprecated int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
- }
-
}
package android.database {
@@ -169,10 +152,6 @@
method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
- method public deprecated boolean isUserRunningAndLocked();
- method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
- method public deprecated boolean isUserRunningAndUnlocked();
- method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
}
}
@@ -190,15 +169,6 @@
}
-package android.preference {
-
- public class PreferenceManager {
- method public deprecated void setStorageCredentialEncrypted();
- method public deprecated void setStorageDeviceEncrypted();
- }
-
-}
-
package android.provider {
public class Browser {
diff --git a/core/java/android/annotation/HalfFloat.java b/core/java/android/annotation/HalfFloat.java
index d3e9f08..256008c 100644
--- a/core/java/android/annotation/HalfFloat.java
+++ b/core/java/android/annotation/HalfFloat.java
@@ -37,7 +37,7 @@
* }</pre>
*
* @see android.util.Half
- * @see android.util.Half#valueOf(float)
+ * @see android.util.Half#toHalf(float)
* @see android.util.Half#toFloat(short)
*
* @hide
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 1652299..0608acb 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1024,12 +1024,18 @@
}
@Override
- @SuppressWarnings("unchecked")
public List<ProviderInfo> queryContentProviders(String processName,
int uid, int flags) {
+ return queryContentProviders(processName, uid, flags, null);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public List<ProviderInfo> queryContentProviders(String processName,
+ int uid, int flags, String metaDataKey) {
try {
ParceledListSlice<ProviderInfo> slice =
- mPM.queryContentProviders(processName, uid, flags);
+ mPM.queryContentProviders(processName, uid, flags, metaDataKey);
return slice != null ? slice.getList() : Collections.<ProviderInfo>emptyList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 3e9b987..7ee93d0 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -38,6 +38,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
+import android.content.res.CompatResources;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -49,6 +50,7 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
+import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Debug;
import android.os.Environment;
@@ -1925,8 +1927,8 @@
final int displayId = mDisplay != null
? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
- c.mResources = createResources(mActivityToken, pi, displayId, null,
- getDisplayAdjustments(displayId).getCompatibilityInfo());
+ c.setResources(createResources(mActivityToken, pi, displayId, null,
+ getDisplayAdjustments(displayId).getCompatibilityInfo()));
if (c.mResources != null) {
return c;
}
@@ -1962,8 +1964,8 @@
final int displayId = mDisplay != null
? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
- c.mResources = createResources(mActivityToken, pi, displayId, null,
- getDisplayAdjustments(displayId).getCompatibilityInfo());
+ c.setResources(createResources(mActivityToken, pi, displayId, null,
+ getDisplayAdjustments(displayId).getCompatibilityInfo()));
if (c.mResources != null) {
return c;
}
@@ -1990,7 +1992,7 @@
final int displayId = mDisplay != null
? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
- context.mResources = ResourcesManager.getInstance().getResources(
+ context.setResources(ResourcesManager.getInstance().getResources(
mActivityToken,
mPackageInfo.getResDir(),
paths,
@@ -1999,7 +2001,7 @@
displayId,
null,
mPackageInfo.getCompatibilityInfo(),
- classLoader);
+ classLoader));
return context;
}
@@ -2013,8 +2015,8 @@
mUser, mFlags, mClassLoader);
final int displayId = mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
- context.mResources = createResources(mActivityToken, mPackageInfo, displayId,
- overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo());
+ context.setResources(createResources(mActivityToken, mPackageInfo, displayId,
+ overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo()));
return context;
}
@@ -2028,8 +2030,8 @@
mUser, mFlags, mClassLoader);
final int displayId = display.getDisplayId();
- context.mResources = createResources(mActivityToken, mPackageInfo, displayId, null,
- getDisplayAdjustments(displayId).getCompatibilityInfo());
+ context.setResources(createResources(mActivityToken, mPackageInfo, displayId, null,
+ getDisplayAdjustments(displayId).getCompatibilityInfo()));
context.mDisplay = display;
return context;
}
@@ -2136,7 +2138,7 @@
LoadedApk packageInfo = new LoadedApk(mainThread);
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, 0,
null);
- context.mResources = packageInfo.getResources();
+ context.setResources(packageInfo.getResources());
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
context.mResourcesManager.getDisplayMetrics());
return context;
@@ -2146,7 +2148,7 @@
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, 0,
null);
- context.mResources = packageInfo.getResources();
+ context.setResources(packageInfo.getResources());
return context;
}
@@ -2185,7 +2187,7 @@
// Create the base resources for which all configuration contexts for this Activity
// will be rebased upon.
- context.mResources = resourcesManager.createBaseActivityResources(activityToken,
+ context.setResources(resourcesManager.createBaseActivityResources(activityToken,
packageInfo.getResDir(),
splitDirs,
packageInfo.getOverlayDirs(),
@@ -2193,7 +2195,7 @@
displayId,
overrideConfiguration,
compatInfo,
- classLoader);
+ classLoader));
context.mDisplay = resourcesManager.getAdjustedDisplay(displayId,
context.getResources());
return context;
@@ -2232,7 +2234,7 @@
if (container != null) {
mBasePackageName = container.mBasePackageName;
mOpPackageName = container.mOpPackageName;
- mResources = container.mResources;
+ setResources(container.mResources);
mDisplay = container.mDisplay;
} else {
mBasePackageName = packageInfo.mPackageName;
@@ -2251,6 +2253,14 @@
mContentResolver = new ApplicationContentResolver(this, mainThread, user);
}
+ void setResources(Resources r) {
+ if (mPackageInfo.getTargetSdkVersion() < VERSION_CODES.O) {
+ mResources = new CompatResources(r, this);
+ } else {
+ mResources = r;
+ }
+ }
+
void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
mPackageInfo.installSystemApplicationInfo(info, classLoader);
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 812daf8..64fc44b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2702,11 +2702,11 @@
}
/**
- * Specifies the time at which this notification should be canceled, if it is not already
- * canceled.
+ * Specifies a duration in milliseconds after which this notification should be canceled,
+ * if it is not already canceled.
*/
- public Builder setTimeout(long when) {
- mN.mTimeout = when;
+ public Builder setTimeout(long durationMs) {
+ mN.mTimeout = durationMs;
return this;
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 9cb3dd6..6585793 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3346,6 +3346,17 @@
public static final int KEYGUARD_DISABLE_FEATURES_ALL = 0x7fffffff;
/**
+ * Keyguard features that when set on a managed profile that doesn't have its own challenge will
+ * affect the profile's parent user. These can also be set on the managed profile's parent
+ * {@link DevicePolicyManager} instance.
+ *
+ * @hide
+ */
+ public static final int PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER =
+ DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS
+ | DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
+
+ /**
* Called by an application that is administering the device to request that the storage system
* be encrypted.
* <p>
@@ -7697,7 +7708,34 @@
/**
* Called by a device owner to control the network logging feature.
*
- * <p> Network logs contain DNS lookup and connect() library call events.
+ * <p> Network logs contain DNS lookup and connect() library call events. The following library
+ * functions are recorded while network logging is active:
+ * <ul>
+ * <li>{@code getaddrinfo()}</li>
+ * <li>{@code gethostbyname()}</li>
+ * <li>{@code connect()}</li>
+ * </ul>
+ *
+ * <p> Network logging is a low-overhead tool for forensics but it is not guaranteed to use
+ * full system call logging; event reporting is enabled by default for all processes but not
+ * strongly enforced.
+ * Events from applications using alternative implementations of libc, making direct kernel
+ * calls, or deliberately obfuscating traffic may not be recorded.
+ *
+ * <p> Some common network events may not be reported. For example:
+ * <ul>
+ * <li>Applications may hardcode IP addresses to reduce the number of DNS lookups, or use
+ * an alternative system for name resolution, and so avoid calling
+ * {@code getaddrinfo()} or {@code gethostbyname}.</li>
+ * <li>Applications may use datagram sockets for performance reasons, for example
+ * for a game client. Calling {@code connect()} is unnecessary for this kind of
+ * socket, so it will not trigger a network event.</li>
+ * </ul>
+ *
+ * <p> It is possible to directly intercept layer 3 traffic leaving the device using an
+ * always-on VPN service.
+ * See {@link #setAlwaysOnVpnPackage(ComponentName, String, boolean)}
+ * and {@link android.net.VpnService} for details.
*
* <p><strong>Note:</strong> The device owner won't be able to retrieve network logs if there
* are unaffiliated secondary users or profiles on the device, regardless of whether the
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 2d6b45d..3887556 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -174,12 +174,26 @@
*/
public static final int FLAG_WILL_BE_FOREGROUND = 1 << 0;
+ /**
+ * @hide
+ */
+ public static final int CONSTRAINT_FLAG_CHARGING = 1 << 0;
+
+ /**
+ * @hide
+ */
+ public static final int CONSTRAINT_FLAG_BATTERY_NOT_LOW = 1 << 1;
+
+ /**
+ * @hide
+ */
+ public static final int CONSTRAINT_FLAG_DEVICE_IDLE = 1 << 2;
+
private final int jobId;
private final PersistableBundle extras;
private final Bundle transientExtras;
private final ComponentName service;
- private final boolean requireCharging;
- private final boolean requireDeviceIdle;
+ private final int constraintFlags;
private final TriggerContentUri[] triggerContentUris;
private final long triggerContentUpdateDelay;
private final long triggerContentMaxDelay;
@@ -241,14 +255,28 @@
* Whether this job needs the device to be plugged in.
*/
public boolean isRequireCharging() {
- return requireCharging;
+ return (constraintFlags & CONSTRAINT_FLAG_CHARGING) != 0;
+ }
+
+ /**
+ * Whether this job needs the device's battery level to not be at below the critical threshold.
+ */
+ public boolean isRequireBatteryNotLow() {
+ return (constraintFlags & CONSTRAINT_FLAG_BATTERY_NOT_LOW) != 0;
}
/**
* Whether this job needs the device to be in an Idle maintenance window.
*/
public boolean isRequireDeviceIdle() {
- return requireDeviceIdle;
+ return (constraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0;
+ }
+
+ /**
+ * @hide
+ */
+ public int getConstraintFlags() {
+ return constraintFlags;
}
/**
@@ -376,8 +404,7 @@
extras = in.readPersistableBundle();
transientExtras = in.readBundle();
service = in.readParcelable(null);
- requireCharging = in.readInt() == 1;
- requireDeviceIdle = in.readInt() == 1;
+ constraintFlags = in.readInt();
triggerContentUris = in.createTypedArray(TriggerContentUri.CREATOR);
triggerContentUpdateDelay = in.readLong();
triggerContentMaxDelay = in.readLong();
@@ -401,8 +428,7 @@
extras = b.mExtras.deepcopy();
transientExtras = b.mTransientExtras.deepcopy();
service = b.mJobService;
- requireCharging = b.mRequiresCharging;
- requireDeviceIdle = b.mRequiresDeviceIdle;
+ constraintFlags = b.mConstraintFlags;
triggerContentUris = b.mTriggerContentUris != null
? b.mTriggerContentUris.toArray(new TriggerContentUri[b.mTriggerContentUris.size()])
: null;
@@ -434,8 +460,7 @@
out.writePersistableBundle(extras);
out.writeBundle(transientExtras);
out.writeParcelable(service, flags);
- out.writeInt(requireCharging ? 1 : 0);
- out.writeInt(requireDeviceIdle ? 1 : 0);
+ out.writeInt(constraintFlags);
out.writeTypedArray(triggerContentUris, flags);
out.writeLong(triggerContentUpdateDelay);
out.writeLong(triggerContentMaxDelay);
@@ -563,8 +588,7 @@
private int mPriority = PRIORITY_DEFAULT;
private int mFlags;
// Requirements.
- private boolean mRequiresCharging;
- private boolean mRequiresDeviceIdle;
+ private int mConstraintFlags;
private int mNetworkType;
private ArrayList<TriggerContentUri> mTriggerContentUris;
private long mTriggerContentUpdateDelay = -1;
@@ -651,7 +675,21 @@
* @param requiresCharging Whether or not the device is plugged in.
*/
public Builder setRequiresCharging(boolean requiresCharging) {
- mRequiresCharging = requiresCharging;
+ mConstraintFlags = (mConstraintFlags&~CONSTRAINT_FLAG_CHARGING)
+ | (requiresCharging ? CONSTRAINT_FLAG_CHARGING : 0);
+ return this;
+ }
+
+ /**
+ * Specify that to run this job, the device's battery level must not be low.
+ * This defaults to false. If true, the job will only run when the battery level
+ * is not low, which is generally the point where the user is given a "low battery"
+ * warning.
+ * @param batteryNotLow Whether or not the device's battery level must not be low.
+ */
+ public Builder setRequiresBatteryNotLow(boolean batteryNotLow) {
+ mConstraintFlags = (mConstraintFlags&~CONSTRAINT_FLAG_BATTERY_NOT_LOW)
+ | (batteryNotLow ? CONSTRAINT_FLAG_BATTERY_NOT_LOW : 0);
return this;
}
@@ -666,7 +704,8 @@
* window.
*/
public Builder setRequiresDeviceIdle(boolean requiresDeviceIdle) {
- mRequiresDeviceIdle = requiresDeviceIdle;
+ mConstraintFlags = (mConstraintFlags&~CONSTRAINT_FLAG_DEVICE_IDLE)
+ | (requiresDeviceIdle ? CONSTRAINT_FLAG_DEVICE_IDLE : 0);
return this;
}
@@ -816,8 +855,8 @@
*/
public JobInfo build() {
// Allow jobs with no constraints - What am I, a database?
- if (!mHasEarlyConstraint && !mHasLateConstraint && !mRequiresCharging &&
- !mRequiresDeviceIdle && mNetworkType == NETWORK_TYPE_NONE &&
+ if (!mHasEarlyConstraint && !mHasLateConstraint && mConstraintFlags == 0 &&
+ mNetworkType == NETWORK_TYPE_NONE &&
mTriggerContentUris == null) {
throw new IllegalArgumentException("You're trying to build a job with no " +
"constraints, this is not allowed.");
@@ -843,7 +882,7 @@
throw new IllegalArgumentException("Can't call setTransientExtras() on a " +
"persisted job");
}
- if (mBackoffPolicySet && mRequiresDeviceIdle) {
+ if (mBackoffPolicySet && (mConstraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) {
throw new IllegalArgumentException("An idle mode job will not respect any" +
" back-off policy, so calling setBackoffCriteria with" +
" setRequiresDeviceIdle is an error.");
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 4480b41..be49f24 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -36,6 +36,7 @@
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.DeadObjectException;
@@ -500,6 +501,12 @@
public ContentResolver(Context context) {
mContext = context != null ? context : ActivityThread.currentApplication();
mPackageName = mContext.getOpPackageName();
+ if (android.os.Process.myUid() == android.os.Process.PHONE_UID) {
+ // STOPSHIP: Telephony needs to fix b/35792675
+ mTargetSdkVersion = Build.VERSION_CODES.N_MR1;
+ } else {
+ mTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
+ }
}
/** @hide */
@@ -1868,13 +1875,18 @@
/**
* Register an observer class that gets callbacks when data identified by a
* given content URI changes.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
+ * notifications must be backed by a valid {@link ContentProvider}.
*
- * @param uri The URI to watch for changes. This can be a specific row URI, or a base URI
- * for a whole class of content.
- * @param notifyForDescendants When false, the observer will be notified whenever a
- * change occurs to the exact URI specified by <code>uri</code> or to one of the
- * URI's ancestors in the path hierarchy. When true, the observer will also be notified
- * whenever a change occurs to the URI's descendants in the path hierarchy.
+ * @param uri The URI to watch for changes. This can be a specific row URI,
+ * or a base URI for a whole class of content.
+ * @param notifyForDescendants When false, the observer will be notified
+ * whenever a change occurs to the exact URI specified by
+ * <code>uri</code> or to one of the URI's ancestors in the path
+ * hierarchy. When true, the observer will also be notified
+ * whenever a change occurs to the URI's descendants in the path
+ * hierarchy.
* @param observer The object that receives callbacks when changes occur.
* @see #unregisterContentObserver
*/
@@ -1894,7 +1906,7 @@
ContentObserver observer, @UserIdInt int userHandle) {
try {
getContentService().registerContentObserver(uri, notifyForDescendents,
- observer.getContentObserver(), userHandle);
+ observer.getContentObserver(), userHandle, mTargetSdkVersion);
} catch (RemoteException e) {
}
}
@@ -1918,16 +1930,22 @@
}
/**
- * Notify registered observers that a row was updated and attempt to sync changes
- * to the network.
- * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}.
- * By default, CursorAdapter objects will get this notification.
+ * Notify registered observers that a row was updated and attempt to sync
+ * changes to the network.
+ * <p>
+ * To observe events sent through this call, use
+ * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
+ * notifications must be backed by a valid {@link ContentProvider}.
*
* @param uri The uri of the content that was changed.
- * @param observer The observer that originated the change, may be <code>null</null>.
- * The observer that originated the change will only receive the notification if it
- * has requested to receive self-change notifications by implementing
- * {@link ContentObserver#deliverSelfNotifications()} to return true.
+ * @param observer The observer that originated the change, may be
+ * <code>null</null>. The observer that originated the change
+ * will only receive the notification if it has requested to
+ * receive self-change notifications by implementing
+ * {@link ContentObserver#deliverSelfNotifications()} to return
+ * true.
*/
public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer) {
notifyChange(uri, observer, true /* sync to network */);
@@ -1935,17 +1953,25 @@
/**
* Notify registered observers that a row was updated.
- * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}.
- * By default, CursorAdapter objects will get this notification.
- * If syncToNetwork is true, this will attempt to schedule a local sync using the sync
- * adapter that's registered for the authority of the provided uri. No account will be
- * passed to the sync adapter, so all matching accounts will be synchronized.
+ * <p>
+ * To observe events sent through this call, use
+ * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
+ * <p>
+ * If syncToNetwork is true, this will attempt to schedule a local sync
+ * using the sync adapter that's registered for the authority of the
+ * provided uri. No account will be passed to the sync adapter, so all
+ * matching accounts will be synchronized.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
+ * notifications must be backed by a valid {@link ContentProvider}.
*
* @param uri The uri of the content that was changed.
- * @param observer The observer that originated the change, may be <code>null</null>.
- * The observer that originated the change will only receive the notification if it
- * has requested to receive self-change notifications by implementing
- * {@link ContentObserver#deliverSelfNotifications()} to return true.
+ * @param observer The observer that originated the change, may be
+ * <code>null</null>. The observer that originated the change
+ * will only receive the notification if it has requested to
+ * receive self-change notifications by implementing
+ * {@link ContentObserver#deliverSelfNotifications()} to return
+ * true.
* @param syncToNetwork If true, same as {@link #NOTIFY_SYNC_TO_NETWORK}.
* @see #requestSync(android.accounts.Account, String, android.os.Bundle)
*/
@@ -1961,17 +1987,25 @@
/**
* Notify registered observers that a row was updated.
- * To register, call {@link #registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver) registerContentObserver()}.
- * By default, CursorAdapter objects will get this notification.
- * If syncToNetwork is true, this will attempt to schedule a local sync using the sync
- * adapter that's registered for the authority of the provided uri. No account will be
- * passed to the sync adapter, so all matching accounts will be synchronized.
+ * <p>
+ * To observe events sent through this call, use
+ * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
+ * <p>
+ * If syncToNetwork is true, this will attempt to schedule a local sync
+ * using the sync adapter that's registered for the authority of the
+ * provided uri. No account will be passed to the sync adapter, so all
+ * matching accounts will be synchronized.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
+ * notifications must be backed by a valid {@link ContentProvider}.
*
* @param uri The uri of the content that was changed.
- * @param observer The observer that originated the change, may be <code>null</null>.
- * The observer that originated the change will only receive the notification if it
- * has requested to receive self-change notifications by implementing
- * {@link ContentObserver#deliverSelfNotifications()} to return true.
+ * @param observer The observer that originated the change, may be
+ * <code>null</null>. The observer that originated the change
+ * will only receive the notification if it has requested to
+ * receive self-change notifications by implementing
+ * {@link ContentObserver#deliverSelfNotifications()} to return
+ * true.
* @param flags Additional flags: {@link #NOTIFY_SYNC_TO_NETWORK}.
* @see #requestSync(android.accounts.Account, String, android.os.Bundle)
*/
@@ -1997,7 +2031,7 @@
uri, observer == null ? null : observer.getContentObserver(),
observer != null && observer.deliverSelfNotifications(),
syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0,
- userHandle);
+ userHandle, mTargetSdkVersion);
} catch (RemoteException e) {
}
}
@@ -2013,7 +2047,7 @@
getContentService().notifyChange(
uri, observer == null ? null : observer.getContentObserver(),
observer != null && observer.deliverSelfNotifications(), flags,
- userHandle);
+ userHandle, mTargetSdkVersion);
} catch (RemoteException e) {
}
}
@@ -2932,6 +2966,7 @@
private final Context mContext;
final String mPackageName;
+ final int mTargetSdkVersion;
private static final String TAG = "ContentResolver";
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 44f6c43..aff00c3 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -730,12 +730,6 @@
*/
public abstract boolean moveSharedPreferencesFrom(Context sourceContext, String name);
- /** @removed */
- @Deprecated
- public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
- return moveSharedPreferencesFrom(sourceContext, name);
- }
-
/**
* Delete an existing shared preferences file.
*
@@ -1451,12 +1445,6 @@
*/
public abstract boolean moveDatabaseFrom(Context sourceContext, String name);
- /** @removed */
- @Deprecated
- public boolean migrateDatabaseFrom(Context sourceContext, String name) {
- return moveDatabaseFrom(sourceContext, name);
- }
-
/**
* Delete an existing private SQLiteDatabase associated with this Context's
* application package.
@@ -4382,12 +4370,6 @@
*/
public abstract Context createDeviceProtectedStorageContext();
- /** @removed */
- @Deprecated
- public Context createDeviceEncryptedStorageContext() {
- return createDeviceProtectedStorageContext();
- }
-
/**
* Return a new Context object for the current Context but whose storage
* APIs are backed by credential-protected storage. This is the default
@@ -4416,12 +4398,6 @@
@SystemApi
public abstract Context createCredentialProtectedStorageContext();
- /** @removed */
- @Deprecated
- public Context createCredentialEncryptedStorageContext() {
- return createCredentialProtectedStorageContext();
- }
-
/**
* Gets the display adjustments holder for this context. This information
* is provided on a per-application or activity basis and is used to simulate lower density
@@ -4462,12 +4438,6 @@
*/
public abstract boolean isDeviceProtectedStorage();
- /** @removed */
- @Deprecated
- public boolean isDeviceEncryptedStorage() {
- return isDeviceProtectedStorage();
- }
-
/**
* Indicates if the storage APIs of this Context are backed by
* credential-protected storage.
@@ -4478,12 +4448,6 @@
@SystemApi
public abstract boolean isCredentialProtectedStorage();
- /** @removed */
- @Deprecated
- public boolean isCredentialEncryptedStorage() {
- return isCredentialProtectedStorage();
- }
-
/**
* @hide
*/
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 3446e03..c500116 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -42,7 +42,7 @@
* USER_CURRENT are properly handled.
*/
void registerContentObserver(in Uri uri, boolean notifyForDescendants,
- IContentObserver observer, int userHandle);
+ IContentObserver observer, int userHandle, int targetSdkVersion);
/**
* Notify observers of a particular user's view of the provider.
@@ -53,7 +53,7 @@
*/
void notifyChange(in Uri uri, IContentObserver observer,
boolean observerWantsSelfNotifications, int flags,
- int userHandle);
+ int userHandle, int targetSdkVersion);
void requestSync(in Account account, String authority, in Bundle extras);
/**
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 28068c5..870db217 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1115,6 +1115,15 @@
public static final String ACTION_SIM_ACTIVATION_REQUEST =
"android.intent.action.SIM_ACTIVATION_REQUEST";
/**
+ * Activity Action: Main entry point for carrier setup apps.
+ * <p>Carrier apps that provide an implementation for this action may be invoked to configure
+ * carrier service and typically require
+ * {@link android.telephony.TelephonyManager#hasCarrierPrivileges() carrier privileges} to
+ * fulfill their duties.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
+ /**
* Activity Action: Send a message to someone specified by the data.
* <p>Input: {@link #getData} is URI describing the target.
* <p>Output: nothing.
@@ -9260,6 +9269,13 @@
mClipData.prepareToLeaveProcess(leavingPackage, getFlags());
}
+ if (mExtras != null && !mExtras.isParcelled()) {
+ final Object intent = mExtras.get(Intent.EXTRA_INTENT);
+ if (intent instanceof Intent) {
+ ((Intent) intent).prepareToLeaveProcess(leavingPackage);
+ }
+ }
+
if (mAction != null && mData != null && StrictMode.vmFileUriExposureEnabled()
&& leavingPackage) {
switch (mAction) {
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 9737b11..b4d77a0 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -720,10 +720,6 @@
*/
public String deviceProtectedDataDir;
- /** @removed */
- @Deprecated
- public String deviceEncryptedDataDir;
-
/**
* Full path to the credential-protected directory assigned to the package
* for its persistent data.
@@ -733,10 +729,6 @@
@SystemApi
public String credentialProtectedDataDir;
- /** @removed */
- @Deprecated
- public String credentialEncryptedDataDir;
-
/**
* Full path to the directory where native JNI libraries are stored.
*/
@@ -1140,8 +1132,8 @@
seInfoUser = orig.seInfoUser;
sharedLibraryFiles = orig.sharedLibraryFiles;
dataDir = orig.dataDir;
- deviceEncryptedDataDir = deviceProtectedDataDir = orig.deviceProtectedDataDir;
- credentialEncryptedDataDir = credentialProtectedDataDir = orig.credentialProtectedDataDir;
+ deviceProtectedDataDir = orig.deviceProtectedDataDir;
+ credentialProtectedDataDir = orig.credentialProtectedDataDir;
uid = orig.uid;
minSdkVersion = orig.minSdkVersion;
targetSdkVersion = orig.targetSdkVersion;
@@ -1264,8 +1256,8 @@
seInfoUser = source.readString();
sharedLibraryFiles = source.readStringArray();
dataDir = source.readString();
- deviceEncryptedDataDir = deviceProtectedDataDir = source.readString();
- credentialEncryptedDataDir = credentialProtectedDataDir = source.readString();
+ deviceProtectedDataDir = source.readString();
+ credentialProtectedDataDir = source.readString();
uid = source.readInt();
minSdkVersion = source.readInt();
targetSdkVersion = source.readInt();
@@ -1336,10 +1328,10 @@
return;
}
- deviceEncryptedDataDir = deviceProtectedDataDir = Environment
+ deviceProtectedDataDir = Environment
.getDataUserDePackageDirectory(volumeUuid, userId, packageName)
.getAbsolutePath();
- credentialEncryptedDataDir = credentialProtectedDataDir = Environment
+ credentialProtectedDataDir = Environment
.getDataUserCePackageDirectory(volumeUuid, userId, packageName)
.getAbsolutePath();
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index c08bd1d..41311eb 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -55,7 +55,8 @@
String callingPackage, String packageName, int flags, in UserHandle user);
ParceledListSlice getShortcuts(String callingPackage, long changedSince, String packageName,
- in List shortcutIds, in ComponentName componentName, int flags, in UserHandle user);
+ in List shortcutIds, in ComponentName componentName, in Intent intent, int flags,
+ in UserHandle user);
void pinShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
in UserHandle user);
boolean startShortcut(String callingPackage, String packageName, String id,
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 11948db..147b3e1 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -211,7 +211,7 @@
inout List<ProviderInfo> outInfo);
ParceledListSlice queryContentProviders(
- String processName, int uid, int flags);
+ String processName, int uid, int flags, String metaDataKey);
InstrumentationInfo getInstrumentationInfo(
in ComponentName className, int flags);
diff --git a/core/java/android/content/pm/IPinItemRequest.aidl b/core/java/android/content/pm/IPinItemRequest.aidl
index efe2835..eddce58 100644
--- a/core/java/android/content/pm/IPinItemRequest.aidl
+++ b/core/java/android/content/pm/IPinItemRequest.aidl
@@ -16,6 +16,8 @@
package android.content.pm;
import android.os.Bundle;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.pm.ShortcutInfo;
/**
* {@hide}
@@ -23,4 +25,6 @@
interface IPinItemRequest {
boolean isValid();
boolean accept(in Bundle options);
+ ShortcutInfo getShortcutInfo();
+ AppWidgetProviderInfo getAppWidgetProviderInfo();
}
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 0866af2..776492a 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -275,7 +275,18 @@
@Deprecated
public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;
- /** @hide */
+ /**
+ * Include chooser shortcuts in the result.
+ * STOPSHIP TODO: Unless explicitly requesting chooser fields, we should strip out chooser
+ * relevant fields from the Shortcut. This should also be adequately documented.
+ */
+ public static final int FLAG_MATCH_CHOOSER = 1 << 4;
+
+ /**
+ * Does not retrieve CHOOSER only shortcuts.
+ * TODO: Add another flag for MATCH_ALL_PINNED
+ * @hide
+ */
public static final int FLAG_MATCH_ALL_KINDS =
FLAG_GET_DYNAMIC | FLAG_GET_PINNED | FLAG_GET_MANIFEST;
@@ -308,6 +319,7 @@
FLAG_MATCH_DYNAMIC,
FLAG_MATCH_PINNED,
FLAG_MATCH_MANIFEST,
+ FLAG_MATCH_CHOOSER,
FLAG_GET_KEY_FIELDS_ONLY,
})
@Retention(RetentionPolicy.SOURCE)
@@ -324,6 +336,9 @@
@Nullable
ComponentName mActivity;
+ @Nullable
+ Intent mIntent;
+
@QueryFlags
int mQueryFlags;
@@ -368,6 +383,14 @@
}
/**
+ * If non-null, returns only shortcuts with intent filters that match this intent.
+ */
+ public ShortcutQuery setIntent(@Nullable Intent intent) {
+ mIntent = intent;
+ return this;
+ }
+
+ /**
* Set query options. At least one of the {@code MATCH} flags should be set. Otherwise,
* no shortcuts will be returned.
*
@@ -681,7 +704,7 @@
try {
return mService.getShortcuts(mContext.getPackageName(),
query.mChangedSince, query.mPackage, query.mShortcutIds, query.mActivity,
- query.mQueryFlags, user)
+ query.mIntent, query.mQueryFlags, user)
.getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -1291,28 +1314,14 @@
public @interface RequestType {}
private final int mRequestType;
- private final ShortcutInfo mShortcutInfo;
- private final AppWidgetProviderInfo mAppWidgetInfo;
private final IPinItemRequest mInner;
/**
* @hide
*/
- public PinItemRequest(ShortcutInfo shortcutInfo, IPinItemRequest inner) {
- mRequestType = REQUEST_TYPE_SHORTCUT;
- mShortcutInfo = shortcutInfo;
- mAppWidgetInfo = null;
+ public PinItemRequest(IPinItemRequest inner, int type) {
mInner = inner;
- }
-
- /**
- * @hide
- */
- public PinItemRequest(AppWidgetProviderInfo appWidgetInfo, IPinItemRequest inner) {
- mRequestType = REQUEST_TYPE_APPWIDGET;
- mShortcutInfo = null;
- mAppWidgetInfo = appWidgetInfo;
- mInner = inner;
+ mRequestType = type;
}
/**
@@ -1330,7 +1339,11 @@
*/
@Nullable
public ShortcutInfo getShortcutInfo() {
- return mShortcutInfo;
+ try {
+ return mInner.getShortcutInfo();
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
}
/**
@@ -1339,12 +1352,16 @@
*/
@Nullable
public AppWidgetProviderInfo getAppWidgetProviderInfo(Context context) {
- if (mAppWidgetInfo != null) {
- AppWidgetProviderInfo info = mAppWidgetInfo.clone();
+ try {
+ final AppWidgetProviderInfo info = mInner.getAppWidgetProviderInfo();
+ if (info == null) {
+ return null;
+ }
info.updateDimensions(context.getResources().getDisplayMetrics());
return info;
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
}
- return null;
}
/**
@@ -1381,22 +1398,12 @@
final ClassLoader cl = getClass().getClassLoader();
mRequestType = source.readInt();
- mShortcutInfo = mRequestType == REQUEST_TYPE_SHORTCUT ?
- (ShortcutInfo) source.readParcelable(cl) : null;
- mAppWidgetInfo = mRequestType == REQUEST_TYPE_APPWIDGET ?
- (AppWidgetProviderInfo) source.readParcelable(cl) : null;
mInner = IPinItemRequest.Stub.asInterface(source.readStrongBinder());
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mRequestType);
- if (mRequestType == REQUEST_TYPE_SHORTCUT) {
- dest.writeParcelable(mShortcutInfo, flags);
- }
- if (mRequestType == REQUEST_TYPE_APPWIDGET) {
- dest.writeParcelable(mAppWidgetInfo, flags);
- }
dest.writeStrongBinder(mInner.asBinder());
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 5733982..0482f51 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -411,17 +411,6 @@
*/
public static final int MATCH_DIRECT_BOOT_AWARE = 0x00080000;
- /** @removed */
- @Deprecated
- public static final int MATCH_ENCRYPTION_UNAWARE = 0x00040000;
- /** @removed */
- @Deprecated
- public static final int MATCH_ENCRYPTION_AWARE = 0x00080000;
- /** @removed */
- @Deprecated
- public static final int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = MATCH_ENCRYPTION_AWARE
- | MATCH_ENCRYPTION_UNAWARE;
-
/**
* Querying flag: include only components from applications that are marked
* with {@link ApplicationInfo#FLAG_SYSTEM}.
@@ -624,8 +613,10 @@
* should be installed as forward locked, i.e. only the app itself should
* have access to its code and non-resource assets.
*
+ * @deprecated new installs into ASEC containers are no longer supported.
* @hide
*/
+ @Deprecated
public static final int INSTALL_FORWARD_LOCK = 0x00000001;
/**
@@ -648,8 +639,11 @@
* Flag parameter for {@link #installPackage} to indicate that this package
* must be installed to an ASEC on a {@link VolumeInfo#TYPE_PUBLIC}.
*
+ * @deprecated new installs into ASEC containers are no longer supported;
+ * use adoptable storage instead.
* @hide
*/
+ @Deprecated
public static final int INSTALL_EXTERNAL = 0x00000008;
/**
@@ -4468,6 +4462,27 @@
String processName, int uid, @ComponentInfoFlags int flags);
/**
+ * Same as {@link #queryContentProviders}, except when {@code metaDataKey} is not null,
+ * it only returns providers which have metadata with the {@code metaDataKey} key.
+ *
+ * <p>DO NOT USE the {@code metaDataKey} parameter, unless you're the contacts provider.
+ * You really shouldn't need it. Other apps should use {@link #queryIntentContentProviders}
+ * instead.
+ *
+ * <p>The {@code metaDataKey} parameter was added to allow the contacts provider to quickly
+ * scan the GAL providers on the device. Unfortunately the discovery protocol used metadata
+ * to mark GAL providers, rather than intent filters, so we can't use
+ * {@link #queryIntentContentProviders} for that.
+ *
+ * @hide
+ */
+ public List<ProviderInfo> queryContentProviders(
+ String processName, int uid, @ComponentInfoFlags int flags, String metaDataKey) {
+ // Provide the default implementation for mocks.
+ return queryContentProviders(processName, uid, flags);
+ }
+
+ /**
* Retrieve all of the information we know about a particular
* instrumentation class.
*
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index f1f2683..d3d3c66 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -21,8 +21,10 @@
import android.annotation.UserIdInt;
import android.app.TaskStackBuilder;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
@@ -38,10 +40,12 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -95,6 +99,14 @@
public static final int FLAG_MASKABLE_BITMAP = 1 << 9;
/** @hide */
+ public static final int FLAG_CHOOSER = 1 << 10;
+
+ /**
+ * TODO: Add FLAG_CHOOSER_INFO_OMITTED to reflect that chooser info was omitted in the Shortcut
+ * due to the context in which it was retrieved.
+ * TODO: Add a FLAG_LAUNCHABLE to reflect whether or not the Shortcut has a launchable intent
+ * @hide
+ */
@IntDef(flag = true,
value = {
FLAG_DYNAMIC,
@@ -107,6 +119,7 @@
FLAG_STRINGS_RESOLVED,
FLAG_IMMUTABLE,
FLAG_MASKABLE_BITMAP,
+ FLAG_CHOOSER,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ShortcutFlags {}
@@ -201,6 +214,24 @@
@Nullable
private PersistableBundle[] mIntentPersistableExtrases;
+ /**
+ * If used in a chooser, extras that should be added into the intent passed through.
+ */
+ @Nullable
+ private PersistableBundle mChooserExtras;
+
+ /**
+ * Intent filters to be used if the shortcut is to be used in a chooser context.
+ */
+ @Nullable
+ private IntentFilter[] mChooserIntentFilters;
+
+ /**
+ * Component names corresponding to the above intent filters.
+ */
+ @Nullable
+ private ComponentName[] mChooserComponentNames;
+
private int mRank;
/**
@@ -250,6 +281,13 @@
mDisabledMessageResId = b.mDisabledMessageResId;
mCategories = cloneCategories(b.mCategories);
mIntents = cloneIntents(b.mIntents);
+ if (b.mChooserIntentFilters != null) {
+ mChooserIntentFilters = b.mChooserIntentFilters.toArray(new IntentFilter[0]);
+ }
+ if (b.mChooserComponentNames != null) {
+ mChooserComponentNames = b.mChooserComponentNames.toArray(new ComponentName[0]);
+ }
+ mChooserExtras = b.mChooserExtras;
fixUpIntentExtras();
mRank = b.mRank;
mExtras = b.mExtras;
@@ -330,8 +368,28 @@
if (mTitle == null && mTitleResId == 0) {
throw new IllegalArgumentException("Short label must be provided");
}
- Preconditions.checkNotNull(mIntents, "Shortcut Intent must be provided");
- Preconditions.checkArgument(mIntents.length > 0, "Shortcut Intent must be provided");
+
+ // For a shortcut to be valid, there should either be an Intent, or a non-empty set of
+ // intent filters.
+ if (mIntents == null || mIntents.length == 0) {
+ Preconditions.checkNotNull(mChooserIntentFilters,
+ "Intent must be provided if not a chooser target");
+ Preconditions.checkNotNull(mChooserComponentNames,
+ "Intent must be provided if not a chooser target");
+ }
+
+ // If ChooserIntentFilter are provided, they should match the length of the provided
+ // component names.
+ if (mChooserIntentFilters != null) {
+ if (mChooserComponentNames == null
+ || mChooserIntentFilters.length != mChooserComponentNames.length) {
+ throw new IllegalArgumentException("Inconsistent intent filters and "
+ + "component names given");
+ }
+ if (mChooserIntentFilters.length == 0 || mChooserComponentNames.length == 0) {
+ throw new IllegalArgumentException("Empty intent filter and component names given");
+ }
+ }
}
/**
@@ -376,6 +434,10 @@
mDisabledMessageResName = source.mDisabledMessageResName;
mIconResName = source.mIconResName;
}
+ // TODO: Omit these by default and add a new clone flag.
+ mChooserIntentFilters = source.mChooserIntentFilters;
+ mChooserComponentNames = source.mChooserComponentNames;
+ mChooserExtras = source.mChooserExtras;
} else {
// Set this bit.
mFlags |= FLAG_KEY_FIELDS_ONLY;
@@ -503,6 +565,25 @@
}
/**
+ * Whether the shortcut has any intentFilter matching the passed in one.
+ * @hide
+ */
+ @VisibleForTesting
+ public boolean hasMatchingFilter(ContentResolver resolver, Intent intent) {
+ if (mChooserIntentFilters == null) {
+ return false;
+ }
+ for (IntentFilter filter : mChooserIntentFilters) {
+ int match = filter.match(resolver, intent, false, TAG);
+ if (match > 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /**
* Extract the entry name from a fully-donated resource name.
* e.g. "com.android.app1:drawable/icon1" -> "icon1"
* @hide
@@ -685,6 +766,15 @@
if (source.mExtras != null) {
mExtras = source.mExtras;
}
+ if (source.mChooserExtras != null) {
+ mChooserExtras = source.mChooserExtras;
+ }
+ if (source.mChooserIntentFilters != null) {
+ mChooserIntentFilters = source.mChooserIntentFilters;
+ }
+ if (source.mChooserComponentNames != null) {
+ mChooserComponentNames = source.mChooserComponentNames;
+ }
}
/**
@@ -746,6 +836,12 @@
private PersistableBundle mExtras;
+ private PersistableBundle mChooserExtras;
+
+ private List<IntentFilter> mChooserIntentFilters;
+
+ private List<ComponentName> mChooserComponentNames;
+
/**
* Old style constructor.
* @hide
@@ -1032,6 +1128,40 @@
}
/**
+ * Extras that can be added which will be added to the Intent used to launch the app if
+ * launched from a chooser context.
+ */
+ @NonNull
+ public Builder setChooserExtras(@NonNull PersistableBundle extras) {
+ mChooserExtras = extras;
+ return this;
+ }
+
+ /**
+ * IntentFilters and the components that should resolve a match for a given chooser target.
+ * If multiple matches are found, the component corresponding to the closest match will be
+ * used.
+ *
+ * @param filter IntendFilter that if matched will have the intent forwarded to the given
+ * component
+ * @param name The component that an intent that passes this filter will resolve to.
+ */
+ public Builder addChooserIntentFilter(@NonNull IntentFilter filter,
+ @NonNull ComponentName name) {
+ Preconditions.checkNotNull(filter, "intent filter cannot be null");
+ Preconditions.checkNotNull(name, "component name cannot be null");
+
+ if (mChooserIntentFilters == null || mChooserComponentNames == null) {
+ mChooserIntentFilters = new ArrayList<>();
+ mChooserComponentNames = new ArrayList<>();
+ }
+
+ mChooserIntentFilters.add(filter);
+ mChooserComponentNames.add(name);
+ return this;
+ }
+
+ /**
* Creates a {@link ShortcutInfo} instance.
*/
@NonNull
@@ -1232,6 +1362,30 @@
}
/**
+ * Retrieve the extras that will be added in to any intent launched through the chooser.
+ */
+ @NonNull
+ public PersistableBundle getChooserExtras() {
+ return mChooserExtras;
+ }
+
+ /**
+ * Retrieve the list of intent filters for chooser targets.
+ */
+ @NonNull
+ public IntentFilter[] getChooserIntentFilters() {
+ return mChooserIntentFilters;
+ }
+
+ /**
+ * Retrieve the list of component names corresponding to the above intent filters.
+ */
+ @NonNull
+ public ComponentName[] getChooserComponentNames() {
+ return mChooserComponentNames;
+ }
+
+ /**
* "Rank" of a shortcut, which is a non-negative, sequential value that's unique for each
* {@link #getActivity} for each of the two types of shortcuts (static and dynamic).
*
@@ -1352,6 +1506,11 @@
return hasFlags(FLAG_PINNED);
}
+ /** Return whether a shortcut can be shown in the chooser. */
+ public boolean isChooser() {
+ return hasFlags(FLAG_CHOOSER);
+ }
+
/**
* Return whether a shortcut is static; that is, whether a shortcut is
* published from AndroidManifest.xml. If {@code true}, the shortcut is
@@ -1380,6 +1539,14 @@
return isPinned() && !(isDynamic() || isManifestShortcut());
}
+ /**
+ * @return true if pinned but neither static nor dynamic.
+ * @hide
+ */
+ public boolean isDynamicOrChooser() {
+ return hasFlags(FLAG_DYNAMIC) || hasFlags(FLAG_CHOOSER);
+ }
+
/** @hide */
public boolean isOriginallyFromManifest() {
return hasFlags(FLAG_IMMUTABLE);
@@ -1661,6 +1828,19 @@
mCategories.add(source.readString().intern());
}
}
+
+ // We put a placeholder empty array in to keep the parcelable order, but can do away with
+ // them at this point if they're empty.
+ mChooserComponentNames = source.readParcelableArray(cl, ComponentName.class);
+ if (mChooserComponentNames.length == 0) {
+ mChooserComponentNames = null;
+ }
+
+ mChooserIntentFilters = source.readParcelableArray(cl, IntentFilter.class);
+ if (mChooserIntentFilters.length == 0) {
+ mChooserIntentFilters = null;
+ }
+ mChooserExtras = source.readPersistableBundle(cl);
}
@Override
@@ -1707,6 +1887,17 @@
} else {
dest.writeInt(0);
}
+ if (mChooserComponentNames != null) {
+ dest.writeParcelableArray(mChooserComponentNames, flags);
+ } else {
+ dest.writeParcelableArray(new ComponentName[0], flags);
+ }
+ if (mChooserIntentFilters != null) {
+ dest.writeParcelableArray(mChooserIntentFilters, flags);
+ } else {
+ dest.writeParcelableArray(new IntentFilter[0], flags);
+ }
+ dest.writePersistableBundle(mChooserExtras);
}
public static final Creator<ShortcutInfo> CREATOR =
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index 87a6d4a..696fe81 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -44,8 +44,8 @@
getShortcuts(int launcherUserId,
@NonNull String callingPackage, long changedSince,
@Nullable String packageName, @Nullable List<String> shortcutIds,
- @Nullable ComponentName componentName, @ShortcutQuery.QueryFlags int flags,
- int userId);
+ @Nullable ComponentName componentName, @Nullable Intent intent,
+ @ShortcutQuery.QueryFlags int flags, int userId);
public abstract boolean
isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
diff --git a/core/java/android/content/res/CompatResources.java b/core/java/android/content/res/CompatResources.java
new file mode 100644
index 0000000..15575fd
--- /dev/null
+++ b/core/java/android/content/res/CompatResources.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package android.content.res;
+
+import android.annotation.ColorRes;
+import android.annotation.DrawableRes;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Version of resources generated for apps targeting <26.
+ * @hide
+ */
+public class CompatResources extends Resources {
+
+ private final WeakReference<Context> mContext;
+
+ public CompatResources(Resources base, Context context) {
+ super(base.getClassLoader());
+ setImpl(base.getImpl());
+ mContext = new WeakReference<>(context);
+ }
+
+ @Override
+ public Drawable getDrawable(@DrawableRes int id) throws NotFoundException {
+ return getDrawable(id, getTheme());
+ }
+
+ @Override
+ public Drawable getDrawableForDensity(@DrawableRes int id, int density)
+ throws NotFoundException {
+ return getDrawableForDensity(id, density, getTheme());
+ }
+
+ @Override
+ public int getColor(@ColorRes int id) throws NotFoundException {
+ return getColor(id, getTheme());
+ }
+
+ @Override
+ public ColorStateList getColorStateList(@ColorRes int id) throws NotFoundException {
+ return getColorStateList(id, getTheme());
+ }
+
+ private Theme getTheme() {
+ Context c = mContext.get();
+ return c != null ? c.getTheme() : null;
+ }
+}
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
index f249daf..362ea9d 100644
--- a/core/java/android/net/INetworkScoreService.aidl
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -18,7 +18,7 @@
import android.net.INetworkScoreCache;
import android.net.NetworkKey;
-import android.net.NetworkScorerAppManager;
+import android.net.NetworkScorerAppData;
import android.net.RecommendationRequest;
import android.net.RecommendationResult;
import android.net.ScoredNetwork;
@@ -135,11 +135,11 @@
/**
* Returns metadata about the active scorer or <code>null</code> if there is no active scorer.
*/
- NetworkScorerAppManager.NetworkScorerAppData getActiveScorer();
+ NetworkScorerAppData getActiveScorer();
/**
* Returns the list of available scorer apps. The list will be empty if there are
* no valid scorers.
*/
- List<NetworkScorerAppManager.NetworkScorerAppData> getAllValidScorers();
+ List<NetworkScorerAppData> getAllValidScorers();
}
diff --git a/core/java/android/net/NetworkRecommendationProvider.java b/core/java/android/net/NetworkRecommendationProvider.java
index 8395864..271b0a7 100644
--- a/core/java/android/net/NetworkRecommendationProvider.java
+++ b/core/java/android/net/NetworkRecommendationProvider.java
@@ -1,6 +1,8 @@
package android.net;
+import android.Manifest.permission;
import android.annotation.SystemApi;
+import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -10,8 +12,10 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
import java.util.Objects;
+import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -32,6 +36,7 @@
/**
* Constructs a new instance.
* @param handler indicates which thread to use when handling requests. Cannot be {@code null}.
+ * @deprecated use {@link #NetworkRecommendationProvider(Context, Executor)}
*/
public NetworkRecommendationProvider(Handler handler) {
if (handler == null) {
@@ -41,6 +46,17 @@
}
/**
+ * Constructs a new instance.
+ * @param context the current context instance. Cannot be {@code null}.
+ * @param executor used to execute the incoming requests. Cannot be {@code null}.
+ */
+ public NetworkRecommendationProvider(Context context, Executor executor) {
+ Preconditions.checkNotNull(context);
+ Preconditions.checkNotNull(executor);
+ mService = new ServiceWrapper(context, executor);
+ }
+
+ /**
* Invoked when a recommendation has been requested.
*
* @param request a {@link RecommendationRequest} instance containing additional
@@ -130,17 +146,28 @@
* A wrapper around INetworkRecommendationProvider that dispatches to the provided Handler.
*/
private final class ServiceWrapper extends INetworkRecommendationProvider.Stub {
+ private final Context mContext;
+ private final Executor mExecutor;
private final Handler mHandler;
ServiceWrapper(Handler handler) {
mHandler = handler;
+ mExecutor = null;
+ mContext = null;
+ }
+
+ ServiceWrapper(Context context, Executor executor) {
+ mContext = context;
+ mExecutor = executor;
+ mHandler = null;
}
@Override
public void requestRecommendation(final RecommendationRequest request,
final IRemoteCallback callback, final int sequence) throws RemoteException {
+ enforceCallingPermission();
if (VERBOSE) Log.v(TAG, "requestRecommendation(seq=" + sequence + ")");
- mHandler.post(new Runnable() {
+ execute(new Runnable() {
@Override
public void run() {
if (VERBOSE) {
@@ -154,8 +181,9 @@
@Override
public void requestScores(final NetworkKey[] networks) throws RemoteException {
+ enforceCallingPermission();
if (networks != null && networks.length > 0) {
- mHandler.post(new Runnable() {
+ execute(new Runnable() {
@Override
public void run() {
onRequestScores(networks);
@@ -163,5 +191,20 @@
});
}
}
+
+ private void execute(Runnable command) {
+ if (mExecutor != null) {
+ mExecutor.execute(command);
+ } else {
+ mHandler.post(command);
+ }
+ }
+
+ private void enforceCallingPermission() {
+ if (mContext != null) {
+ mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES,
+ "Permission denied.");
+ }
+ }
}
}
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index edfaee4..815d480 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -18,7 +18,6 @@
import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT;
-import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -26,7 +25,6 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.content.Context;
-import android.net.NetworkScorerAppManager.NetworkScorerAppData;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteCallback;
diff --git a/core/java/android/net/NetworkScorerAppManager.aidl b/core/java/android/net/NetworkScorerAppData.aidl
similarity index 91%
rename from core/java/android/net/NetworkScorerAppManager.aidl
rename to core/java/android/net/NetworkScorerAppData.aidl
index d968343..ee7f1d1 100644
--- a/core/java/android/net/NetworkScorerAppManager.aidl
+++ b/core/java/android/net/NetworkScorerAppData.aidl
@@ -16,4 +16,4 @@
package android.net;
-parcelable NetworkScorerAppManager.NetworkScorerAppData;
+parcelable NetworkScorerAppData;
diff --git a/core/java/android/net/NetworkScorerAppData.java b/core/java/android/net/NetworkScorerAppData.java
new file mode 100644
index 0000000..fca0a2e
--- /dev/null
+++ b/core/java/android/net/NetworkScorerAppData.java
@@ -0,0 +1,99 @@
+package android.net;
+
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Holds metadata about a discovered network scorer/recommendation application.
+ *
+ * @hide
+ */
+public final class NetworkScorerAppData implements Parcelable {
+ /** UID of the scorer app. */
+ public final int packageUid;
+ private final ComponentName mRecommendationService;
+ /**
+ * The {@link ComponentName} of the Activity to start before enabling the "connect to open
+ * wifi networks automatically" feature.
+ */
+ private final ComponentName mEnableUseOpenWifiActivity;
+
+ public NetworkScorerAppData(int packageUid, ComponentName recommendationServiceComp,
+ ComponentName enableUseOpenWifiActivity) {
+ this.packageUid = packageUid;
+ this.mRecommendationService = recommendationServiceComp;
+ this.mEnableUseOpenWifiActivity = enableUseOpenWifiActivity;
+ }
+
+ protected NetworkScorerAppData(Parcel in) {
+ packageUid = in.readInt();
+ mRecommendationService = ComponentName.readFromParcel(in);
+ mEnableUseOpenWifiActivity = ComponentName.readFromParcel(in);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(packageUid);
+ ComponentName.writeToParcel(mRecommendationService, dest);
+ ComponentName.writeToParcel(mEnableUseOpenWifiActivity, dest);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<NetworkScorerAppData> CREATOR =
+ new Creator<NetworkScorerAppData>() {
+ @Override
+ public NetworkScorerAppData createFromParcel(Parcel in) {
+ return new NetworkScorerAppData(in);
+ }
+
+ @Override
+ public NetworkScorerAppData[] newArray(int size) {
+ return new NetworkScorerAppData[size];
+ }
+ };
+
+ public String getRecommendationServicePackageName() {
+ return mRecommendationService.getPackageName();
+ }
+
+ public ComponentName getRecommendationServiceComponent() {
+ return mRecommendationService;
+ }
+
+ @Nullable
+ public ComponentName getEnableUseOpenWifiActivity() {
+ return mEnableUseOpenWifiActivity;
+ }
+
+ @Override
+ public String toString() {
+ return "NetworkScorerAppData{" +
+ "packageUid=" + packageUid +
+ ", mRecommendationService=" + mRecommendationService +
+ ", mEnableUseOpenWifiActivity=" + mEnableUseOpenWifiActivity +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ NetworkScorerAppData that = (NetworkScorerAppData) o;
+ return packageUid == that.packageUid &&
+ Objects.equals(mRecommendationService, that.mRecommendationService) &&
+ Objects.equals(mEnableUseOpenWifiActivity, that.mEnableUseOpenWifiActivity);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(packageUid, mRecommendationService, mEnableUseOpenWifiActivity);
+ }
+}
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
deleted file mode 100644
index bbc1c79..0000000
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright (C) 2014 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.net;
-
-import android.Manifest.permission;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.content.pm.ServiceInfo;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Internal class for discovering and managing the network scorer/recommendation application.
- *
- * @hide
- */
-public class NetworkScorerAppManager {
- private static final String TAG = "NetworkScorerAppManager";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
- private final Context mContext;
-
- public NetworkScorerAppManager(Context context) {
- mContext = context;
- }
-
- /**
- * Holds metadata about a discovered network scorer/recommendation application.
- */
- public static final class NetworkScorerAppData implements Parcelable {
- /** UID of the scorer app. */
- public final int packageUid;
- private final ComponentName mRecommendationService;
- /**
- * The {@link ComponentName} of the Activity to start before enabling the "connect to open
- * wifi networks automatically" feature.
- */
- private final ComponentName mEnableUseOpenWifiActivity;
-
- public NetworkScorerAppData(int packageUid, ComponentName recommendationServiceComp,
- ComponentName enableUseOpenWifiActivity) {
- this.packageUid = packageUid;
- this.mRecommendationService = recommendationServiceComp;
- this.mEnableUseOpenWifiActivity = enableUseOpenWifiActivity;
- }
-
- protected NetworkScorerAppData(Parcel in) {
- packageUid = in.readInt();
- mRecommendationService = ComponentName.readFromParcel(in);
- mEnableUseOpenWifiActivity = ComponentName.readFromParcel(in);
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(packageUid);
- ComponentName.writeToParcel(mRecommendationService, dest);
- ComponentName.writeToParcel(mEnableUseOpenWifiActivity, dest);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Creator<NetworkScorerAppData> CREATOR =
- new Creator<NetworkScorerAppData>() {
- @Override
- public NetworkScorerAppData createFromParcel(Parcel in) {
- return new NetworkScorerAppData(in);
- }
-
- @Override
- public NetworkScorerAppData[] newArray(int size) {
- return new NetworkScorerAppData[size];
- }
- };
-
- public String getRecommendationServicePackageName() {
- return mRecommendationService.getPackageName();
- }
-
- public ComponentName getRecommendationServiceComponent() {
- return mRecommendationService;
- }
-
- @Nullable public ComponentName getEnableUseOpenWifiActivity() {
- return mEnableUseOpenWifiActivity;
- }
-
- @Override
- public String toString() {
- return "NetworkScorerAppData{" +
- "packageUid=" + packageUid +
- ", mRecommendationService=" + mRecommendationService +
- ", mEnableUseOpenWifiActivity=" + mEnableUseOpenWifiActivity +
- '}';
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- NetworkScorerAppData that = (NetworkScorerAppData) o;
- return packageUid == that.packageUid &&
- Objects.equals(mRecommendationService, that.mRecommendationService) &&
- Objects.equals(mEnableUseOpenWifiActivity, that.mEnableUseOpenWifiActivity);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(packageUid, mRecommendationService, mEnableUseOpenWifiActivity);
- }
- }
-
- /**
- * Returns the list of available scorer apps. The list will be empty if there are
- * no valid scorers.
- */
- public List<NetworkScorerAppData> getAllValidScorers() {
- return Collections.emptyList();
- }
-
- /**
- * @return A {@link NetworkScorerAppData} instance containing information about the
- * best configured network recommendation provider installed or {@code null}
- * if none of the configured packages can recommend networks.
- *
- * <p>A network recommendation provider is any application which:
- * <ul>
- * <li>Is listed in the <code>config_networkRecommendationPackageNames</code> config.
- * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
- * <li>Includes a Service for {@link NetworkScoreManager#ACTION_RECOMMEND_NETWORKS}.
- * </ul>
- */
- public NetworkScorerAppData getNetworkRecommendationProviderData() {
- // Network recommendation apps can only run as the primary user right now.
- // http://b/23422763
- if (UserHandle.getCallingUserId() != UserHandle.USER_SYSTEM) {
- return null;
- }
-
- final List<String> potentialPkgs = getPotentialRecommendationProviderPackages();
- if (potentialPkgs.isEmpty()) {
- if (DEBUG) {
- Log.d(TAG, "No Network Recommendation Providers specified.");
- }
- return null;
- }
-
- for (int i = 0; i < potentialPkgs.size(); i++) {
- final String potentialPkg = potentialPkgs.get(i);
-
- // Look for the recommendation service class and required receiver.
- final ServiceInfo serviceInfo = findRecommendationService(potentialPkg);
- if (serviceInfo != null) {
- final ComponentName serviceComponentName =
- new ComponentName(potentialPkg, serviceInfo.name);
- final ComponentName useOpenWifiNetworksActivity =
- findUseOpenWifiNetworksActivity(serviceInfo);
- return new NetworkScorerAppData(serviceInfo.applicationInfo.uid,
- serviceComponentName, useOpenWifiNetworksActivity);
- } else {
- if (DEBUG) {
- Log.d(TAG, potentialPkg + " does not have the required components, skipping.");
- }
- }
- }
-
- // None of the configured packages are valid.
- return null;
- }
-
- @Nullable private ComponentName findUseOpenWifiNetworksActivity(ServiceInfo serviceInfo) {
- if (serviceInfo.metaData == null) {
- if (DEBUG) {
- Log.d(TAG, "No metadata found on recommendation service.");
- }
- return null;
- }
- final String useOpenWifiPackage = serviceInfo.metaData
- .getString(NetworkScoreManager.USE_OPEN_WIFI_PACKAGE_META_DATA);
- if (TextUtils.isEmpty(useOpenWifiPackage)) {
- if (DEBUG) {
- Log.d(TAG, "No use_open_wifi_package metadata found.");
- }
- return null;
- }
- final Intent enableUseOpenWifiIntent = new Intent(NetworkScoreManager.ACTION_CUSTOM_ENABLE)
- .setPackage(useOpenWifiPackage);
- final ResolveInfo resolveActivityInfo = mContext.getPackageManager()
- .resolveActivity(enableUseOpenWifiIntent, 0 /* flags */);
- if (VERBOSE) {
- Log.d(TAG, "Resolved " + enableUseOpenWifiIntent + " to " + serviceInfo);
- }
-
- if (resolveActivityInfo != null && resolveActivityInfo.activityInfo != null) {
- return resolveActivityInfo.activityInfo.getComponentName();
- }
-
- return null;
- }
-
- /**
- * @return A priority order list of package names that have been granted the
- * permission needed for them to act as a network recommendation provider.
- * The packages in the returned list may not contain the other required
- * network recommendation provider components so additional checks are required
- * before making a package the network recommendation provider.
- */
- public List<String> getPotentialRecommendationProviderPackages() {
- final String[] packageArray = mContext.getResources().getStringArray(
- R.array.config_networkRecommendationPackageNames);
- if (packageArray == null || packageArray.length == 0) {
- if (DEBUG) {
- Log.d(TAG, "No Network Recommendation Providers specified.");
- }
- return Collections.emptyList();
- }
-
- if (VERBOSE) {
- Log.d(TAG, "Configured packages: " + TextUtils.join(", ", packageArray));
- }
-
- List<String> packages = new ArrayList<>();
- final PackageManager pm = mContext.getPackageManager();
- for (String potentialPkg : packageArray) {
- if (pm.checkPermission(permission.SCORE_NETWORKS, potentialPkg)
- == PackageManager.PERMISSION_GRANTED) {
- packages.add(potentialPkg);
- } else {
- if (DEBUG) {
- Log.d(TAG, potentialPkg + " has not been granted " + permission.SCORE_NETWORKS
- + ", skipping.");
- }
- }
- }
-
- return packages;
- }
-
- @Nullable private ServiceInfo findRecommendationService(String packageName) {
- final PackageManager pm = mContext.getPackageManager();
- final int resolveFlags = PackageManager.GET_META_DATA;
- final Intent serviceIntent = new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS);
- serviceIntent.setPackage(packageName);
- final ResolveInfo resolveServiceInfo =
- pm.resolveService(serviceIntent, resolveFlags);
-
- if (VERBOSE) {
- Log.d(TAG, "Resolved " + serviceIntent + " to " + resolveServiceInfo);
- }
-
- if (resolveServiceInfo != null && resolveServiceInfo.serviceInfo != null) {
- return resolveServiceInfo.serviceInfo;
- }
-
- if (VERBOSE) {
- Log.v(TAG, packageName + " does not have a service for " + serviceIntent);
- }
- return null;
- }
-
- /**
- * Get the application to use for scoring networks.
- *
- * @return the scorer app info or null if scoring is disabled (including if no scorer was ever
- * selected) or if the previously-set scorer is no longer a valid scorer app (e.g. because
- * it was disabled or uninstalled).
- */
- @Nullable
- public NetworkScorerAppData getActiveScorer() {
- if (isNetworkRecommendationsDisabled()) {
- // If recommendations are disabled then there can't be an active scorer.
- return null;
- }
-
- // Otherwise return the recommendation provider (which may be null).
- return getNetworkRecommendationProviderData();
- }
-
- /**
- * Set the specified package as the default scorer application.
- *
- * <p>The caller must have permission to write to {@link android.provider.Settings.Global}.
- *
- * @param packageName the packageName of the new scorer to use. If null, scoring will be
- * disabled. Otherwise, the scorer will only be set if it is a valid scorer application.
- * @return true if the scorer was changed, or false if the package is not a valid scorer or
- * a valid network recommendation provider exists.
- * @deprecated Scorers are now selected from a configured list.
- */
- @Deprecated
- public boolean setActiveScorer(String packageName) {
- return false;
- }
-
- private boolean isNetworkRecommendationsDisabled() {
- final ContentResolver cr = mContext.getContentResolver();
- // A value of 1 indicates enabled.
- return Settings.Global.getInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0) != 1;
- }
-}
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 3a441c7..9ffe2fe 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -118,6 +118,13 @@
*/
public static final String EXTRA_CHARGE_COUNTER = "charge_counter";
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * Current int sequence number of the update.
+ * {@hide}
+ */
+ public static final String EXTRA_SEQUENCE = "seq";
+
// values for "status" field in the ACTION_BATTERY_CHANGED Intent
public static final int BATTERY_STATUS_UNKNOWN = Constants.BATTERY_STATUS_UNKNOWN;
public static final int BATTERY_STATUS_CHARGING = Constants.BATTERY_STATUS_CHARGING;
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index d299672..63d3e7a 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -18,8 +18,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.LooperProto;
import android.util.Log;
import android.util.Printer;
+import android.util.proto.ProtoOutputStream;
/**
* Class used to run a message loop for a thread. Threads by default do
@@ -289,6 +291,16 @@
mQueue.dump(pw, prefix + " ");
}
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long looperToken = proto.start(fieldId);
+ proto.write(LooperProto.THREAD_NAME, mThread.getName());
+ proto.write(LooperProto.THREAD_ID, mThread.getId());
+ proto.write(LooperProto.IDENTITY_HASH_CODE, System.identityHashCode(this));
+ mQueue.writeToProto(proto, LooperProto.QUEUE);
+ proto.end(looperToken);
+ }
+
@Override
public String toString() {
return "Looper (" + mThread.getName() + ", tid " + mThread.getId()
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 8c75847..d066db1 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -16,13 +16,15 @@
package android.os;
+import android.os.MessageProto;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
/**
- *
+ *
* Defines a message containing a description and arbitrary data object that can be
* sent to a {@link Handler}. This object contains two extra int fields and an
- * extra object field that allow you to not do allocations in many cases.
+ * extra object field that allow you to not do allocations in many cases.
*
* <p class="note">While the constructor of Message is public, the best way to get
* one of these is to call {@link #obtain Message.obtain()} or one of the
@@ -31,7 +33,7 @@
*/
public final class Message implements Parcelable {
/**
- * User-defined message code so that the recipient can identify
+ * User-defined message code so that the recipient can identify
* what this message is about. Each {@link Handler} has its own name-space
* for message codes, so you do not need to worry about yours conflicting
* with other handlers.
@@ -43,7 +45,7 @@
* {@link #setData(Bundle) setData()} if you only need to store a
* few integer values.
*/
- public int arg1;
+ public int arg1;
/**
* arg1 and arg2 are lower-cost alternatives to using
@@ -58,7 +60,7 @@
* be non-null if it contains a Parcelable of a framework class (not one
* implemented by the application). For other data transfer use
* {@link #setData}.
- *
+ *
* <p>Note that Parcelable objects here are not supported prior to
* the {@link android.os.Build.VERSION_CODES#FROYO} release.
*/
@@ -97,13 +99,13 @@
/*package*/ int flags;
/*package*/ long when;
-
+
/*package*/ Bundle data;
-
+
/*package*/ Handler target;
-
+
/*package*/ Runnable callback;
-
+
// sometimes we store linked lists of these things
/*package*/ Message next;
@@ -216,9 +218,9 @@
}
/**
- * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
+ * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
* <em>arg1</em>, and <em>arg2</em> members.
- *
+ *
* @param h The <em>target</em> value to set.
* @param what The <em>what</em> value to set.
* @param arg1 The <em>arg1</em> value to set.
@@ -236,9 +238,9 @@
}
/**
- * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
+ * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
* <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members.
- *
+ *
* @param h The <em>target</em> value to set.
* @param what The <em>what</em> value to set.
* @param arg1 The <em>arg1</em> value to set.
@@ -246,7 +248,7 @@
* @param obj The <em>obj</em> value to set.
* @return A Message object from the global pool.
*/
- public static Message obtain(Handler h, int what,
+ public static Message obtain(Handler h, int what,
int arg1, int arg2, Object obj) {
Message m = obtain();
m.target = h;
@@ -339,7 +341,7 @@
public long getWhen() {
return when;
}
-
+
public void setTarget(Handler target) {
this.target = target;
}
@@ -367,8 +369,8 @@
public Runnable getCallback() {
return callback;
}
-
- /**
+
+ /**
* Obtains a Bundle of arbitrary data associated with this
* event, lazily creating it if necessary. Set this value by calling
* {@link #setData(Bundle)}. Note that when transferring data across
@@ -383,11 +385,11 @@
if (data == null) {
data = new Bundle();
}
-
+
return data;
}
- /**
+ /**
* Like getData(), but does not lazily create the Bundle. A null
* is returned if the Bundle does not already exist. See
* {@link #getData} for further information on this.
@@ -401,7 +403,7 @@
/**
* Sets a Bundle of arbitrary data values. Use arg1 and arg2 members
* as a lower cost way to send a few simple integer values, if you can.
- * @see #getData()
+ * @see #getData()
* @see #peekData()
*/
public void setData(Bundle data) {
@@ -520,6 +522,37 @@
return b.toString();
}
+ void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long messageToken = proto.start(fieldId);
+ proto.write(MessageProto.WHEN, when);
+
+ if (target != null) {
+ if (callback != null) {
+ proto.write(MessageProto.CALLBACK, callback.getClass().getName());
+ } else {
+ proto.write(MessageProto.WHAT, what);
+ }
+
+ if (arg1 != 0) {
+ proto.write(MessageProto.ARG1, arg1);
+ }
+
+ if (arg2 != 0) {
+ proto.write(MessageProto.ARG2, arg2);
+ }
+
+ if (obj != null) {
+ proto.write(MessageProto.OBJ, obj.toString());
+ }
+
+ proto.write(MessageProto.TARGET, target.getClass().getName());
+ } else {
+ proto.write(MessageProto.BARRIER, arg1);
+ }
+
+ proto.end(messageToken);
+ }
+
public static final Parcelable.Creator<Message> CREATOR
= new Parcelable.Creator<Message>() {
public Message createFromParcel(Parcel source) {
@@ -527,12 +560,12 @@
msg.readFromParcel(source);
return msg;
}
-
+
public Message[] newArray(int size) {
return new Message[size];
}
};
-
+
public int describeContents() {
return 0;
}
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index 4f2e968..2a8c52e 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -18,9 +18,11 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.os.MessageQueueProto;
import android.util.Log;
import android.util.Printer;
import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
import java.io.FileDescriptor;
import java.lang.annotation.Retention;
@@ -31,7 +33,7 @@
* Low-level class holding the list of messages to be dispatched by a
* {@link Looper}. Messages are not added directly to a MessageQueue,
* but rather through {@link Handler} objects associated with the Looper.
- *
+ *
* <p>You can retrieve the MessageQueue for the current thread with
* {@link Looper#myQueue() Looper.myQueue()}.
*/
@@ -770,6 +772,18 @@
}
}
+ void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long messageQueueToken = proto.start(fieldId);
+ synchronized (this) {
+ for (Message msg = mMessages; msg != null; msg = msg.next) {
+ msg.writeToProto(proto, MessageQueueProto.MESSAGES);
+ }
+ proto.write(MessageQueueProto.IS_POLLING_LOCKED, isPollingLocked());
+ proto.write(MessageQueueProto.IS_QUITTING, mQuitting);
+ }
+ proto.end(messageQueueToken);
+ }
+
/**
* Callback interface for discovering when a thread is going to block
* waiting for more messages.
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 21c70f9..13a495e 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1097,40 +1097,6 @@
}
}
- /** @removed */
- @Deprecated
- public boolean isUserRunningAndLocked() {
- return isUserRunningAndLocked(Process.myUserHandle());
- }
-
- /** @removed */
- @Deprecated
- public boolean isUserRunningAndLocked(UserHandle user) {
- try {
- return ActivityManager.getService().isUserRunning(
- user.getIdentifier(), ActivityManager.FLAG_AND_LOCKED);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- }
-
- /** @removed */
- @Deprecated
- public boolean isUserRunningAndUnlocked() {
- return isUserRunningAndUnlocked(Process.myUserHandle());
- }
-
- /** @removed */
- @Deprecated
- public boolean isUserRunningAndUnlocked(UserHandle user) {
- try {
- return ActivityManager.getService().isUserRunning(
- user.getIdentifier(), ActivityManager.FLAG_AND_UNLOCKED);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- }
-
/**
* Return whether the calling user is running in an "unlocked" state.
* <p>
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index f8da87a..ecec448 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -1,6 +1,8 @@
package android.os;
+import android.os.WorkSourceProto;
import android.util.Log;
+import android.util.proto.ProtoOutputStream;
import java.util.Arrays;
@@ -296,7 +298,7 @@
break;
}
if (mUids[i] == uid) {
- int diff = mNames[i].compareTo(name);
+ int diff = mNames[i].compareTo(name);
if (diff > 0) {
break;
}
@@ -692,6 +694,20 @@
return result.toString();
}
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long workSourceToken = proto.start(fieldId);
+ for (int i = 0; i < mNum; i++) {
+ final long contentProto = proto.start(WorkSourceProto.WORK_SOURCE_CONTENTS);
+ proto.write(WorkSourceProto.WorkSourceContentProto.UID, mUids[i]);
+ if (mNames != null) {
+ proto.write(WorkSourceProto.WorkSourceContentProto.NAME, mNames[i]);
+ }
+ proto.end(contentProto);
+ }
+ proto.end(workSourceToken);
+ }
+
public static final Parcelable.Creator<WorkSource> CREATOR
= new Parcelable.Creator<WorkSource>() {
public WorkSource createFromParcel(Parcel in) {
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index a2f4db6..756c3f4 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -420,12 +420,6 @@
mSharedPreferences = null;
}
- /** @removed */
- @Deprecated
- public void setStorageDeviceEncrypted() {
- setStorageDeviceProtected();
- }
-
/**
* Explicitly set the storage location used internally by this class to be
* credential-protected storage. This is the default storage area for apps
@@ -445,12 +439,6 @@
mSharedPreferences = null;
}
- /** @removed */
- @Deprecated
- public void setStorageCredentialEncrypted() {
- setStorageCredentialProtected();
- }
-
/**
* Indicates if the storage location used internally by this class is the
* default provided by the hosting {@link Context}.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 40de928..c4a5be7 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1121,7 +1121,7 @@
public static final String ACTION_ZEN_MODE_SETTINGS = "android.settings.ZEN_MODE_SETTINGS";
/**
- * Activity Action: Show Zen Mode priority configuration settings.
+ * Activity Action: Show Zen Mode (aka Do Not Disturb) priority configuration settings.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_ZEN_MODE_PRIORITY_SETTINGS
@@ -6905,6 +6905,12 @@
public static final String PACKAGE_VERIFIER_STATE = "package_verifier_state";
/**
+ * Specifies additional package name for broadcasting the CMAS messages.
+ * @hide
+ */
+ public static final String CMAS_ADDITIONAL_BROADCAST_PKG = "cmas_additional_broadcast_pkg";
+
+ /**
* This are the settings to be backed up.
*
* NOTE: Settings are backed up and restored in the order they appear
@@ -8276,6 +8282,16 @@
public static final String NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS =
"network_recommendation_request_timeout_ms";
+ /**
+ * The expiration time in milliseconds for the {@link android.net.WifiKey} request cache in
+ * {@link com.android.server.wifi.RecommendedNetworkEvaluator}.
+ *
+ * Type: long
+ * @hide
+ */
+ public static final String RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS =
+ "recommended_network_evaluator_cache_expiry_ms";
+
/**
* Settings to allow BLE scans to be enabled even when Bluetooth is turned off for
* connectivity.
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index 91c668e..ba75c8b 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -23,7 +23,6 @@
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.ArraySet;
import android.view.autofill.AutoFillId;
import android.view.autofill.AutoFillManager;
import android.widget.RemoteViews;
@@ -69,18 +68,19 @@
*
* <p>If the user does not have any data associated with this {@link android.app.Activity} but
* the service wants to offer the user the option to save the data that was entered, then the
- * service could populate the response with {@code savableIds} instead of {@link Dataset}s:
+ * service could populate the response with a {@link SaveInfo} instead of {@link Dataset}s:
*
* <pre class="prettyprint">
* new FillResponse.Builder()
- * .addSavableFields(id1, id2)
+ * .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_INFO_TYPE_CREDENTIALS)
+ * .addSavableFields(id1, id2))
* .build();
* </pre>
*
* <p>Similarly, there might be cases where the user data on the service is enough to populate some
* fields but not all, and the service would still be interested on saving the other fields. In this
- * scenario, the service could populate the response with both {@link Dataset}s and {@code
- * savableIds}:
+ * scenario, the service could populate the response with both {@link Dataset}s and
+ * {@link SaveInfo}:
*
* <pre class="prettyprint">
* new FillResponse.Builder()
@@ -90,7 +90,8 @@
* .setTextFieldValue(id3, "742 Evergreen Terrace") // street
* .setTextFieldValue(id4, "Springfield") // city
* .build())
- * .addSavableFields(id5, id6) // state and zipcode
+ * .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_INFO_TYPE_ADDRESS)
+ * .addSavableFields(id5, id6)) // state and zipcode
* .build();
*
* </pre>
@@ -140,9 +141,11 @@
* </pre>
*
* <p>The service could require user authentication at the {@link FillResponse} or the
- * {@link Dataset} level, prior to auto-filling an activity - see {@link FillResponse.Builder
- * #setAuthentication(IntentSender)} and {@link Dataset.Builder#setAuthentication(IntentSender)}.
- * It is recommended that you encrypt only the sensitive data but leave the labels unencrypted
+ * {@link Dataset} level, prior to auto-filling an activity - see
+ * {@link FillResponse.Builder#setAuthentication(IntentSender, RemoteViews)} and
+ * {@link Dataset.Builder#setAuthentication(IntentSender)}.
+ *
+ * <p>It is recommended that you encrypt only the sensitive data but leave the labels unencrypted
* which would allow you to provide a dataset presentation views with labels and if the user
* chooses one of them challenge the user to authenticate. For example, if the user has a
* home and a work address the Home and Work labels could be stored unencrypted as they don't
@@ -158,14 +161,45 @@
public final class FillResponse implements Parcelable {
private final ArrayList<Dataset> mDatasets;
- private final ArraySet<AutoFillId> mSavableIds;
+ private final SaveInfo mSaveInfo;
private final Bundle mExtras;
private final RemoteViews mPresentation;
private final IntentSender mAuthentication;
private FillResponse(@NonNull Builder builder) {
mDatasets = builder.mDatasets;
- mSavableIds = builder.mSavableIds;
+
+ if (false) {
+ // TODO(b/33197203, 35727295): this is how mSaveInfo will be set once we don't support
+ // FillResponse.setSavableIds()
+ mSaveInfo = builder.mSaveInfo;
+ if (mSaveInfo != null) {
+ mSaveInfo.addSavableIds(mDatasets);
+ if (mSaveInfo.getSavableIds() == null) {
+ throw new IllegalArgumentException(
+ "need to provide at least one savable id on SaveInfo");
+ }
+ }
+ } else {
+ // Temporary workaround to support FillResponse.setSavableIds()
+ SaveInfo saveInfo = builder.mSaveInfoBuilder != null ? builder.mSaveInfoBuilder.build()
+ : builder.mSaveInfo;
+
+ // Handle the the case where service didn't call setSavableIds() because it would
+ // contain just the ids from the datasets.
+ if (saveInfo == null && mDatasets != null) {
+ saveInfo = new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_GENERIC).build();
+ }
+ if (saveInfo != null) {
+ saveInfo.addSavableIds(mDatasets);
+ if (saveInfo.getSavableIds() == null) {
+ throw new IllegalArgumentException(
+ "need to provide at least one savable id on SaveInfo");
+ }
+ }
+ mSaveInfo = saveInfo;
+ }
+
mExtras = builder.mExtras;
mPresentation = builder.mPresentation;
mAuthentication = builder.mAuthentication;
@@ -182,8 +216,8 @@
}
/** @hide */
- public @Nullable ArraySet<AutoFillId> getSavableIds() {
- return mSavableIds;
+ public @Nullable SaveInfo getSaveInfo() {
+ return mSaveInfo;
}
/** @hide */
@@ -202,7 +236,10 @@
*/
public static final class Builder {
private ArrayList<Dataset> mDatasets;
- private ArraySet<AutoFillId> mSavableIds;
+ // TODO(b/33197203, 35727295): temporary builder use by deprecated addSavableIds() method,
+ // should be removed once that method is gone
+ private SaveInfo.Builder mSaveInfoBuilder;
+ private SaveInfo mSaveInfo;
private Bundle mExtras;
private RemoteViews mPresentation;
private IntentSender mAuthentication;
@@ -276,41 +313,37 @@
if (!mDatasets.add(dataset)) {
return this;
}
- if (dataset.getFieldIds() != null) {
- final int fieldCount = dataset.getFieldIds().size();
- for (int i = 0; i < fieldCount; i++) {
- final AutoFillId id = dataset.getFieldIds().get(i);
- if (mSavableIds == null) {
- mSavableIds = new ArraySet<>();
- }
- mSavableIds.add(id);
- }
+ return this;
+ }
+
+ /** @hide */
+ // TODO(b/33197203, 35727295): remove when not used by clients
+ public @NonNull Builder addSavableFields(@Nullable AutoFillId... ids) {
+ throwIfDestroyed();
+ if (mSaveInfo != null) {
+ throw new IllegalStateException("setSaveInfo() already called");
}
+ if (mSaveInfoBuilder == null) {
+ mSaveInfoBuilder = new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_GENERIC);
+ }
+ mSaveInfoBuilder.addSavableIds(ids);
+
return this;
}
/**
- * Adds ids of additional fields that the service would be interested to save (through
- * {@link AutoFillService#onSaveRequest(
- * android.app.assist.AssistStructure, Bundle, SaveCallback)})
- * but were not indirectly set through {@link #addDataset(Dataset)}.
+ * Sets the {@link SaveInfo} associated with this response.
*
- * @param ids The savable ids.
+ * <p>See {@link FillResponse} for more info.
+ *
* @return This builder.
- *
- * @see FillResponse
*/
- public @NonNull Builder addSavableFields(@Nullable AutoFillId... ids) {
+ public @NonNull Builder setSaveInfo(@NonNull SaveInfo saveInfo) {
throwIfDestroyed();
- if (ids == null) {
- return this;
+ if (mSaveInfoBuilder != null) {
+ throw new IllegalStateException("addSavableFields() already called");
}
- for (AutoFillId id : ids) {
- if (mSavableIds == null) {
- mSavableIds = new ArraySet<>();
- }
- mSavableIds.add(id);
- }
+ mSaveInfo = saveInfo;
return this;
}
@@ -340,9 +373,11 @@
*/
public FillResponse build() {
throwIfDestroyed();
- if (mAuthentication == null && mDatasets == null && mSavableIds == null) {
- throw new IllegalArgumentException("need to provide at least one"
- + " data set or savable ids or an authentication with a presentation");
+
+ if (mAuthentication == null && mDatasets == null && mSaveInfoBuilder == null
+ && mSaveInfo == null) {
+ throw new IllegalArgumentException("need to provide at least one DataSet or a "
+ + "SaveInfo or an authentication with a presentation");
}
mDestroyed = true;
return new FillResponse(this);
@@ -361,9 +396,10 @@
@Override
public String toString() {
if (!DEBUG) return super.toString();
+
return new StringBuilder(
"FillResponse: [datasets=").append(mDatasets)
- .append(", savableIds=").append(mSavableIds)
+ .append(", saveInfo=").append(mSaveInfo)
.append(", hasExtras=").append(mExtras != null)
.append(", hasPresentation=").append(mPresentation != null)
.append(", hasAuthentication=").append(mAuthentication != null)
@@ -382,7 +418,7 @@
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeTypedArrayList(mDatasets, flags);
- parcel.writeTypedArraySet(mSavableIds, flags);
+ parcel.writeParcelable(mSaveInfo, flags);
parcel.writeParcelable(mExtras, flags);
parcel.writeParcelable(mAuthentication, flags);
parcel.writeParcelable(mPresentation, flags);
@@ -401,11 +437,7 @@
for (int i = 0; i < datasetCount; i++) {
builder.addDataset(datasets.get(i));
}
- final ArraySet<AutoFillId> fillIds = parcel.readTypedArraySet(null);
- final int fillIdCount = (fillIds != null) ? fillIds.size() : 0;
- for (int i = 0; i < fillIdCount; i++) {
- builder.addSavableFields(fillIds.valueAt(i));
- }
+ builder.setSaveInfo(parcel.readParcelable(null));
builder.setExtras(parcel.readParcelable(null));
builder.setAuthentication(parcel.readParcelable(null),
parcel.readParcelable(null));
diff --git a/core/java/android/net/NetworkScorerAppManager.aidl b/core/java/android/service/autofill/SaveInfo.aidl
similarity index 88%
copy from core/java/android/net/NetworkScorerAppManager.aidl
copy to core/java/android/service/autofill/SaveInfo.aidl
index d968343..8cda608 100644
--- a/core/java/android/net/NetworkScorerAppManager.aidl
+++ b/core/java/android/service/autofill/SaveInfo.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.net;
+package android.service.autofill;
-parcelable NetworkScorerAppManager.NetworkScorerAppData;
+parcelable SaveInfo;
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
new file mode 100644
index 0000000..096f28b
--- /dev/null
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill;
+
+import static android.view.autofill.Helper.DEBUG;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArraySet;
+import android.view.autofill.AutoFillId;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+
+/**
+ * Information used to indicate that a service is interested on saving the user-inputed data for
+ * future use.
+ *
+ * <p>A {@link SaveInfo} is always associated with a {@link FillResponse}.
+ *
+ * <p>A {@link SaveInfo} must define the type it represents, and contain at least one
+ * {@code savableId}. A {@code savableId} is the {@link AutoFillId} of a view the service is
+ * interested to save in a {@code onSaveRequest()}; the ids of all {@link Dataset} present in the
+ * {@link FillResponse} associated with this {@link SaveInfo} are already marked as savable,
+ * but additional ids can be added through {@link Builder#addSavableIds(AutoFillId...)}.
+ *
+ * <p>See {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
+ * SaveCallback)} and {@link FillResponse} for more info.
+ */
+public final class SaveInfo implements Parcelable {
+
+ /**
+ * Type used on when the service can save the contents of an activity, but cannot describe what
+ * the content is for.
+ */
+ public static final int SAVE_DATA_TYPE_GENERIC = 0;
+
+ /**
+ * Type used when the {@link FillResponse} represents user credentials that have a password.
+ */
+ public static final int SAVE_DATA_TYPE_PASSWORD = 1;
+
+
+ /**
+ * Type used on when the {@link FillResponse} represents a physical address (such as street,
+ * city, state, etc).
+ */
+ public static final int SAVE_DATA_TYPE_ADDRESS = 2;
+
+ /**
+ * Type used when the {@link FillResponse} represents a credit card.
+ */
+ public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3;
+
+ private final @SaveDataType int mType;
+ private ArraySet<AutoFillId> mSavableIds;
+ private final CharSequence mDescription;
+
+ /** @hide */
+ @IntDef({
+ SAVE_DATA_TYPE_GENERIC,
+ SAVE_DATA_TYPE_PASSWORD,
+ SAVE_DATA_TYPE_ADDRESS,
+ SAVE_DATA_TYPE_CREDIT_CARD
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SaveDataType {
+ }
+
+ private SaveInfo(Builder builder) {
+ mType = builder.mType;
+ mSavableIds = builder.mSavableIds;
+ mDescription = builder.mDescription;
+ }
+
+ /** @hide */
+ public @Nullable ArraySet<AutoFillId> getSavableIds() {
+ return mSavableIds;
+ }
+
+ /** @hide */
+ public int getType() {
+ return mType;
+ }
+
+ /** @hide */
+ public CharSequence getDescription() {
+ return mDescription;
+ }
+
+ /** @hide */
+ public void addSavableIds(@Nullable ArrayList<Dataset> datasets) {
+ if (datasets != null) {
+ for (Dataset dataset : datasets) {
+ final ArrayList<AutoFillId> ids = dataset.getFieldIds();
+ if (ids != null) {
+ final int fieldCount = ids.size();
+ for (int i = 0; i < fieldCount; i++) {
+ final AutoFillId id = ids.get(i);
+ if (mSavableIds == null) {
+ mSavableIds = new ArraySet<>();
+ }
+ mSavableIds.add(id);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * A builder for {@link SaveInfo} objects.
+ */
+ public static final class Builder {
+
+ private final @SaveDataType int mType;
+ private ArraySet<AutoFillId> mSavableIds;
+ private CharSequence mDescription;
+ private boolean mDestroyed;
+
+ /**
+ * Creates a new builder.
+ *
+ * @param type the type of information the associated {@link FillResponse} represents. Must
+ * be {@link SaveInfo#SAVE_DATA_TYPE_GENERIC}, {@link SaveInfo#SAVE_DATA_TYPE_PASSWORD},
+ * {@link SaveInfo#SAVE_DATA_TYPE_ADDRESS}, or {@link SaveInfo#SAVE_DATA_TYPE_CREDIT_CARD};
+ * otherwise it will assume {@link SaveInfo#SAVE_DATA_TYPE_GENERIC}.
+ */
+ public Builder(@SaveDataType int type) {
+ switch (type) {
+ case SAVE_DATA_TYPE_PASSWORD:
+ case SAVE_DATA_TYPE_ADDRESS:
+ case SAVE_DATA_TYPE_CREDIT_CARD:
+ mType = type;
+ break;
+ default:
+ mType = SAVE_DATA_TYPE_GENERIC;
+ }
+ }
+
+ /**
+ * Adds ids of additional views the service would be interested to save, but were not
+ * indirectly set through {@link FillResponse.Builder#addDataset(Dataset)}.
+ *
+ * @param ids The savable ids.
+ * @return This builder.
+ *
+ * @see FillResponse
+ */
+ public @NonNull Builder addSavableIds(@Nullable AutoFillId... ids) {
+ throwIfDestroyed();
+
+ if (ids == null) {
+ return this;
+ }
+ for (AutoFillId id : ids) {
+ if (mSavableIds == null) {
+ mSavableIds = new ArraySet<>();
+ }
+ mSavableIds.add(id);
+ }
+ return this;
+ }
+
+ /**
+ * Sets an optional description to be shown in the UI when the user is asked to save.
+ *
+ * <p>Typically, it describes how the data will be stored by the service, so it can help
+ * users to decide whether they can trust the service to save their data.
+ *
+ * @param description a succint description.
+ * @return This Builder.
+ */
+ public @NonNull Builder setDescription(@Nullable CharSequence description) {
+ mDescription = description;
+ return this;
+ }
+
+ /**
+ * Builds a new {@link SaveInfo} instance.
+ */
+ public SaveInfo build() {
+ throwIfDestroyed();
+ mDestroyed = true;
+ return new SaveInfo(this);
+ }
+
+ private void throwIfDestroyed() {
+ if (mDestroyed) {
+ throw new IllegalStateException("Already called #build()");
+ }
+ }
+
+ }
+
+ /////////////////////////////////////
+ // Object "contract" methods. //
+ /////////////////////////////////////
+ @Override
+ public String toString() {
+ if (!DEBUG) return super.toString();
+
+ return new StringBuilder("SaveInfo: [type=").append(mType)
+ .append(", savableIds=").append(mSavableIds)
+ .append("]").toString();
+ }
+
+ /////////////////////////////////////
+ // Parcelable "contract" methods. //
+ /////////////////////////////////////
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeInt(mType);
+ parcel.writeTypedArraySet(mSavableIds, flags);
+ parcel.writeCharSequence(mDescription);
+ }
+
+ public static final Parcelable.Creator<SaveInfo> CREATOR = new Parcelable.Creator<SaveInfo>() {
+ @Override
+ public SaveInfo createFromParcel(Parcel parcel) {
+ // Always go through the builder to ensure the data ingested by
+ // the system obeys the contract of the builder to avoid attacks
+ // using specially crafted parcels.
+ final Builder builder = new Builder(parcel.readInt());
+ final ArraySet<AutoFillId> savableIds = parcel.readTypedArraySet(null);
+ final int savableIdsCount = (savableIds != null) ? savableIds.size() : 0;
+ for (int i = 0; i < savableIdsCount; i++) {
+ builder.addSavableIds(savableIds.valueAt(i));
+ }
+ builder.setDescription(parcel.readCharSequence());
+ return builder.build();
+ }
+
+ @Override
+ public SaveInfo[] newArray(int size) {
+ return new SaveInfo[size];
+ }
+ };
+}
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
index c8358a6..3e992ec 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -127,7 +127,7 @@
}
/**
- * Request that the provider be rebound, after a previous call to (@link requestUnbind).
+ * Request that the provider be rebound, after a previous call to (@link #requestUnbind).
*
* <p>This method will fail for providers that have not been granted the permission by the user.
*/
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 5f7ff67..70e0461 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -148,7 +148,7 @@
// Notification cancellation reasons
- /** Notification was canceled by the status bar reporting a click. */
+ /** Notification was canceled by the status bar reporting a notification click. */
public static final int REASON_DELEGATE_CLICK = 1;
/** Notification was canceled by the status bar reporting a user dismissal. */
public static final int REASON_DELEGATE_CANCEL = 2;
@@ -547,20 +547,20 @@
* Inform the notification manager about snoozing a specific notification.
* <p>
* Use this if your listener has a user interface that allows the user to snooze a notification
- * until a given time. It should be called after the user snoozes a single notification using
+ * for a time. It should be called after the user snoozes a single notification using
* your UI; upon being informed, the notification manager will actually remove the notification
* and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback. When the
* snoozing period expires, you will get a
* {@link #onNotificationPosted(StatusBarNotification, RankingMap)} callback for the
* notification.
* @param key The key of the notification to snooze
- * @param snoozeUntil A time in the future, in milliseconds.
+ * @param durationMs A duration to snooze the notification for, in milliseconds.
*/
- public final void snoozeNotification(String key, long snoozeUntil) {
+ public final void snoozeNotification(String key, long durationMs) {
if (!isBound()) return;
try {
getNotificationInterface().snoozeNotificationUntilFromListener(
- mWrapper, key, snoozeUntil);
+ mWrapper, key, durationMs);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
}
@@ -636,7 +636,7 @@
* <p>The service should wait for the {@link #onListenerConnected()} event
* before performing this operation.
*
- * @return An array of active notifications, sorted in natural order.
+ * @return An array of snoozed notifications, sorted in natural order.
*/
public final StatusBarNotification[] getSnoozedNotifications() {
try {
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 85bccf7..6a24aa4 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -67,6 +67,9 @@
this.groupKey = groupKey();
}
+ /**
+ * @deprecated Non-system apps should not need to create StatusBarNotifications.
+ */
@Deprecated
public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid,
int initialPid, int score, Notification notification, UserHandle user,
diff --git a/core/java/android/transition/Fade.java b/core/java/android/transition/Fade.java
index b0de711..38b89dc 100644
--- a/core/java/android/transition/Fade.java
+++ b/core/java/android/transition/Fade.java
@@ -103,6 +103,7 @@
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Fade);
int fadingMode = a.getInt(R.styleable.Fade_fadingMode, getMode());
setMode(fadingMode);
+ a.recycle();
}
@Override
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index 4c5a717..0cc981e 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -276,9 +276,11 @@
transition.addTarget(clazz);
}
} catch (ClassNotFoundException e) {
+ a.recycle();
throw new RuntimeException("Could not create " + className, e);
}
}
+ a.recycle();
} else {
throw new RuntimeException("Unknown scene name: " + parser.getName());
}
diff --git a/core/java/android/util/Half.java b/core/java/android/util/Half.java
index e4f8dd1..84c2e83 100644
--- a/core/java/android/util/Half.java
+++ b/core/java/android/util/Half.java
@@ -17,9 +17,13 @@
package android.util;
import android.annotation.HalfFloat;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import sun.misc.FloatingDecimal;
/**
- * <p>Half is a utility class to manipulate half-precision 16-bit
+ * <p>The {@code Half} class is a wrapper and a utility class to manipulate half-precision 16-bit
* <a href="https://en.wikipedia.org/wiki/Half-precision_floating-point_format">IEEE 754</a>
* floating point data types (also called fp16 or binary16). A half-precision float can be
* created from or converted to single-precision floats, and is stored in a short data type.
@@ -88,7 +92,7 @@
* <p>This table shows that numbers higher than 1024 lose all fractional precision.</p>
*/
@SuppressWarnings("SimplifiableIfStatement")
-public final class Half {
+public final class Half extends Number implements Comparable<Half> {
/**
* The number of bits used to represent a half-precision float value.
*/
@@ -164,7 +168,332 @@
private static final int FP32_DENORMAL_MAGIC = 126 << 23;
private static final float FP32_DENORMAL_FLOAT = Float.intBitsToFloat(FP32_DENORMAL_MAGIC);
- private Half() {
+ private final @HalfFloat short mValue;
+
+ /**
+ * Constructs a newly allocated {@code Half} object that represents the
+ * half-precision float type argument.
+ *
+ * @param value The value to be represented by the {@code Half}
+ */
+ public Half(@HalfFloat short value) {
+ mValue = value;
+ }
+
+ /**
+ * Constructs a newly allocated {@code Half} object that represents the
+ * argument converted to a half-precision float.
+ *
+ * @param value The value to be represented by the {@code Half}
+ *
+ * @see #toHalf(float)
+ */
+ public Half(float value) {
+ mValue = toHalf(value);
+ }
+
+ /**
+ * Constructs a newly allocated {@code Half} object that
+ * represents the argument converted to a half-precision float.
+ *
+ * @param value The value to be represented by the {@code Half}
+ *
+ * @see #toHalf(float)
+ */
+ public Half(double value) {
+ mValue = toHalf((float) value);
+ }
+
+ /**
+ * <p>Constructs a newly allocated {@code Half} object that represents the
+ * half-precision float value represented by the string.
+ * The string is converted to a half-precision float value as if by the
+ * {@link #valueOf(String)} method.</p>
+ *
+ * <p>Calling this constructor is equivalent to calling:</p>
+ * <pre>
+ * new Half(Float.parseFloat(value))
+ * </pre>
+ *
+ * @param value A string to be converted to a {@code Half}
+ * @throws NumberFormatException if the string does not contain a parsable number
+ *
+ * @see Float#valueOf(java.lang.String)
+ * @see #toHalf(float)
+ */
+ public Half(@NonNull String value) throws NumberFormatException {
+ mValue = toHalf(Float.parseFloat(value));
+ }
+
+ /**
+ * Returns the half-precision value of this {@code Half} as a {@code short}
+ * containing the bit representation described in {@link Half}.
+ *
+ * @return The half-precision float value represented by this object
+ */
+ public @HalfFloat short halfValue() {
+ return mValue;
+ }
+
+ /**
+ * Returns the value of this {@code Half} as a {@code byte} after
+ * a narrowing primitive conversion.
+ *
+ * @return The half-precision float value represented by this object
+ * converted to type {@code byte}
+ */
+ @Override
+ public byte byteValue() {
+ return (byte) toFloat(mValue);
+ }
+
+ /**
+ * Returns the value of this {@code Half} as a {@code short} after
+ * a narrowing primitive conversion.
+ *
+ * @return The half-precision float value represented by this object
+ * converted to type {@code short}
+ */
+ @Override
+ public short shortValue() {
+ return (short) toFloat(mValue);
+ }
+
+ /**
+ * Returns the value of this {@code Half} as a {@code int} after
+ * a narrowing primitive conversion.
+ *
+ * @return The half-precision float value represented by this object
+ * converted to type {@code int}
+ */
+ @Override
+ public int intValue() {
+ return (int) toFloat(mValue);
+ }
+
+ /**
+ * Returns the value of this {@code Half} as a {@code long} after
+ * a narrowing primitive conversion.
+ *
+ * @return The half-precision float value represented by this object
+ * converted to type {@code long}
+ */
+ @Override
+ public long longValue() {
+ return (long) toFloat(mValue);
+ }
+
+ /**
+ * Returns the value of this {@code Half} as a {@code float} after
+ * a widening primitive conversion.
+ *
+ * @return The half-precision float value represented by this object
+ * converted to type {@code float}
+ */
+ @Override
+ public float floatValue() {
+ return toFloat(mValue);
+ }
+
+ /**
+ * Returns the value of this {@code Half} as a {@code double} after
+ * a widening primitive conversion.
+ *
+ * @return The half-precision float value represented by this object
+ * converted to type {@code double}
+ */
+ @Override
+ public double doubleValue() {
+ return toFloat(mValue);
+ }
+
+ /**
+ * Returns true if this {@code Half} value represents a Not-a-Number,
+ * false otherwise.
+ *
+ * @return True if the value is a NaN, false otherwise
+ */
+ public boolean isNaN() {
+ return isNaN(mValue);
+ }
+
+ /**
+ * Compares this object against the specified object. The result is {@code true}
+ * if and only if the argument is not {@code null} and is a {@code Half} object
+ * that represents the same half-precision value as the this object. Two
+ * half-precision values are considered to be the same if and only if the method
+ * {@link #halfToIntBits(short)} returns an identical {@code int} value for both.
+ *
+ * @param o The object to compare
+ * @return True if the objects are the same, false otherwise
+ *
+ * @see #halfToIntBits(short)
+ */
+ @Override
+ public boolean equals(@Nullable Object o) {
+ return (o instanceof Half) &&
+ (halfToIntBits(((Half) o).mValue) == halfToIntBits(mValue));
+ }
+
+ /**
+ * Returns a hash code for this {@code Half} object. The result is the
+ * integer bit representation, exactly as produced by the method
+ * {@link #halfToIntBits(short)}, of the primitive half-precision float
+ * value represented by this {@code Half} object.
+ *
+ * @return A hash code value for this object
+ */
+ @Override
+ public int hashCode() {
+ return hashCode(mValue);
+ }
+
+ /**
+ * Returns a string representation of the specified half-precision
+ * float value. See {@link #toString(short)} for more information.
+ *
+ * @return A string representation of this {@code Half} object
+ */
+ @NonNull
+ @Override
+ public String toString() {
+ return toString(mValue);
+ }
+
+ /**
+ * <p>Compares the two specified half-precision float values. The following
+ * conditions apply during the comparison:</p>
+ *
+ * <ul>
+ * <li>{@link #NaN} is considered by this method to be equal to itself and greater
+ * than all other half-precision float values (including {@code #POSITIVE_INFINITY})</li>
+ * <li>{@link #POSITIVE_ZERO} is considered by this method to be greater than
+ * {@link #NEGATIVE_ZERO}.</li>
+ * </ul>
+ *
+ * @param h The half-precision float value to compare to the half-precision value
+ * represented by this {@code Half} object
+ *
+ * @return The value {@code 0} if {@code x} is numerically equal to {@code y}; a
+ * value less than {@code 0} if {@code x} is numerically less than {@code y};
+ * and a value greater than {@code 0} if {@code x} is numerically greater
+ * than {@code y}
+ */
+ @Override
+ public int compareTo(@NonNull Half h) {
+ return compare(mValue, h.mValue);
+ }
+
+ /**
+ * Returns a hash code for a half-precision float value.
+ *
+ * @param h The value to hash
+ *
+ * @return A hash code value for a half-precision float value
+ */
+ public static int hashCode(@HalfFloat short h) {
+ return halfToIntBits(h);
+ }
+
+ /**
+ * <p>Compares the two specified half-precision float values. The following
+ * conditions apply during the comparison:</p>
+ *
+ * <ul>
+ * <li>{@link #NaN} is considered by this method to be equal to itself and greater
+ * than all other half-precision float values (including {@code #POSITIVE_INFINITY})</li>
+ * <li>{@link #POSITIVE_ZERO} is considered by this method to be greater than
+ * {@link #NEGATIVE_ZERO}.</li>
+ * </ul>
+ *
+ * @param x The first half-precision float value to compare.
+ * @param y The second half-precision float value to compare
+ *
+ * @return The value {@code 0} if {@code x} is numerically equal to {@code y}, a
+ * value less than {@code 0} if {@code x} is numerically less than {@code y},
+ * and a value greater than {@code 0} if {@code x} is numerically greater
+ * than {@code y}
+ */
+ public static int compare(@HalfFloat short x, @HalfFloat short y) {
+ if (less(x, y)) return -1;
+ if (greater(x, y)) return 1;
+
+ // Collapse NaNs, akin to halfToIntBits(), but we want to keep
+ // (signed) short value types to preserve the ordering of -0.0
+ // and +0.0
+ short xBits = (x & FP16_COMBINED) > FP16_EXPONENT_MAX ? NaN : x;
+ short yBits = (y & FP16_COMBINED) > FP16_EXPONENT_MAX ? NaN : y;
+
+ return (xBits == yBits ? 0 : (xBits < yBits ? -1 : 1));
+ }
+
+ /**
+ * <p>Returns a representation of the specified half-precision float value
+ * according to the bit layout described in {@link Half}.</p>
+ *
+ * <p>Similar to {@link #halfToIntBits(short)}, this method collapses all
+ * possible Not-a-Number values to a single canonical Not-a-Number value
+ * defined by {@link #NaN}.</p>
+ *
+ * @param h A half-precision float value
+ * @return The bits that represent the half-precision float value
+ *
+ * @see #halfToIntBits(short)
+ */
+ public static @HalfFloat short halfToShortBits(@HalfFloat short h) {
+ return (h & FP16_COMBINED) > FP16_EXPONENT_MAX ? NaN : h;
+ }
+
+ /**
+ * <p>Returns a representation of the specified half-precision float value
+ * according to the bit layout described in {@link Half}.</p>
+ *
+ * <p>Unlike {@link #halfToRawIntBits(short)}, this method collapses all
+ * possible Not-a-Number values to a single canonical Not-a-Number value
+ * defined by {@link #NaN}.</p>
+ *
+ * @param h A half-precision float value
+ * @return The bits that represent the half-precision float value
+ *
+ * @see #halfToRawIntBits(short)
+ * @see #halfToShortBits(short)
+ * @see #intBitsToHalf(int)
+ */
+ public static int halfToIntBits(@HalfFloat short h) {
+ return (h & FP16_COMBINED) > FP16_EXPONENT_MAX ? NaN : h & 0xffff;
+ }
+
+ /**
+ * <p>Returns a representation of the specified half-precision float value
+ * according to the bit layout described in {@link Half}.</p>
+ *
+ * <p>The argument is considered to be a representation of a half-precision
+ * float value according to the bit layout described in {@link Half}. The 16
+ * most significant bits of the returned value are set to 0.</p>
+ *
+ * @param h A half-precision float value
+ * @return The bits that represent the half-precision float value
+ *
+ * @see #halfToIntBits(short)
+ * @see #intBitsToHalf(int)
+ */
+ public static int halfToRawIntBits(@HalfFloat short h) {
+ return h & 0xffff;
+ }
+
+ /**
+ * <p>Returns the half-precision float value corresponding to a given
+ * bit representation.</p>
+ *
+ * <p>The argument is considered to be a representation of a half-precision
+ * float value according to the bit layout described in {@link Half}. The 16
+ * most significant bits of the argument are ignored.</p>
+ *
+ * @param bits An integer
+ * @return The half-precision float value with the same bit pattern
+ */
+ public static @HalfFloat short intBitsToHalf(int bits) {
+ return (short) (bits & 0xffff);
}
/**
@@ -509,7 +838,7 @@
* infinity, false otherwise.
*
* @param h A half-precision float value
- * @return true if the value is positive infinity or negative infinity,
+ * @return True if the value is positive infinity or negative infinity,
* false otherwise
*/
public static boolean isInfinite(@HalfFloat short h) {
@@ -521,7 +850,7 @@
* a Not-a-Number, false otherwise.
*
* @param h A half-precision float value
- * @return true if the value is a NaN, false otherwise
+ * @return True if the value is a NaN, false otherwise
*/
public static boolean isNaN(@HalfFloat short h) {
return (h & FP16_COMBINED) > FP16_EXPONENT_MAX;
@@ -535,7 +864,7 @@
* number, this method returns false.
*
* @param h A half-precision float value
- * @return true if the value is normalized, false otherwise
+ * @return True if the value is normalized, false otherwise
*/
public static boolean isNormalized(@HalfFloat short h) {
return (h & FP16_EXPONENT_MAX) != 0 && (h & FP16_EXPONENT_MAX) != FP16_EXPONENT_MAX;
@@ -608,7 +937,7 @@
* @return A half-precision float value
*/
@SuppressWarnings("StatementWithEmptyBody")
- public static @HalfFloat short valueOf(float f) {
+ public static @HalfFloat short toHalf(float f) {
int bits = Float.floatToRawIntBits(f);
int s = (bits >>> FP32_SIGN_SHIFT );
int e = (bits >>> FP32_EXPONENT_SHIFT) & FP32_EXPONENT_MASK;
@@ -650,6 +979,57 @@
}
/**
+ * Returns a {@code Half} instance representing the specified
+ * half-precision float value.
+ *
+ * @param h A half-precision float value
+ * @return a {@code Half} instance representing {@code h}
+ */
+ public static @NonNull Half valueOf(@HalfFloat short h) {
+ return new Half(h);
+ }
+
+ /**
+ * Returns a {@code Half} instance representing the specified float value.
+ *
+ * @param f A float value
+ * @return a {@code Half} instance representing {@code f}
+ */
+ public static @NonNull Half valueOf(float f) {
+ return new Half(f);
+ }
+
+ /**
+ * Returns a {@code Half} instance representing the specified string value.
+ * Calling this method is equivalent to calling
+ * <code>toHalf(Float.parseString(h))</code>. See {@link Float#valueOf(String)}
+ * for more information on the format of the string representation.
+ *
+ * @param s The string to be parsed
+ * @return a {@code Half} instance representing {@code h}
+ * @throws NumberFormatException if the string does not contain a parsable
+ * half-precision float value
+ */
+ public static @NonNull Half valueOf(@NonNull String s) {
+ return new Half(s);
+ }
+
+ /**
+ * Returns the half-precision float value represented by the specified string.
+ * Calling this method is equivalent to calling
+ * <code>toHalf(Float.parseString(h))</code>. See {@link Float#valueOf(String)}
+ * for more information on the format of the string representation.
+ *
+ * @param s The string to be parsed
+ * @return A half-precision float value represented by the string
+ * @throws NumberFormatException if the string does not contain a parsable
+ * half-precision float value
+ */
+ public static @HalfFloat short parseHalf(@NonNull String s) throws NumberFormatException {
+ return toHalf(FloatingDecimal.parseFloat(s));
+ }
+
+ /**
* Returns a string representation of the specified half-precision
* float value. Calling this method is equivalent to calling
* <code>Float.toString(toFloat(h))</code>. See {@link Float#toString(float)}
@@ -658,6 +1038,7 @@
* @param h A half-precision float value
* @return A string representation of the specified value
*/
+ @NonNull
public static String toString(@HalfFloat short h) {
return Float.toString(toFloat(h));
}
@@ -688,6 +1069,7 @@
* @param h A half-precision float value
* @return A hexadecimal string representation of the specified value
*/
+ @NonNull
public static String toHexString(@HalfFloat short h) {
StringBuilder o = new StringBuilder();
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index 7fde8a6..ad06141 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -117,7 +117,7 @@
public View findNextKeyboardNavigationCluster(
@NonNull View root,
@Nullable View currentCluster,
- int direction) {
+ @View.FocusDirection int direction) {
View next = null;
final ArrayList<View> clusters = mTempList;
@@ -206,7 +206,7 @@
View root,
View currentCluster,
List<View> clusters,
- int direction) {
+ @View.FocusDirection int direction) {
final int count = clusters.size();
switch (direction) {
@@ -732,27 +732,17 @@
getRect(first, mFirstRect);
getRect(second, mSecondRect);
- if (mFirstRect.top < mSecondRect.top) {
- return -1;
- } else if (mFirstRect.top > mSecondRect.top) {
- return 1;
- } else if (mFirstRect.left < mSecondRect.left) {
- return mIsLayoutRtl ? 1 : -1;
- } else if (mFirstRect.left > mSecondRect.left) {
- return mIsLayoutRtl ? -1 : 1;
- } else if (mFirstRect.bottom < mSecondRect.bottom) {
- return -1;
- } else if (mFirstRect.bottom > mSecondRect.bottom) {
- return 1;
- } else if (mFirstRect.right < mSecondRect.right) {
- return mIsLayoutRtl ? 1 : -1;
- } else if (mFirstRect.right > mSecondRect.right) {
- return mIsLayoutRtl ? -1 : 1;
+ boolean overlapsVertically = (mFirstRect.top < mSecondRect.top
+ && mFirstRect.bottom > mSecondRect.top)
+ || (mFirstRect.top > mSecondRect.top
+ && mFirstRect.top < mSecondRect.bottom);
+ boolean alignedVertically = (mFirstRect.left > mSecondRect.left)
+ == (mFirstRect.right < mSecondRect.right);
+ if (overlapsVertically && !alignedVertically) {
+ int rtl = mIsLayoutRtl ? -1 : 1;
+ return rtl * (mFirstRect.left - mSecondRect.left);
} else {
- // The view are distinct but completely coincident so we consider
- // them equal for our purposes. Since the sort is stable, this
- // means that the views will retain their layout order relative to one another.
- return 0;
+ return mFirstRect.top - mSecondRect.top;
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 66c394f..e349170 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4500,6 +4500,8 @@
break;
case com.android.internal.R.styleable.View_focusableInTouchMode:
if (a.getBoolean(attr, false)) {
+ // unset auto focus since focusableInTouchMode implies explicit focusable
+ viewFlagValues &= ~FOCUSABLE_AUTO;
viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
}
@@ -6471,12 +6473,18 @@
}
}
}
+
+ // Invisible and gone views are never focusable.
if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
return false;
}
- return (allowAutoFocus
- ? getFocusable() != NOT_FOCUSABLE
- : getFocusable() == FOCUSABLE) && isFocusable();
+
+ // Only use effective focusable value when allowed.
+ if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
+ return true;
+ }
+
+ return false;
}
/**
@@ -8666,7 +8674,10 @@
// which, in touch mode, will not successfully request focus on this view
// because the focusable in touch mode flag is not set
setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
+
+ // Clear FOCUSABLE_AUTO if set.
if (focusableInTouchMode) {
+ // Clears FOCUSABLE_AUTO if set.
setFlags(FOCUSABLE, FOCUSABLE_MASK);
}
}
@@ -9433,7 +9444,8 @@
* @return The nearest keyboard navigation cluster in the specified direction, or null if none
* can be found
*/
- public View keyboardNavigationClusterSearch(View currentCluster, int direction) {
+ public View keyboardNavigationClusterSearch(View currentCluster,
+ @FocusDirection int direction) {
if (isKeyboardNavigationCluster()) {
currentCluster = this;
}
@@ -11729,7 +11741,10 @@
&& isOnScrollbar(event.getX(), event.getY())) {
awakenScrollBars();
}
- if (isHoverable()) {
+
+ // If we consider ourself hoverable, or if we we're already hovered,
+ // handle changing state in response to ENTER and EXIT events.
+ if (isHoverable() || isHovered()) {
switch (action) {
case MotionEvent.ACTION_HOVER_ENTER:
setHovered(true);
@@ -12260,12 +12275,13 @@
// If focusable is auto, update the FOCUSABLE bit.
int focusableChangedByAuto = 0;
if (((mViewFlags & FOCUSABLE_AUTO) != 0)
- && (changed & (FOCUSABLE_MASK | CLICKABLE | FOCUSABLE_IN_TOUCH_MODE)) != 0) {
- int newFocus = NOT_FOCUSABLE;
- if ((mViewFlags & (CLICKABLE | FOCUSABLE_IN_TOUCH_MODE)) != 0) {
+ && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
+ // Heuristic only takes into account whether view is clickable.
+ final int newFocus;
+ if ((mViewFlags & CLICKABLE) != 0) {
newFocus = FOCUSABLE;
} else {
- mViewFlags = (mViewFlags & ~FOCUSABLE_IN_TOUCH_MODE);
+ newFocus = NOT_FOCUSABLE;
}
mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
@@ -20259,9 +20275,9 @@
* @return the view of the specified id, null if cannot be found
* @hide
*/
- protected View findViewTraversal(@IdRes int id) {
+ protected <T extends View> T findViewTraversal(@IdRes int id) {
if (id == mID) {
- return this;
+ return (T) this;
}
return null;
}
@@ -20271,9 +20287,9 @@
* @return the view of specified tag, null if cannot be found
* @hide
*/
- protected View findViewWithTagTraversal(Object tag) {
+ protected <T extends View> T findViewWithTagTraversal(Object tag) {
if (tag != null && tag.equals(mTag)) {
- return this;
+ return (T) this;
}
return null;
}
@@ -20284,9 +20300,10 @@
* @return The first view that matches the predicate or null.
* @hide
*/
- protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+ protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
+ View childToSkip) {
if (predicate.test(this)) {
- return this;
+ return (T) this;
}
return null;
}
@@ -20299,7 +20316,7 @@
* @return The view that has the given id in the hierarchy or null
*/
@Nullable
- public final View findViewById(@IdRes int id) {
+ public final <T extends View> T findViewById(@IdRes int id) {
if (id < 0) {
return null;
}
@@ -20312,11 +20329,11 @@
* @param accessibilityId The searched accessibility id.
* @return The found view.
*/
- final View findViewByAccessibilityId(int accessibilityId) {
+ final <T extends View> T findViewByAccessibilityId(int accessibilityId) {
if (accessibilityId < 0) {
return null;
}
- View view = findViewByAccessibilityIdTraversal(accessibilityId);
+ T view = findViewByAccessibilityIdTraversal(accessibilityId);
if (view != null) {
return view.includeForAccessibility() ? view : null;
}
@@ -20335,12 +20352,11 @@
*
* @param accessibilityId The accessibility id.
* @return The found view.
- *
* @hide
*/
- public View findViewByAccessibilityIdTraversal(int accessibilityId) {
+ public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
if (getAccessibilityViewId() == accessibilityId) {
- return this;
+ return (T) this;
}
return null;
}
@@ -20352,7 +20368,7 @@
* @param tag The tag to search for, using "tag.equals(getTag())".
* @return The View that has the given tag in the hierarchy or null
*/
- public final View findViewWithTag(Object tag) {
+ public final <T extends View> T findViewWithTag(Object tag) {
if (tag == null) {
return null;
}
@@ -20367,7 +20383,7 @@
* @return The first view that matches the predicate or null.
* @hide
*/
- public final View findViewByPredicate(Predicate<View> predicate) {
+ public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
return findViewByPredicateTraversal(predicate, null);
}
@@ -20387,10 +20403,11 @@
* @return The first view that matches the predicate or null.
* @hide
*/
- public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
+ public final <T extends View> T findViewByPredicateInsideOut(
+ View start, Predicate<View> predicate) {
View childToSkip = null;
for (;;) {
- View view = start.findViewByPredicateTraversal(predicate, childToSkip);
+ T view = start.findViewByPredicateTraversal(predicate, childToSkip);
if (view != null || start == this) {
return view;
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7aa2168..3dd3ba8 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1148,18 +1148,21 @@
@Override
boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
+ // This should probably be super.hasFocusable, but that would change
+ // behavior. Historically, we have not checked the ancestor views for
+ // shouldBlockFocusForTouchscreen() in ViewGroup.hasFocusable.
+
+ // Invisible and gone views are never focusable.
if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
return false;
}
- // TODO This should probably be super.hasFocusable, but that would change behavior.
- // The below is a much simpler check than we do in the superclass implementation,
- // but it's been this way for a long time and other code likely relies on it.
- if ((allowAutoFocus ? getFocusable() != NOT_FOCUSABLE : getFocusable() == FOCUSABLE)
- && isFocusable()) {
+ // Only use effective focusable value when allowed.
+ if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
return true;
}
+ // Determine whether we have a focused descendant.
final int descendantFocusability = getDescendantFocusability();
if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
final int count = mChildrenCount;
@@ -4324,9 +4327,9 @@
* {@hide}
*/
@Override
- protected View findViewTraversal(@IdRes int id) {
+ protected <T extends View> T findViewTraversal(@IdRes int id) {
if (id == mID) {
- return this;
+ return (T) this;
}
final View[] where = mChildren;
@@ -4339,7 +4342,7 @@
v = v.findViewById(id);
if (v != null) {
- return v;
+ return (T) v;
}
}
}
@@ -4351,9 +4354,9 @@
* {@hide}
*/
@Override
- protected View findViewWithTagTraversal(Object tag) {
+ protected <T extends View> T findViewWithTagTraversal(Object tag) {
if (tag != null && tag.equals(mTag)) {
- return this;
+ return (T) this;
}
final View[] where = mChildren;
@@ -4366,7 +4369,7 @@
v = v.findViewWithTag(tag);
if (v != null) {
- return v;
+ return (T) v;
}
}
}
@@ -4378,9 +4381,10 @@
* {@hide}
*/
@Override
- protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+ protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
+ View childToSkip) {
if (predicate.test(this)) {
- return this;
+ return (T) this;
}
final View[] where = mChildren;
@@ -4393,7 +4397,7 @@
v = v.findViewByPredicate(predicate);
if (v != null) {
- return v;
+ return (T) v;
}
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 595e7a1..20d960f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -72,6 +72,7 @@
import android.util.TypedValue;
import android.view.Surface.OutOfResourcesException;
import android.view.View.AttachInfo;
+import android.view.View.FocusDirection;
import android.view.View.MeasureSpec;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import android.view.accessibility.AccessibilityEvent;
@@ -4304,11 +4305,11 @@
mTranslator.translateEventInScreenToAppWindow(event);
}
- // Enter touch mode on down or scroll.
+ // Enter touch mode on down or scroll, if it is coming from a touch screen device,
+ // exit otherwise.
final int action = event.getAction();
- if (event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)
- && (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_SCROLL)) {
- ensureTouchMode(true);
+ if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_SCROLL) {
+ ensureTouchMode(event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN));
}
if (action == MotionEvent.ACTION_DOWN && mAttachInfo.mTooltipHost != null) {
@@ -5975,7 +5976,8 @@
* {@inheritDoc}
*/
@Override
- public View keyboardNavigationClusterSearch(View currentCluster, int direction) {
+ public View keyboardNavigationClusterSearch(View currentCluster,
+ @FocusDirection int direction) {
checkThread();
return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
mView, currentCluster, direction);
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index d866927..8094fa6 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -3591,6 +3591,7 @@
* <li><strong>Standard actions</strong> - These are actions that are reported and
* handled by the standard UI widgets in the platform. For each standard action
* there is a static constant defined in this class, e.g. {@link #ACTION_FOCUS}.
+ * These actions will have {@code null} labels.
* </li>
* <li><strong>Custom actions action</strong> - These are actions that are reported
* and handled by custom widgets. i.e. ones that are not part of the UI toolkit. For
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 51587a7..9a39a17 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -250,7 +250,7 @@
mDefaultActivityButton = (FrameLayout) findViewById(R.id.default_activity_button);
mDefaultActivityButton.setOnClickListener(mCallbacks);
mDefaultActivityButton.setOnLongClickListener(mCallbacks);
- mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.image);
+ mDefaultActivityButtonImage = mDefaultActivityButton.findViewById(R.id.image);
final FrameLayout expandButton = (FrameLayout) findViewById(R.id.expand_activities_button);
expandButton.setOnClickListener(mCallbacks);
@@ -282,7 +282,7 @@
mExpandActivityOverflowButton = expandButton;
mExpandActivityOverflowButtonImage =
- (ImageView) expandButton.findViewById(R.id.image);
+ expandButton.findViewById(R.id.image);
mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable);
mAdapter = new ActivityChooserViewAdapter();
@@ -760,7 +760,7 @@
convertView = LayoutInflater.from(getContext()).inflate(
R.layout.activity_chooser_view_list_item, parent, false);
convertView.setId(ITEM_VIEW_TYPE_FOOTER);
- TextView titleView = (TextView) convertView.findViewById(R.id.title);
+ TextView titleView = convertView.findViewById(R.id.title);
titleView.setText(mContext.getString(
R.string.activity_chooser_view_see_all));
}
@@ -772,11 +772,11 @@
}
PackageManager packageManager = mContext.getPackageManager();
// Set the icon
- ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
+ ImageView iconView = convertView.findViewById(R.id.icon);
ResolveInfo activity = (ResolveInfo) getItem(position);
iconView.setImageDrawable(activity.loadIcon(packageManager));
// Set the title.
- TextView titleView = (TextView) convertView.findViewById(R.id.title);
+ TextView titleView = convertView.findViewById(R.id.title);
titleView.setText(activity.loadLabel(packageManager));
// Highlight the default.
if (mShowDefaultActivity && position == 0 && mHighlightDefaultActivity) {
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 68e6809..06d4868 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -451,7 +451,7 @@
private View getPermissionsView(int which, boolean showRevokeUI) {
LinearLayout permsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
- LinearLayout displayList = (LinearLayout) permsView.findViewById(R.id.perms_list);
+ LinearLayout displayList = permsView.findViewById(R.id.perms_list);
View noPermsView = permsView.findViewById(R.id.no_permissions);
displayPermissions(mPermGroupsList, displayList, which, showRevokeUI);
@@ -517,8 +517,8 @@
CharSequence grpName, CharSequence permList, boolean dangerous, Drawable icon) {
View permView = inflater.inflate(R.layout.app_permission_item_old, null);
- TextView permGrpView = (TextView) permView.findViewById(R.id.permission_group);
- TextView permDescView = (TextView) permView.findViewById(R.id.permission_list);
+ TextView permGrpView = permView.findViewById(R.id.permission_group);
+ TextView permDescView = permView.findViewById(R.id.permission_list);
ImageView imgView = (ImageView)permView.findViewById(R.id.perm_icon);
imgView.setImageDrawable(icon);
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index bbc50da..81f0d3d 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -388,7 +388,7 @@
text = (TextView) view;
} else {
// Otherwise, find the TextView field within the layout
- text = (TextView) view.findViewById(mFieldId);
+ text = view.findViewById(mFieldId);
if (text == null) {
throw new RuntimeException("Failed to find view with ID "
diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java
index 557d411..1b899db 100644
--- a/core/java/android/widget/CalendarViewLegacyDelegate.java
+++ b/core/java/android/widget/CalendarViewLegacyDelegate.java
@@ -316,9 +316,9 @@
View content = layoutInflater.inflate(R.layout.calendar_view, null, false);
mDelegator.addView(content);
- mListView = (ListView) mDelegator.findViewById(R.id.list);
- mDayNamesHeader = (ViewGroup) content.findViewById(R.id.day_names);
- mMonthName = (TextView) content.findViewById(R.id.month_name);
+ mListView = mDelegator.findViewById(R.id.list);
+ mDayNamesHeader = content.findViewById(R.id.day_names);
+ mMonthName = content.findViewById(R.id.month_name);
setUpHeader();
setUpListView();
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index f712685..907250a 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -115,10 +115,10 @@
mDelegator.addView(mContainer);
// Set up header views.
- final ViewGroup header = (ViewGroup) mContainer.findViewById(R.id.date_picker_header);
- mHeaderYear = (TextView) header.findViewById(R.id.date_picker_header_year);
+ final ViewGroup header = mContainer.findViewById(R.id.date_picker_header);
+ mHeaderYear = header.findViewById(R.id.date_picker_header_year);
mHeaderYear.setOnClickListener(mOnHeaderClickListener);
- mHeaderMonthDay = (TextView) header.findViewById(R.id.date_picker_header_date);
+ mHeaderMonthDay = header.findViewById(R.id.date_picker_header_date);
mHeaderMonthDay.setOnClickListener(mOnHeaderClickListener);
// For the sake of backwards compatibility, attempt to extract the text
@@ -154,10 +154,10 @@
a.recycle();
// Set up picker container.
- mAnimator = (ViewAnimator) mContainer.findViewById(R.id.animator);
+ mAnimator = mContainer.findViewById(R.id.animator);
// Set up day picker view.
- mDayPickerView = (DayPickerView) mAnimator.findViewById(R.id.date_picker_day_picker);
+ mDayPickerView = mAnimator.findViewById(R.id.date_picker_day_picker);
mDayPickerView.setFirstDayOfWeek(mFirstDayOfWeek);
mDayPickerView.setMinDate(mMinDate.getTimeInMillis());
mDayPickerView.setMaxDate(mMaxDate.getTimeInMillis());
@@ -165,7 +165,7 @@
mDayPickerView.setOnDaySelectedListener(mOnDaySelectedListener);
// Set up year picker view.
- mYearPickerView = (YearPickerView) mAnimator.findViewById(R.id.date_picker_year_picker);
+ mYearPickerView = mAnimator.findViewById(R.id.date_picker_year_picker);
mYearPickerView.setRange(mMinDate, mMaxDate);
mYearPickerView.setYear(mCurrentDate.get(Calendar.YEAR));
mYearPickerView.setOnYearSelectedListener(mOnYearSelectedListener);
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index 8d5bf8f..63621e1 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -225,7 +225,7 @@
public Object instantiateItem(ViewGroup container, int position) {
final View itemView = mInflater.inflate(mLayoutResId, container, false);
- final SimpleMonthView v = (SimpleMonthView) itemView.findViewById(mCalendarViewId);
+ final SimpleMonthView v = itemView.findViewById(mCalendarViewId);
v.setOnDayClickListener(mOnDayClickListener);
v.setMonthTextAppearance(mMonthTextAppearance);
v.setDayOfWeekTextAppearance(mDayOfWeekTextAppearance);
diff --git a/core/java/android/widget/DayPickerViewPager.java b/core/java/android/widget/DayPickerViewPager.java
index a27e022..1704ed7 100644
--- a/core/java/android/widget/DayPickerViewPager.java
+++ b/core/java/android/widget/DayPickerViewPager.java
@@ -137,9 +137,10 @@
}
@Override
- protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+ protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
+ View childToSkip) {
if (predicate.test(this)) {
- return this;
+ return (T) this;
}
// Always try the selected view first.
@@ -148,7 +149,7 @@
if (current != childToSkip && current != null) {
final View v = current.findViewByPredicate(predicate);
if (v != null) {
- return v;
+ return (T) v;
}
}
@@ -160,7 +161,7 @@
final View v = child.findViewByPredicate(predicate);
if (v != null) {
- return v;
+ return (T) v;
}
}
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index dd3b054..ade03e1 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2183,6 +2183,11 @@
}
void onTouchUpEvent(MotionEvent event) {
+ if (getSelectionActionModeHelper().resetOriginalSelection(
+ getTextView().getOffsetForPosition(event.getX(), event.getY()))) {
+ return;
+ }
+
boolean selectAllGotFocus = mSelectAllOnFocus && mTextView.didTouchFocusSelect();
hideCursorAndSpanControllers();
stopTextActionMode();
@@ -3916,7 +3921,7 @@
@Override
public void onDestroyActionMode(ActionMode mode) {
// Clear mTextActionMode not to recursively destroy action mode by clearing selection.
- getSelectionActionModeHelper().cancelAsyncTask();
+ getSelectionActionModeHelper().onDestroyActionMode();
mTextActionMode = null;
Callback customCallback = getCustomCallback();
if (customCallback != null) {
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 46e998a..1c0c4ef 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3740,20 +3740,21 @@
* @removed For internal use only. This should have been hidden.
*/
@Override
- protected View findViewTraversal(@IdRes int id) {
- View v;
- v = super.findViewTraversal(id);
+ protected <T extends View> T findViewTraversal(@IdRes int id) {
+ // First look in our children, then in any header and footer views that
+ // may be scrolled off.
+ View v = super.findViewTraversal(id);
if (v == null) {
v = findViewInHeadersOrFooters(mHeaderViewInfos, id);
if (v != null) {
- return v;
+ return (T) v;
}
v = findViewInHeadersOrFooters(mFooterViewInfos, id);
if (v != null) {
- return v;
+ return (T) v;
}
}
- return v;
+ return (T) v;
}
View findViewInHeadersOrFooters(ArrayList<FixedViewInfo> where, int id) {
@@ -3782,21 +3783,22 @@
* @removed For internal use only. This should have been hidden.
*/
@Override
- protected View findViewWithTagTraversal(Object tag) {
- View v;
- v = super.findViewWithTagTraversal(tag);
+ protected <T extends View> T findViewWithTagTraversal(Object tag) {
+ // First look in our children, then in any header and footer views that
+ // may be scrolled off.
+ View v = super.findViewWithTagTraversal(tag);
if (v == null) {
v = findViewWithTagInHeadersOrFooters(mHeaderViewInfos, tag);
if (v != null) {
- return v;
+ return (T) v;
}
v = findViewWithTagInHeadersOrFooters(mFooterViewInfos, tag);
if (v != null) {
- return v;
+ return (T) v;
}
}
- return v;
+ return (T) v;
}
View findViewWithTagInHeadersOrFooters(ArrayList<FixedViewInfo> where, Object tag) {
@@ -3829,21 +3831,21 @@
* @hide
*/
@Override
- protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
- View v;
- v = super.findViewByPredicateTraversal(predicate, childToSkip);
+ protected <T extends View> T findViewByPredicateTraversal(
+ Predicate<View> predicate, View childToSkip) {
+ View v = super.findViewByPredicateTraversal(predicate, childToSkip);
if (v == null) {
v = findViewByPredicateInHeadersOrFooters(mHeaderViewInfos, predicate, childToSkip);
if (v != null) {
- return v;
+ return (T) v;
}
v = findViewByPredicateInHeadersOrFooters(mFooterViewInfos, predicate, childToSkip);
if (v != null) {
- return v;
+ return (T) v;
}
}
- return v;
+ return (T) v;
}
/**
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 8008637..8e04f1c 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -257,13 +257,13 @@
.getText(com.android.internal.R.string.lockscreen_transport_play_description);
mPauseDescription = res
.getText(com.android.internal.R.string.lockscreen_transport_pause_description);
- mPauseButton = (ImageButton) v.findViewById(com.android.internal.R.id.pause);
+ mPauseButton = v.findViewById(com.android.internal.R.id.pause);
if (mPauseButton != null) {
mPauseButton.requestFocus();
mPauseButton.setOnClickListener(mPauseListener);
}
- mFfwdButton = (ImageButton) v.findViewById(com.android.internal.R.id.ffwd);
+ mFfwdButton = v.findViewById(com.android.internal.R.id.ffwd);
if (mFfwdButton != null) {
mFfwdButton.setOnClickListener(mFfwdListener);
if (!mFromXml) {
@@ -271,7 +271,7 @@
}
}
- mRewButton = (ImageButton) v.findViewById(com.android.internal.R.id.rew);
+ mRewButton = v.findViewById(com.android.internal.R.id.rew);
if (mRewButton != null) {
mRewButton.setOnClickListener(mRewListener);
if (!mFromXml) {
@@ -280,16 +280,16 @@
}
// By default these are hidden. They will be enabled when setPrevNextListeners() is called
- mNextButton = (ImageButton) v.findViewById(com.android.internal.R.id.next);
+ mNextButton = v.findViewById(com.android.internal.R.id.next);
if (mNextButton != null && !mFromXml && !mListenersSet) {
mNextButton.setVisibility(View.GONE);
}
- mPrevButton = (ImageButton) v.findViewById(com.android.internal.R.id.prev);
+ mPrevButton = v.findViewById(com.android.internal.R.id.prev);
if (mPrevButton != null && !mFromXml && !mListenersSet) {
mPrevButton.setVisibility(View.GONE);
}
- mProgress = (ProgressBar) v.findViewById(com.android.internal.R.id.mediacontroller_progress);
+ mProgress = v.findViewById(com.android.internal.R.id.mediacontroller_progress);
if (mProgress != null) {
if (mProgress instanceof SeekBar) {
SeekBar seeker = (SeekBar) mProgress;
@@ -298,8 +298,8 @@
mProgress.setMax(1000);
}
- mEndTime = (TextView) v.findViewById(com.android.internal.R.id.time);
- mCurrentTime = (TextView) v.findViewById(com.android.internal.R.id.time_current);
+ mEndTime = v.findViewById(com.android.internal.R.id.time);
+ mCurrentTime = v.findViewById(com.android.internal.R.id.time_current);
mFormatBuilder = new StringBuilder();
mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 359d04e..5505f2f 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1578,7 +1578,7 @@
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
final Context context = root.getContext();
- final ViewGroup target = (ViewGroup) root.findViewById(viewId);
+ final ViewGroup target = root.findViewById(viewId);
if (target == null) return;
if (nestedViews != null) {
// Inflate nested views and add as children
@@ -1757,7 +1757,7 @@
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
- final TextView target = (TextView) root.findViewById(viewId);
+ final TextView target = root.findViewById(viewId);
if (target == null) return;
if (drawablesLoaded) {
if (isRelative) {
@@ -1857,7 +1857,7 @@
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
- final TextView target = (TextView) root.findViewById(viewId);
+ final TextView target = root.findViewById(viewId);
if (target == null) return;
target.setTextSize(units, size);
}
@@ -2045,7 +2045,7 @@
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
- final TextView target = (TextView) root.findViewById(viewId);
+ final TextView target = root.findViewById(viewId);
if (target == null) return;
Drawable[] drawables = isRelative
? target.getCompoundDrawablesRelative()
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 770d9ee..6790532 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -54,6 +54,8 @@
private TextClassificationResult mTextClassificationResult;
private AsyncTask mTextClassificationAsyncTask;
+ private final SelectionInfo mSelectionInfo = new SelectionInfo();
+
SelectionActionModeHelper(@NonNull Editor editor) {
mEditor = Preconditions.checkNotNull(editor);
final TextView textView = mEditor.getTextView();
@@ -94,12 +96,12 @@
}
}
- public void cancelAsyncTask() {
- if (mTextClassificationAsyncTask != null) {
- mTextClassificationAsyncTask.cancel(true);
- mTextClassificationAsyncTask = null;
+ public boolean resetOriginalSelection(int textIndex) {
+ if (mSelectionInfo.resetOriginalSelection(textIndex, mEditor.getTextView().getText())) {
+ invalidateActionModeAsync();
+ return true;
}
- mTextClassificationResult = null;
+ return false;
}
@Nullable
@@ -107,12 +109,28 @@
return mTextClassificationResult;
}
+ public void onDestroyActionMode() {
+ mSelectionInfo.onSelectionDestroyed();
+ cancelAsyncTask();
+ }
+
+ private void cancelAsyncTask() {
+ if (mTextClassificationAsyncTask != null) {
+ mTextClassificationAsyncTask.cancel(true);
+ mTextClassificationAsyncTask = null;
+ }
+ mTextClassificationResult = null;
+ }
+
private boolean isNoOpTextClassifier() {
return mEditor.getTextView().getTextClassifier() == TextClassifier.NO_OP;
}
private void startActionMode(@Nullable SelectionResult result) {
- final CharSequence text = mEditor.getTextView().getText();
+ final TextView textView = mEditor.getTextView();
+ final CharSequence text = textView.getText();
+ mSelectionInfo.setOriginalSelection(
+ textView.getSelectionStart(), textView.getSelectionEnd());
if (result != null && text instanceof Spannable) {
Selection.setSelection((Spannable) text, result.mStart, result.mEnd);
mTextClassificationResult = result.mResult;
@@ -124,6 +142,9 @@
if (controller != null) {
controller.show();
}
+ if (result != null) {
+ mSelectionInfo.onSelectionStarted(result.mStart, result.mEnd);
+ }
}
mEditor.setRestartActionModeOnNextRefresh(false);
mTextClassificationAsyncTask = null;
@@ -135,6 +156,8 @@
if (actionMode != null) {
actionMode.invalidate();
}
+ final TextView textView = mEditor.getTextView();
+ mSelectionInfo.onSelectionUpdated(textView.getSelectionStart(), textView.getSelectionEnd());
mTextClassificationAsyncTask = null;
}
@@ -145,6 +168,56 @@
}
/**
+ * Holds information about the selection and uses it to decide on whether or not to update
+ * the selection when resetOriginalSelection is called.
+ * The expected UX here is to allow the user to re-snap the selection back to the original word
+ * that was selected with one tap on that word.
+ */
+ private static final class SelectionInfo {
+
+ private int mOriginalStart;
+ private int mOriginalEnd;
+ private int mSelectionStart;
+ private int mSelectionEnd;
+
+ private boolean mResetOriginal;
+
+ public void setOriginalSelection(int selectionStart, int selectionEnd) {
+ mOriginalStart = selectionStart;
+ mOriginalEnd = selectionEnd;
+ mResetOriginal = false;
+ }
+
+ public void onSelectionStarted(int selectionStart, int selectionEnd) {
+ // Set the reset flag to true if the selection changed.
+ mSelectionStart = selectionStart;
+ mSelectionEnd = selectionEnd;
+ mResetOriginal = mSelectionStart != mOriginalStart || mSelectionEnd != mOriginalEnd;
+ }
+
+ public void onSelectionUpdated(int selectionStart, int selectionEnd) {
+ // If the selection did not change, maintain the reset state. Otherwise, disable reset.
+ mResetOriginal &= selectionStart == mSelectionStart && selectionEnd == mSelectionEnd;
+ }
+
+ public void onSelectionDestroyed() {
+ mResetOriginal = false;
+ }
+
+ public boolean resetOriginalSelection(int textIndex, CharSequence text) {
+ if (mResetOriginal
+ && textIndex >= mOriginalStart && textIndex <= mOriginalEnd
+ && text instanceof Spannable) {
+ Selection.setSelection((Spannable) text, mOriginalStart, mOriginalEnd);
+ // Only allow a reset once.
+ mResetOriginal = false;
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
* AsyncTask for running a query on a background thread and returning the result on the
* UiThread. The AsyncTask times out after a specified time, returning a null result if the
* query has not yet returned.
diff --git a/core/java/android/widget/SuggestionsAdapter.java b/core/java/android/widget/SuggestionsAdapter.java
index f833d1b..fbb8993 100644
--- a/core/java/android/widget/SuggestionsAdapter.java
+++ b/core/java/android/widget/SuggestionsAdapter.java
@@ -286,7 +286,7 @@
v.setTag(new ChildViewCache(v));
// Set up icon.
- final ImageView iconRefine = (ImageView) v.findViewById(R.id.edit_query);
+ final ImageView iconRefine = v.findViewById(R.id.edit_query);
iconRefine.setImageResource(mCommitIconResId);
return v;
@@ -304,11 +304,11 @@
public final ImageView mIconRefine;
public ChildViewCache(View v) {
- mText1 = (TextView) v.findViewById(com.android.internal.R.id.text1);
- mText2 = (TextView) v.findViewById(com.android.internal.R.id.text2);
- mIcon1 = (ImageView) v.findViewById(com.android.internal.R.id.icon1);
- mIcon2 = (ImageView) v.findViewById(com.android.internal.R.id.icon2);
- mIconRefine = (ImageView) v.findViewById(com.android.internal.R.id.edit_query);
+ mText1 = v.findViewById(com.android.internal.R.id.text1);
+ mText2 = v.findViewById(com.android.internal.R.id.text2);
+ mIcon1 = v.findViewById(com.android.internal.R.id.icon1);
+ mIcon2 = v.findViewById(com.android.internal.R.id.icon2);
+ mIconRefine = v.findViewById(com.android.internal.R.id.edit_query);
}
}
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 32418cd..7e2cadf 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -619,7 +619,7 @@
mTabWidget, // tab widget is the parent
false); // no inflate params
- final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
+ final TextView tv = tabIndicator.findViewById(R.id.title);
tv.setText(mLabel);
if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.DONUT) {
@@ -653,8 +653,8 @@
mTabWidget, // tab widget is the parent
false); // no inflate params
- final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
- final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.icon);
+ final TextView tv = tabIndicator.findViewById(R.id.title);
+ final ImageView iconView = tabIndicator.findViewById(R.id.icon);
// when icon is gone by default, we're in exclusive mode
final boolean exclusive = iconView.getVisibility() == View.GONE;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9078e61..adc6f72 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -266,7 +266,7 @@
* @attr ref android.R.styleable#TextView_fontFeatureSettings
* @attr ref android.R.styleable#TextView_breakStrategy
* @attr ref android.R.styleable#TextView_hyphenationFrequency
- * @attr ref android.R.styleable#TextView_autoSizeText
+ * @attr ref android.R.styleable#TextView_autoSizeTextType
* @attr ref android.R.styleable#TextView_autoSizeMinTextSize
* @attr ref android.R.styleable#TextView_autoSizeMaxTextSize
* @attr ref android.R.styleable#TextView_autoSizeStepGranularity
@@ -691,18 +691,24 @@
*/
private int mDeviceProvisionedState = DEVICE_PROVISIONED_UNKNOWN;
- // The TextView does not auto-size text (default).
+ /**
+ * The TextView does not auto-size text (default).
+ */
public static final int AUTO_SIZE_TEXT_TYPE_NONE = 0;
- // The TextView performs uniform horizontal and vertical text size scaling to fit within the
- // container.
+
+ /**
+ * The TextView scales text size both horizontally and vertically to fit within the
+ * container.
+ */
public static final int AUTO_SIZE_TEXT_TYPE_UNIFORM = 1;
+
/** @hide */
@IntDef({AUTO_SIZE_TEXT_TYPE_NONE, AUTO_SIZE_TEXT_TYPE_UNIFORM})
@Retention(RetentionPolicy.SOURCE)
public @interface AutoSizeTextType {}
- // Default minimum size for auto-sizing text in scaled pixels. {@see #setAutoSizeMinTextSize}.
+ // Default minimum size for auto-sizing text in scaled pixels.
private static final int DEFAULT_AUTO_SIZE_MIN_TEXT_SIZE_IN_SP = 12;
- // Default maximum size for auto-sizing text in scaled pixels. {@see #setAutoSizeMaxTextSize}.
+ // Default maximum size for auto-sizing text in scaled pixels.
private static final int DEFAULT_AUTO_SIZE_MAX_TEXT_SIZE_IN_SP = 112;
// Default value for the step size in pixels.
private static final int DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX = 1;
@@ -1308,7 +1314,7 @@
mHyphenationFrequency = a.getInt(attr, Layout.HYPHENATION_FREQUENCY_NONE);
break;
- case com.android.internal.R.styleable.TextView_autoSizeText:
+ case com.android.internal.R.styleable.TextView_autoSizeTextType:
mAutoSizeTextType = a.getInt(attr, AUTO_SIZE_TEXT_TYPE_NONE);
break;
@@ -1660,7 +1666,7 @@
* {@link TextView#AUTO_SIZE_TEXT_TYPE_NONE} or
* {@link TextView#AUTO_SIZE_TEXT_TYPE_UNIFORM}
*
- * @attr ref android.R.styleable#TextView_autoSizeText
+ * @attr ref android.R.styleable#TextView_autoSizeTextType
*
* @see #getAutoSizeTextType()
*/
@@ -1709,7 +1715,7 @@
*
* @throws IllegalArgumentException if any of the configuration params are invalid.
*
- * @attr ref android.R.styleable#TextView_autoSizeText
+ * @attr ref android.R.styleable#TextView_autoSizeTextType
* @attr ref android.R.styleable#TextView_autoSizeMinTextSize
* @attr ref android.R.styleable#TextView_autoSizeMaxTextSize
* @attr ref android.R.styleable#TextView_autoSizeStepGranularity
@@ -1753,7 +1759,7 @@
*
* @throws IllegalArgumentException if all of the <code>presetSizes</code> are invalid.
*
- * @attr ref android.R.styleable#TextView_autoSizeText
+ * @attr ref android.R.styleable#TextView_autoSizeTextType
* @attr ref android.R.styleable#TextView_autoSizePresetSizes
*
* @see #setAutoSizeTextTypeWithDefaults(int)
@@ -1806,7 +1812,7 @@
* {@link TextView#AUTO_SIZE_TEXT_TYPE_NONE} or
* {@link TextView#AUTO_SIZE_TEXT_TYPE_UNIFORM}
*
- * @attr ref android.R.styleable#TextView_autoSizeText
+ * @attr ref android.R.styleable#TextView_autoSizeTextType
*
* @see #setAutoSizeTextTypeWithDefaults(int)
* @see #setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int)
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 7ef54a5..20a5512 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -86,7 +86,7 @@
inflater.inflate(layoutResourceId, mDelegator, true);
// hour
- mHourSpinner = (NumberPicker) delegator.findViewById(R.id.hour);
+ mHourSpinner = delegator.findViewById(R.id.hour);
mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
updateInputState();
@@ -100,17 +100,17 @@
onTimeChanged();
}
});
- mHourSpinnerInput = (EditText) mHourSpinner.findViewById(R.id.numberpicker_input);
+ mHourSpinnerInput = mHourSpinner.findViewById(R.id.numberpicker_input);
mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
// divider (only for the new widget style)
- mDivider = (TextView) mDelegator.findViewById(R.id.divider);
+ mDivider = mDelegator.findViewById(R.id.divider);
if (mDivider != null) {
setDividerText();
}
// minute
- mMinuteSpinner = (NumberPicker) mDelegator.findViewById(R.id.minute);
+ mMinuteSpinner = mDelegator.findViewById(R.id.minute);
mMinuteSpinner.setMinValue(0);
mMinuteSpinner.setMaxValue(59);
mMinuteSpinner.setOnLongPressUpdateInterval(100);
@@ -138,7 +138,7 @@
onTimeChanged();
}
});
- mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input);
+ mMinuteSpinnerInput = mMinuteSpinner.findViewById(R.id.numberpicker_input);
mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
// Get the localized am/pm strings and use them in the spinner.
@@ -173,13 +173,13 @@
onTimeChanged();
}
});
- mAmPmSpinnerInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input);
+ mAmPmSpinnerInput = mAmPmSpinner.findViewById(R.id.numberpicker_input);
mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
}
if (isAmPmAtStart()) {
// Move the am/pm view to the beginning
- ViewGroup amPmParent = (ViewGroup) delegator.findViewById(R.id.timePickerLayout);
+ ViewGroup amPmParent = delegator.findViewById(R.id.timePickerLayout);
amPmParent.removeView(amPmView);
amPmParent.addView(amPmView, 0);
// Swap layout margins if needed. They may be not symmetrical (Old Standard Theme
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 789e60b..bf0601d 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -299,7 +299,7 @@
if (mNextView == null) {
throw new RuntimeException("This Toast was not created with Toast.makeText()");
}
- TextView tv = (TextView) mNextView.findViewById(com.android.internal.R.id.message);
+ TextView tv = mNextView.findViewById(com.android.internal.R.id.message);
if (tv == null) {
throw new RuntimeException("This Toast was not created with Toast.makeText()");
}
diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java
index 69b79971..1a3ca86 100644
--- a/core/java/android/widget/ZoomButtonsController.java
+++ b/core/java/android/widget/ZoomButtonsController.java
@@ -264,7 +264,7 @@
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(com.android.internal.R.layout.zoom_container, container);
- mControls = (ZoomControls) container.findViewById(com.android.internal.R.id.zoomControls);
+ mControls = container.findViewById(com.android.internal.R.id.zoomControls);
mControls.setOnZoomInClickListener(new OnClickListener() {
public void onClick(View v) {
dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT);
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 84c8f7a..79301aa 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -23,15 +23,21 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.LabeledIntent;
+import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
import android.database.DataSetObserver;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
@@ -84,6 +90,14 @@
public class ChooserActivity extends ResolverActivity {
private static final String TAG = "ChooserActivity";
+ /**
+ * Boolean extra to change the following behavior: Normally, ChooserActivity finishes itself
+ * in onStop when launched in a new task. If this extra is set to true, we do not finish
+ * ourselves when onStop gets called.
+ */
+ public static final String EXTRA_PRIVATE_RETAIN_IN_ON_STOP
+ = "com.android.internal.app.ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP";
+
private static final boolean DEBUG = false;
private static final int QUERY_TARGET_SERVICE_LIMIT = 5;
@@ -260,6 +274,7 @@
}
mPinnedSharedPrefs = getPinnedSharedPrefs(this);
+ setRetainInOnStop(intent.getBooleanExtra(EXTRA_PRIVATE_RETAIN_IN_ON_STOP, false));
super.onCreate(savedInstanceState, target, title, defaultTitleRes, initialIntents,
null, false);
@@ -347,6 +362,7 @@
mChooserListAdapter.addServiceResults(null, Lists.newArrayList(mCallerChooserTargets));
}
mChooserRowAdapter = new ChooserRowAdapter(mChooserListAdapter);
+ mChooserRowAdapter.updateRowScales();
mChooserRowAdapter.registerDataSetObserver(new OffsetDataSetObserver(adapterView));
adapterView.setAdapter(mChooserRowAdapter);
if (listView != null) {
@@ -833,7 +849,9 @@
return false;
}
intent.setComponent(mChooserTarget.getComponentName());
- intent.putExtras(mChooserTarget.getIntentExtras());
+ if (mChooserTarget.getIntentExtras() != null) {
+ intent.putExtras(mChooserTarget.getIntentExtras());
+ }
// Important: we will ignore the target security checks in ActivityManager
// if and only if the ChooserTarget's target package is the same package
@@ -916,6 +934,8 @@
private static final int MAX_SERVICE_TARGETS = 8;
private static final int MAX_TARGETS_PER_SERVICE = 4;
+ private boolean mAreChooserShortcutsRetrieved;
+
private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
private final List<TargetInfo> mCallerTargets = new ArrayList<>();
private boolean mShowServiceTargets;
@@ -1007,6 +1027,20 @@
if (mServiceTargets != null) {
pruneServiceTargets();
}
+
+ if (DEBUG) Log.d(TAG, "Adding pushed chooser targets");
+
+ if (!mAreChooserShortcutsRetrieved) {
+ LauncherApps launcherApps = getLauncherApps();
+ LauncherApps.ShortcutQuery query = new LauncherApps.ShortcutQuery();
+ query.setIntent(getTargetIntent());
+ query.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_CHOOSER);
+ List<ShortcutInfo> shortcuts = launcherApps.getShortcuts(query, UserHandle.SYSTEM);
+ if (DEBUG) Log.d(TAG, "Adding " + shortcuts.size() + " chooser shortcuts");
+ addShortcuts(shortcuts);
+ mAreChooserShortcutsRetrieved = true;
+ }
+
if (DEBUG) Log.d(TAG, "List built querying services");
queryTargetServices(this);
}
@@ -1032,6 +1066,7 @@
public int getServiceTargetCount() {
if (!mShowServiceTargets) {
+ if (DEBUG) Log.d("TAG", "Hiding service targets");
return 0;
}
return Math.min(mServiceTargets.size(), MAX_SERVICE_TARGETS);
@@ -1123,6 +1158,71 @@
notifyDataSetChanged();
}
+ // TODO: Pushed targets need to be scored correctly
+ public void addShortcuts(List<ShortcutInfo> infos) {
+ for (ShortcutInfo info : infos) {
+ List<ChooserTarget> newTargets = new ArrayList<>();
+ final ComponentName cn = info.getActivity();
+ ActivityInfo ai;
+ ResolveInfo ri = new ResolveInfo();
+ if (cn != null) {
+ try {
+ ai = getPackageManager().getActivityInfo(cn, 0);
+ ri.activityInfo = ai;
+ UserManager userManager =
+ (UserManager) getSystemService(Context.USER_SERVICE);
+ ri.iconResourceId = ai.icon;
+ ri.labelRes = ai.labelRes;
+ ri.resolvePackageName = ai.packageName;
+ ri.activityInfo.applicationInfo = new ApplicationInfo(
+ ri.activityInfo.applicationInfo);
+ ri.activityInfo.applicationInfo = ai.applicationInfo;
+ ri.activityInfo.applicationInfo.uid = getUserId();
+ } catch (PackageManager.NameNotFoundException ignored) {
+ if (DEBUG) Log.d(TAG, "Package not found, skipping this shortcut");
+ continue;
+ }
+ }
+
+ DisplayResolveInfo resolveInfo = new DisplayResolveInfo(getTargetIntent(),
+ ri,
+ info.getShortLabel(),
+ info.getLongLabel(),
+ getTargetIntent());
+
+ int bestMatch = 0;
+ ComponentName bestComponent = null;
+ for (int i = 0; i < info.getChooserIntentFilters().length; i++) {
+ int newMatch = info.getChooserIntentFilters()[i]
+ .match(getContentResolver(), getTargetIntent(), false, TAG);
+ if (DEBUG) Log.d(TAG, "A match was found with value: " + newMatch);
+ if (newMatch > bestMatch) {
+ bestMatch = newMatch;
+ bestComponent = info.getChooserComponentNames()[i];
+ }
+ }
+ if (bestMatch == 0) {
+ Log.e(TAG, "Unexpectedly, no match was found for the provided chooser intent");
+ return;
+ }
+
+ Bundle extrasToAdd =
+ info.getChooserExtras() == null ? null: new Bundle(info.getChooserExtras());
+ if (DEBUG) Log.d(TAG, "Adding service target " + info.getShortLabel());
+ newTargets.add(new ChooserTarget(
+ info.getShortLabel(),
+ info.getIcon(),
+ 1,
+ bestComponent,
+ extrasToAdd));
+ addServiceResults(resolveInfo, newTargets);
+ }
+ if (mChooserRowAdapter != null) {
+ mChooserRowAdapter.updateRowScales();
+ }
+ setShowServiceTargets(true);
+ }
+
/**
* Set to true to reveal all service targets at once.
*/
@@ -1237,37 +1337,7 @@
@Override
public void onChanged() {
super.onChanged();
- final int rcount = getServiceTargetRowCount();
- if (mServiceTargetScale == null
- || mServiceTargetScale.length != rcount) {
- RowScale[] old = mServiceTargetScale;
- int oldRCount = old != null ? old.length : 0;
- mServiceTargetScale = new RowScale[rcount];
- if (old != null && rcount > 0) {
- System.arraycopy(old, 0, mServiceTargetScale, 0,
- Math.min(old.length, rcount));
- }
-
- for (int i = rcount; i < oldRCount; i++) {
- old[i].cancelAnimation();
- }
-
- for (int i = oldRCount; i < rcount; i++) {
- final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
- .setInterpolator(mInterpolator);
- mServiceTargetScale[i] = rs;
- }
-
- // Start the animations in a separate loop.
- // The process of starting animations will result in
- // binding views to set up initial values, and we must
- // have ALL of the new RowScale objects created above before
- // we get started.
- for (int i = oldRCount; i < rcount; i++) {
- mServiceTargetScale[i].startAnimation();
- }
- }
-
+ updateRowScales();
notifyDataSetChanged();
}
@@ -1284,6 +1354,40 @@
});
}
+ void updateRowScales() {
+ final int rcount = getServiceTargetRowCount();
+ if (mServiceTargetScale == null
+ || mServiceTargetScale.length != rcount) {
+ if (DEBUG) Log.d(TAG, "Row scales need adjusting to " + rcount + " rows.");
+ RowScale[] old = mServiceTargetScale;
+ int oldRCount = old != null ? old.length : 0;
+ mServiceTargetScale = new RowScale[rcount];
+ if (old != null && rcount > 0) {
+ System.arraycopy(old, 0, mServiceTargetScale, 0,
+ Math.min(old.length, rcount));
+ }
+
+ for (int i = rcount; i < oldRCount; i++) {
+ old[i].cancelAnimation();
+ }
+
+ for (int i = oldRCount; i < rcount; i++) {
+ final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
+ .setInterpolator(mInterpolator);
+ mServiceTargetScale[i] = rs;
+ }
+
+ // Start the animations in a separate loop.
+ // The process of starting animations will result in
+ // binding views to set up initial values, and we must
+ // have ALL of the new RowScale objects created above before
+ // we get started.
+ for (int i = oldRCount; i < rcount; i++) {
+ mServiceTargetScale[i].startAnimation();
+ }
+ }
+ }
+
private float getRowScale(int rowPosition) {
final int start = getCallerTargetRowCount();
final int end = start + getServiceTargetRowCount();
@@ -1554,6 +1658,10 @@
}
}
+ public LauncherApps getLauncherApps() {
+ return (LauncherApps) getSystemService(Context.LAUNCHER_APPS_SERVICE);
+ }
+
static class ServiceResultInfo {
public final DisplayResolveInfo originalTarget;
public final List<ChooserTarget> resultTargets;
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 0b1f0aa..3f1c9ad 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -116,6 +116,10 @@
private Runnable mPostListReadyRunnable;
private boolean mRegistered;
+
+ /** See {@link #setRetainInOnStop}. */
+ private boolean mRetainInOnStop;
+
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@Override public void onSomePackagesChanged() {
mAdapter.handlePackagesChanged();
@@ -502,7 +506,7 @@
}
final Intent intent = getIntent();
if ((intent.getFlags() & FLAG_ACTIVITY_NEW_TASK) != 0 && !isVoiceInteraction()
- && !mResolvingHome) {
+ && !mResolvingHome && !mRetainInOnStop) {
// This resolver is in the unusual situation where it has been
// launched at the top of a new task. We don't let it be added
// to the recent tasks shown to the user, and we need to make sure
@@ -531,16 +535,7 @@
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
- if (mSupportsAlwaysUseOption) {
- final int checkedPos = mAdapterView.getCheckedItemPosition();
- final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
- mLastSelected = checkedPos;
- setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
- mOnceButton.setEnabled(hasValidSelection);
- if (hasValidSelection) {
- mAdapterView.setSelection(checkedPos);
- }
- }
+ resetAlwaysOrOnceButtonBar();
}
private boolean hasManagedProfile() {
@@ -577,7 +572,13 @@
boolean enabled = false;
if (hasValidSelection) {
ResolveInfo ri = mAdapter.resolveInfoForPosition(checkedPos, filtered);
- if (ri.targetUserId == UserHandle.USER_CURRENT) {
+ if (ri == null) {
+ Log.e(TAG, "Invalid position supplied to setAlwaysButtonEnabled");
+ return;
+ } else if (ri.targetUserId != UserHandle.USER_CURRENT) {
+ Log.e(TAG, "Attempted to set selection to resolve info for another user");
+ return;
+ } else {
enabled = true;
}
}
@@ -1029,6 +1030,14 @@
}
/**
+ * If {@code retainInOnStop} is set to true, we will not finish ourselves when onStop gets
+ * called and we are launched in a new task.
+ */
+ protected void setRetainInOnStop(boolean retainInOnStop) {
+ mRetainInOnStop = retainInOnStop;
+ }
+
+ /**
* Check a simple match for the component of two ResolveInfos.
*/
static boolean resolveInfoMatch(ResolveInfo lhs, ResolveInfo rhs) {
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
new file mode 100644
index 0000000..3ac5a72
--- /dev/null
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.content;
+
+import android.annotation.CallSuper;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.MatrixCursor.RowBuilder;
+import android.graphics.Point;
+import android.net.Uri;
+import android.os.CancellationSignal;
+import android.os.FileObserver;
+import android.os.FileUtils;
+import android.os.Handler;
+import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsProvider;
+import android.provider.MediaStore;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.webkit.MimeTypeMap;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A helper class for {@link android.provider.DocumentsProvider} to perform file operations on local
+ * files.
+ */
+public abstract class FileSystemProvider extends DocumentsProvider {
+
+ private static final String TAG = "FileSystemProvider";
+
+ private static final boolean LOG_INOTIFY = false;
+
+ private String[] mDefaultProjection;
+
+ @GuardedBy("mObservers")
+ private final ArrayMap<File, DirectoryObserver> mObservers = new ArrayMap<>();
+
+ private Handler mHandler;
+
+ protected abstract File getFileForDocId(String docId, boolean visible)
+ throws FileNotFoundException;
+
+ protected abstract String getDocIdForFile(File file) throws FileNotFoundException;
+
+ protected abstract Uri buildNotificationUri(String docId);
+
+ @Override
+ public boolean onCreate() {
+ throw new UnsupportedOperationException(
+ "Subclass should override this and call onCreate(defaultDocumentProjection)");
+ }
+
+ @CallSuper
+ protected void onCreate(String[] defaultProjection) {
+ mHandler = new Handler();
+ mDefaultProjection = defaultProjection;
+ }
+
+ @Override
+ public boolean isChildDocument(String parentDocId, String docId) {
+ try {
+ final File parent = getFileForDocId(parentDocId).getCanonicalFile();
+ final File doc = getFileForDocId(docId).getCanonicalFile();
+ return FileUtils.contains(parent, doc);
+ } catch (IOException e) {
+ throw new IllegalArgumentException(
+ "Failed to determine if " + docId + " is child of " + parentDocId + ": " + e);
+ }
+ }
+
+ protected final List<String> findDocumentPath(File parent, File doc)
+ throws FileNotFoundException {
+
+ if (!doc.exists()) {
+ throw new FileNotFoundException(doc + " is not found.");
+ }
+
+ if (!FileUtils.contains(parent, doc)) {
+ throw new FileNotFoundException(doc + " is not found under " + parent);
+ }
+
+ LinkedList<String> path = new LinkedList<>();
+ while (doc != null && FileUtils.contains(parent, doc)) {
+ path.addFirst(getDocIdForFile(doc));
+
+ doc = doc.getParentFile();
+ }
+
+ return path;
+ }
+
+ @Override
+ public String createDocument(String docId, String mimeType, String displayName)
+ throws FileNotFoundException {
+ displayName = FileUtils.buildValidFatFilename(displayName);
+
+ final File parent = getFileForDocId(docId);
+ if (!parent.isDirectory()) {
+ throw new IllegalArgumentException("Parent document isn't a directory");
+ }
+
+ final File file = FileUtils.buildUniqueFile(parent, mimeType, displayName);
+ if (Document.MIME_TYPE_DIR.equals(mimeType)) {
+ if (!file.mkdir()) {
+ throw new IllegalStateException("Failed to mkdir " + file);
+ }
+ } else {
+ try {
+ if (!file.createNewFile()) {
+ throw new IllegalStateException("Failed to touch " + file);
+ }
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to touch " + file + ": " + e);
+ }
+ }
+
+ return getDocIdForFile(file);
+ }
+
+ @Override
+ public String renameDocument(String docId, String displayName) throws FileNotFoundException {
+ // Since this provider treats renames as generating a completely new
+ // docId, we're okay with letting the MIME type change.
+ displayName = FileUtils.buildValidFatFilename(displayName);
+
+ final File before = getFileForDocId(docId);
+ final File after = FileUtils.buildUniqueFile(before.getParentFile(), displayName);
+ final File visibleFileBefore = getFileForDocId(docId, true);
+ if (!before.renameTo(after)) {
+ throw new IllegalStateException("Failed to rename to " + after);
+ }
+ removeFromMediaStore(visibleFileBefore);
+
+ final String afterDocId = getDocIdForFile(after);
+ scanFile(getFileForDocId(afterDocId, true));
+
+ if (!TextUtils.equals(docId, afterDocId)) {
+ return afterDocId;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void deleteDocument(String docId) throws FileNotFoundException {
+ final File file = getFileForDocId(docId);
+ final File visibleFile = getFileForDocId(docId, true);
+
+ final boolean isDirectory = file.isDirectory();
+ if (isDirectory) {
+ FileUtils.deleteContents(file);
+ }
+ if (!file.delete()) {
+ throw new IllegalStateException("Failed to delete " + file);
+ }
+
+ removeFromMediaStore(visibleFile);
+ }
+
+ @Override
+ public String moveDocument(String sourceDocumentId, String sourceParentDocumentId,
+ String targetParentDocumentId)
+ throws FileNotFoundException {
+ final File before = getFileForDocId(sourceDocumentId);
+ final File after = new File(getFileForDocId(targetParentDocumentId), before.getName());
+ final File visibleFileBefore = getFileForDocId(sourceDocumentId, true);
+
+ if (after.exists()) {
+ throw new IllegalStateException("Already exists " + after);
+ }
+ if (!before.renameTo(after)) {
+ throw new IllegalStateException("Failed to move to " + after);
+ }
+
+ // Notify media store to update its content
+ removeFromMediaStore(visibleFileBefore);
+ final String docId = getDocIdForFile(after);
+ scanFile(getFileForDocId(docId, true));
+
+ return docId;
+ }
+
+ private void removeFromMediaStore(File visibleFile) throws FileNotFoundException {
+ if (visibleFile != null) {
+ final ContentResolver resolver = getContext().getContentResolver();
+ final Uri externalUri = MediaStore.Files.getContentUri("external");
+
+ // Remove media store entries for any files inside this directory, using
+ // path prefix match. Logic borrowed from MtpDatabase.
+ if (visibleFile.isDirectory()) {
+ final String path = visibleFile.getAbsolutePath() + "/";
+ resolver.delete(externalUri,
+ "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)",
+ new String[] { path + "%", Integer.toString(path.length()), path });
+ }
+
+ // Remove media store entry for this exact file.
+ final String path = visibleFile.getAbsolutePath();
+ resolver.delete(externalUri,
+ "_data LIKE ?1 AND lower(_data)=lower(?2)",
+ new String[] { path, path });
+ }
+ }
+
+ @Override
+ public Cursor queryDocument(String documentId, String[] projection)
+ throws FileNotFoundException {
+ final MatrixCursor result = new MatrixCursor(resolveProjection(projection));
+ includeFile(result, documentId, null);
+ return result;
+ }
+
+ @Override
+ public Cursor queryChildDocuments(
+ String parentDocumentId, String[] projection, String sortOrder)
+ throws FileNotFoundException {
+
+ final File parent = getFileForDocId(parentDocumentId);
+ final MatrixCursor result = new DirectoryCursor(
+ resolveProjection(projection), parentDocumentId, parent);
+ for (File file : parent.listFiles()) {
+ includeFile(result, null, file);
+ }
+ return result;
+ }
+
+ /**
+ * Searches documents under the given folder.
+ *
+ * To avoid runtime explosion only returns the at most 23 items.
+ *
+ * @param folder the root folder where recursive search begins
+ * @param query the search condition used to match file names
+ * @param projection projection of the returned cursor
+ * @param exclusion absolute file paths to exclude from result
+ * @return cursor containing search result
+ * @throws FileNotFoundException when root folder doesn't exist or search fails
+ */
+ protected final Cursor querySearchDocuments(
+ File folder, String query, String[] projection, Set<String> exclusion)
+ throws FileNotFoundException {
+
+ query = query.toLowerCase();
+ final MatrixCursor result = new MatrixCursor(resolveProjection(projection));
+ final LinkedList<File> pending = new LinkedList<>();
+ pending.add(folder);
+ while (!pending.isEmpty() && result.getCount() < 24) {
+ final File file = pending.removeFirst();
+ if (file.isDirectory()) {
+ for (File child : file.listFiles()) {
+ pending.add(child);
+ }
+ }
+ if (file.getName().toLowerCase().contains(query)
+ && !exclusion.contains(file.getAbsolutePath())) {
+ includeFile(result, null, file);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public String getDocumentType(String documentId) throws FileNotFoundException {
+ final File file = getFileForDocId(documentId);
+ return getTypeForFile(file);
+ }
+
+ @Override
+ public ParcelFileDescriptor openDocument(
+ String documentId, String mode, CancellationSignal signal)
+ throws FileNotFoundException {
+ final File file = getFileForDocId(documentId);
+ final File visibleFile = getFileForDocId(documentId, true);
+
+ final int pfdMode = ParcelFileDescriptor.parseMode(mode);
+ if (pfdMode == ParcelFileDescriptor.MODE_READ_ONLY || visibleFile == null) {
+ return ParcelFileDescriptor.open(file, pfdMode);
+ } else {
+ try {
+ // When finished writing, kick off media scanner
+ return ParcelFileDescriptor.open(
+ file, pfdMode, mHandler, (IOException e) -> scanFile(visibleFile));
+ } catch (IOException e) {
+ throw new FileNotFoundException("Failed to open for writing: " + e);
+ }
+ }
+ }
+
+ private void scanFile(File visibleFile) {
+ final Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
+ intent.setData(Uri.fromFile(visibleFile));
+ getContext().sendBroadcast(intent);
+ }
+
+ @Override
+ public AssetFileDescriptor openDocumentThumbnail(
+ String documentId, Point sizeHint, CancellationSignal signal)
+ throws FileNotFoundException {
+ final File file = getFileForDocId(documentId);
+ return DocumentsContract.openImageThumbnail(file);
+ }
+
+ protected RowBuilder includeFile(MatrixCursor result, String docId, File file)
+ throws FileNotFoundException {
+ if (docId == null) {
+ docId = getDocIdForFile(file);
+ } else {
+ file = getFileForDocId(docId);
+ }
+
+ int flags = 0;
+
+ if (file.canWrite()) {
+ if (file.isDirectory()) {
+ flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
+ flags |= Document.FLAG_SUPPORTS_DELETE;
+ flags |= Document.FLAG_SUPPORTS_RENAME;
+ flags |= Document.FLAG_SUPPORTS_MOVE;
+ } else {
+ flags |= Document.FLAG_SUPPORTS_WRITE;
+ flags |= Document.FLAG_SUPPORTS_DELETE;
+ flags |= Document.FLAG_SUPPORTS_RENAME;
+ flags |= Document.FLAG_SUPPORTS_MOVE;
+ }
+ }
+
+ final String mimeType = getTypeForFile(file);
+ final String displayName = file.getName();
+ if (mimeType.startsWith("image/")) {
+ flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
+ }
+
+ final RowBuilder row = result.newRow();
+ row.add(Document.COLUMN_DOCUMENT_ID, docId);
+ row.add(Document.COLUMN_DISPLAY_NAME, displayName);
+ row.add(Document.COLUMN_SIZE, file.length());
+ row.add(Document.COLUMN_MIME_TYPE, mimeType);
+ row.add(Document.COLUMN_FLAGS, flags);
+
+ // Only publish dates reasonably after epoch
+ long lastModified = file.lastModified();
+ if (lastModified > 31536000000L) {
+ row.add(Document.COLUMN_LAST_MODIFIED, lastModified);
+ }
+
+ // Return the row builder just in case any subclass want to add more stuff to it.
+ return row;
+ }
+
+ private static String getTypeForFile(File file) {
+ if (file.isDirectory()) {
+ return Document.MIME_TYPE_DIR;
+ } else {
+ return getTypeForName(file.getName());
+ }
+ }
+
+ private static String getTypeForName(String name) {
+ final int lastDot = name.lastIndexOf('.');
+ if (lastDot >= 0) {
+ final String extension = name.substring(lastDot + 1).toLowerCase();
+ final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
+ if (mime != null) {
+ return mime;
+ }
+ }
+
+ return "application/octet-stream";
+ }
+
+ protected final File getFileForDocId(String docId) throws FileNotFoundException {
+ return getFileForDocId(docId, false);
+ }
+
+ private String[] resolveProjection(String[] projection) {
+ return projection == null ? mDefaultProjection : projection;
+ }
+
+ private void startObserving(File file, Uri notifyUri) {
+ synchronized (mObservers) {
+ DirectoryObserver observer = mObservers.get(file);
+ if (observer == null) {
+ observer = new DirectoryObserver(
+ file, getContext().getContentResolver(), notifyUri);
+ observer.startWatching();
+ mObservers.put(file, observer);
+ }
+ observer.mRefCount++;
+
+ if (LOG_INOTIFY) Log.d(TAG, "after start: " + observer);
+ }
+ }
+
+ private void stopObserving(File file) {
+ synchronized (mObservers) {
+ DirectoryObserver observer = mObservers.get(file);
+ if (observer == null) return;
+
+ observer.mRefCount--;
+ if (observer.mRefCount == 0) {
+ mObservers.remove(file);
+ observer.stopWatching();
+ }
+
+ if (LOG_INOTIFY) Log.d(TAG, "after stop: " + observer);
+ }
+ }
+
+ private static class DirectoryObserver extends FileObserver {
+ private static final int NOTIFY_EVENTS = ATTRIB | CLOSE_WRITE | MOVED_FROM | MOVED_TO
+ | CREATE | DELETE | DELETE_SELF | MOVE_SELF;
+
+ private final File mFile;
+ private final ContentResolver mResolver;
+ private final Uri mNotifyUri;
+
+ private int mRefCount = 0;
+
+ public DirectoryObserver(File file, ContentResolver resolver, Uri notifyUri) {
+ super(file.getAbsolutePath(), NOTIFY_EVENTS);
+ mFile = file;
+ mResolver = resolver;
+ mNotifyUri = notifyUri;
+ }
+
+ @Override
+ public void onEvent(int event, String path) {
+ if ((event & NOTIFY_EVENTS) != 0) {
+ if (LOG_INOTIFY) Log.d(TAG, "onEvent() " + event + " at " + path);
+ mResolver.notifyChange(mNotifyUri, null, false);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "DirectoryObserver{file=" + mFile.getAbsolutePath() + ", ref=" + mRefCount + "}";
+ }
+ }
+
+ private class DirectoryCursor extends MatrixCursor {
+ private final File mFile;
+
+ public DirectoryCursor(String[] columnNames, String docId, File file) {
+ super(columnNames);
+
+ final Uri notifyUri = buildNotificationUri(docId);
+ setNotificationUri(getContext().getContentResolver(), notifyUri);
+
+ mFile = file;
+ startObserving(mFile, notifyUri);
+ }
+
+ @Override
+ public void close() {
+ super.close();
+ stopObserving(mFile);
+ }
+ }
+}
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index be10608df..d67cef3 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -23,6 +23,8 @@
import android.text.TextUtils;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -1495,7 +1497,7 @@
}
/**
- * @return number of log records
+ * @return the number of log records currently readable
*/
public final int getLogRecSize() {
// mSmHandler can be null if the state machine has quit.
@@ -1505,6 +1507,17 @@
}
/**
+ * @return the number of log records we can store
+ */
+ @VisibleForTesting
+ public final int getLogRecMaxSize() {
+ // mSmHandler can be null if the state machine has quit.
+ SmHandler smh = mSmHandler;
+ if (smh == null) return 0;
+ return smh.mLogRecords.mMaxSize;
+ }
+
+ /**
* @return the total number of records processed
*/
public final int getLogRecCount() {
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index 43005e6..919cf99 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -115,7 +115,6 @@
setEnabled(itemData.isEnabled());
setSubMenuArrowVisible(itemData.hasSubMenu());
setContentDescription(itemData.getContentDescription());
- setTooltipText(itemData.getTooltipText());
}
public void setForceShowIcon(boolean forceShow) {
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 817b186..79b0cd1 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -1195,6 +1195,8 @@
}
setButtonTagAndClickListener(menuItemButton, menuItem);
+ // Set tooltips for main panel items, but not overflow items (b/35726766).
+ menuItemButton.setTooltipText(menuItem.getTooltipText());
mMainPanel.addView(menuItemButton);
final ViewGroup.LayoutParams params = menuItemButton.getLayoutParams();
params.width = menuItemButtonWidth + extraPadding / 2;
@@ -1635,7 +1637,6 @@
buttonText.setPaddingRelative(iconTextSpacing, 0, 0, 0);
}
}
- menuItemButton.setTooltipText(menuItem.getTooltipText());
final CharSequence contentDescription = menuItem.getContentDescription();
if (TextUtils.isEmpty(contentDescription)) {
menuItemButton.setContentDescription(menuItem.getTitle());
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index ae2e0ac..cc1c65e 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -278,7 +278,8 @@
public LockPatternView(Context context, AttributeSet attrs) {
super(context, attrs);
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LockPatternView);
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LockPatternView,
+ R.attr.lockPatternStyle, R.style.Widget_LockPatternView);
final String aspect = a.getString(R.styleable.LockPatternView_aspect);
@@ -298,12 +299,9 @@
mPathPaint.setAntiAlias(true);
mPathPaint.setDither(true);
- mRegularColor = context.getColor(R.color.lock_pattern_view_regular_color);
- mErrorColor = context.getColor(R.color.lock_pattern_view_error_color);
- mSuccessColor = context.getColor(R.color.lock_pattern_view_success_color);
- mRegularColor = a.getColor(R.styleable.LockPatternView_regularColor, mRegularColor);
- mErrorColor = a.getColor(R.styleable.LockPatternView_errorColor, mErrorColor);
- mSuccessColor = a.getColor(R.styleable.LockPatternView_successColor, mSuccessColor);
+ mRegularColor = a.getColor(R.styleable.LockPatternView_regularColor, 0);
+ mErrorColor = a.getColor(R.styleable.LockPatternView_errorColor, 0);
+ mSuccessColor = a.getColor(R.styleable.LockPatternView_successColor, 0);
int pathColor = a.getColor(R.styleable.LockPatternView_pathColor, mRegularColor);
mPathPaint.setColor(pathColor);
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index e84cc27..e224b17 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -748,6 +748,10 @@
final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
final int heightSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);
final int widthPadding = getPaddingLeft() + getPaddingRight();
+
+ // Currently we allot more height than is really needed so that the entirety of the
+ // sheet may be pulled up.
+ // TODO: Restrict the height here to be the right value.
int heightUsed = getPaddingTop() + getPaddingBottom();
// Measure always-show children first.
@@ -757,7 +761,7 @@
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp.alwaysShow && child.getVisibility() != GONE) {
measureChildWithMargins(child, widthSpec, widthPadding, heightSpec, heightUsed);
- heightUsed += getHeightUsed(child);
+ heightUsed += child.getMeasuredHeight();
}
}
@@ -769,7 +773,7 @@
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (!lp.alwaysShow && child.getVisibility() != GONE) {
measureChildWithMargins(child, widthSpec, widthPadding, heightSpec, heightUsed);
- heightUsed += getHeightUsed(child);
+ heightUsed += child.getMeasuredHeight();
}
}
@@ -785,36 +789,6 @@
setMeasuredDimension(sourceWidth, heightSize);
}
- private int getHeightUsed(View child) {
- // This method exists because we're taking a fast path at measuring ListViews that
- // lets us get away with not doing the more expensive wrap_content measurement which
- // imposes double child view measurement costs. If we're looking at a ListView, we can
- // check against the lowest child view plus padding and margin instead of the actual
- // measured height of the ListView. This lets the ListView hang off the edge when
- // all of the content would fit on-screen.
-
- int heightUsed = child.getMeasuredHeight();
- if (child instanceof AbsListView) {
- final AbsListView lv = (AbsListView) child;
- final int lvPaddingBottom = lv.getPaddingBottom();
-
- int lowest = 0;
- for (int i = 0, N = lv.getChildCount(); i < N; i++) {
- final int bottom = lv.getChildAt(i).getBottom() + lvPaddingBottom;
- if (bottom > lowest) {
- lowest = bottom;
- }
- }
-
- if (lowest < heightUsed) {
- heightUsed = lowest;
- }
- }
-
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
- return lp.topMargin + heightUsed + lp.bottomMargin;
- }
-
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int width = getWidth();
diff --git a/core/java/com/android/internal/widget/WatchHeaderListView.java b/core/java/com/android/internal/widget/WatchHeaderListView.java
index 7e91537..0654454 100644
--- a/core/java/com/android/internal/widget/WatchHeaderListView.java
+++ b/core/java/com/android/internal/widget/WatchHeaderListView.java
@@ -91,13 +91,14 @@
}
@Override
- protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+ protected <T extends View> T findViewByPredicateTraversal(
+ Predicate<View> predicate, View childToSkip) {
View v = super.findViewByPredicateTraversal(predicate, childToSkip);
if (v == null && mTopPanel != null && mTopPanel != childToSkip
&& !mTopPanel.isRootNamespace()) {
- return mTopPanel.findViewByPredicate(predicate);
+ return (T) mTopPanel.findViewByPredicate(predicate);
}
- return v;
+ return (T) v;
}
@Override
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index c090a75..49024b6 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -63,27 +63,27 @@
return 0;
}
NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
- minikin::FontFamily* family = new minikin::FontFamily(
- builder->langId, builder->variant, std::move(builder->fonts));
+ FontFamilyWrapper* family = new FontFamilyWrapper(
+ std::make_shared<minikin::FontFamily>(
+ builder->langId, builder->variant, std::move(builder->fonts)));
delete builder;
return reinterpret_cast<jlong>(family);
}
static void FontFamily_abort(jlong builderPtr) {
NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
- minikin::Font::clearElementsWithLock(&builder->fonts);
delete builder;
}
static void FontFamily_unref(jlong familyPtr) {
- minikin::FontFamily* fontFamily = reinterpret_cast<minikin::FontFamily*>(familyPtr);
- fontFamily->Unref();
+ FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(familyPtr);
+ delete family;
}
static void addSkTypeface(jlong builderPtr, sk_sp<SkTypeface> face, const void* fontData,
size_t fontSize, int ttcIndex, jint givenWeight, jboolean givenItalic) {
- minikin::MinikinFont* minikinFont =
- new MinikinFontSkia(std::move(face), fontData, fontSize, ttcIndex,
+ std::shared_ptr<minikin::MinikinFont> minikinFont =
+ std::make_shared<MinikinFontSkia>(std::move(face), fontData, fontSize, ttcIndex,
std::vector<minikin::FontVariation>());
NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
int weight = givenWeight / 100;
@@ -96,8 +96,8 @@
}
}
- builder->fonts.push_back(minikin::Font(minikinFont, minikin::FontStyle(weight, italic)));
- minikinFont->Unref();
+ builder->fonts.push_back(minikin::Font(
+ std::move(minikinFont), minikin::FontStyle(weight, italic)));
}
static void release_global_ref(const void* /*data*/, void* context) {
@@ -208,13 +208,12 @@
ALOGE("addFont failed to create font, invalid request");
return false;
}
- minikin::MinikinFont* minikinFont =
- new MinikinFontSkia(std::move(face), fontPtr, fontSize, ttcIndex,
+ std::shared_ptr<minikin::MinikinFont> minikinFont =
+ std::make_shared<MinikinFontSkia>(std::move(face), fontPtr, fontSize, ttcIndex,
std::vector<minikin::FontVariation>());
NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
- builder->fonts.push_back(minikin::Font(minikinFont,
+ builder->fonts.push_back(minikin::Font(std::move(minikinFont),
minikin::FontStyle(weight / 100, isItalic)));
- minikinFont->Unref();
return true;
}
diff --git a/core/jni/android/graphics/FontUtils.h b/core/jni/android/graphics/FontUtils.h
index 8f44b1e..9eaaa49 100644
--- a/core/jni/android/graphics/FontUtils.h
+++ b/core/jni/android/graphics/FontUtils.h
@@ -18,9 +18,19 @@
#define _ANDROID_GRAPHICS_FONT_UTILS_H_
#include <jni.h>
+#include <memory>
+
+namespace minikin {
+class FontFamily;
+} // namespace minikin
namespace android {
+struct FontFamilyWrapper {
+ FontFamilyWrapper(std::shared_ptr<minikin::FontFamily>&& family) : family(family) {}
+ std::shared_ptr<minikin::FontFamily> family;
+};
+
// Utility wrapper for java.util.List
class ListHelper {
public:
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index bdf79d3..1846237 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -300,8 +300,8 @@
static void getTextPath(JNIEnv* env, Paint* paint, Typeface* typeface, const jchar* text,
jint count, jint bidiFlags, jfloat x, jfloat y, SkPath* path) {
- minikin::Layout layout;
- MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count);
+ minikin::Layout layout = MinikinUtils::doLayout(
+ paint, bidiFlags, typeface, text, 0, count, count);
size_t nGlyphs = layout.nGlyphs();
uint16_t* glyphs = new uint16_t[nGlyphs];
SkPoint* pos = new SkPoint[nGlyphs];
@@ -344,8 +344,8 @@
SkRect r;
SkIRect ir;
- minikin::Layout layout;
- MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, 0, count, count);
+ minikin::Layout layout = MinikinUtils::doLayout(
+ &paint, bidiFlags, typeface, text, 0, count, count);
minikin::MinikinRect rect;
layout.getBounds(&rect);
r.fLeft = rect.mLeft;
@@ -459,9 +459,8 @@
nChars++;
prevCp = cp;
}
- minikin::Layout layout;
- MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, str.get(), 0, str.size(),
- str.size());
+ minikin::Layout layout = MinikinUtils::doLayout(
+ paint, bidiFlags, typeface, str.get(), 0, str.size(), str.size());
size_t nGlyphs = countNonSpaceGlyphs(layout);
if (nGlyphs != 1 && nChars > 1) {
// multiple-character input, and was not a ligature
@@ -480,8 +479,8 @@
// since ZZ is reserved for unknown or invalid territory.
// U+1F1FF (REGIONAL INDICATOR SYMBOL LETTER Z) is \uD83C\uDDFF in UTF16.
static const jchar ZZ_FLAG_STR[] = { 0xD83C, 0xDDFF, 0xD83C, 0xDDFF };
- minikin::Layout zzLayout;
- MinikinUtils::doLayout(&zzLayout, paint, bidiFlags, typeface, ZZ_FLAG_STR, 0, 4, 4);
+ minikin::Layout zzLayout = MinikinUtils::doLayout(
+ paint, bidiFlags, typeface, ZZ_FLAG_STR, 0, 4, 4);
if (zzLayout.nGlyphs() != 1 || layoutContainsNotdef(zzLayout)) {
// The font collection doesn't have a glyph for unknown flag. Just return true.
return true;
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index 0a0fce3e..0cdc74f 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -67,9 +67,7 @@
static void Typeface_unref(JNIEnv* env, jobject obj, jlong faceHandle) {
Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
- if (face != NULL) {
- face->unref();
- }
+ delete face;
}
static jint Typeface_getStyle(JNIEnv* env, jobject obj, jlong faceHandle) {
@@ -79,12 +77,13 @@
static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray) {
ScopedLongArrayRO families(env, familyArray);
- std::vector<minikin::FontFamily*> familyVec;
+ std::vector<std::shared_ptr<minikin::FontFamily>> familyVec;
+ familyVec.reserve(families.size());
for (size_t i = 0; i < families.size(); i++) {
- minikin::FontFamily* family = reinterpret_cast<minikin::FontFamily*>(families[i]);
- familyVec.push_back(family);
+ FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
+ familyVec.emplace_back(family->family);
}
- return reinterpret_cast<jlong>(Typeface::createFromFamilies(familyVec));
+ return reinterpret_cast<jlong>(Typeface::createFromFamilies(std::move(familyVec)));
}
static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) {
diff --git a/core/jni/android_hardware_HardwareBuffer.cpp b/core/jni/android_hardware_HardwareBuffer.cpp
index b26b6e1..b91bd5c 100644
--- a/core/jni/android_hardware_HardwareBuffer.cpp
+++ b/core/jni/android_hardware_HardwareBuffer.cpp
@@ -46,7 +46,7 @@
// ----------------------------------------------------------------------------
// Debug
-static const bool kDebugGraphicBuffer = false;
+static constexpr bool kDebugGraphicBuffer = false;
// ----------------------------------------------------------------------------
// Types
@@ -92,8 +92,8 @@
}
uint64_t producerUsage = 0;
uint64_t consumerUsage = 0;
- android_hardware_HardwareBuffer_convertToGrallocUsageBits(usage, 0, &producerUsage,
- &consumerUsage);
+ android_hardware_HardwareBuffer_convertToGrallocUsageBits(&producerUsage, &consumerUsage, usage,
+ 0);
status_t error;
sp<GraphicBuffer> buffer(alloc->createGraphicBuffer(width, height, pixelFormat,
layers, producerUsage, consumerUsage,
@@ -155,8 +155,11 @@
static jlong android_hardware_HardwareBuffer_getUsage(JNIEnv* env,
jobject clazz, jlong nativeObject) {
GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject);
- return android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
+ uint64_t usage0 = 0;
+ uint64_t usage1 = 0;
+ android_hardware_HardwareBuffer_convertFromGrallocUsageBits(&usage0, &usage1,
buffer->getUsage(), buffer->getUsage());
+ return usage0;
}
// ----------------------------------------------------------------------------
@@ -228,15 +231,14 @@
return AHardwareBuffer_convertToPixelFormat(format);
}
-void android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t usage0,
- uint64_t /*usage1*/, uint64_t* outProducerUsage,
- uint64_t* outConsumerUsage) {
- AHardwareBuffer_convertToGrallocUsageBits(usage0, outProducerUsage, outConsumerUsage);
+void android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t* outProducerUsage,
+ uint64_t* outConsumerUsage, uint64_t usage0, uint64_t usage1) {
+ AHardwareBuffer_convertToGrallocUsageBits(outProducerUsage, outConsumerUsage, usage0, usage1);
}
-uint64_t android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
- uint64_t producerUsage, uint64_t consumerUsage) {
- return AHardwareBuffer_convertFromGrallocUsageBits(producerUsage, consumerUsage);
+void android_hardware_HardwareBuffer_convertFromGrallocUsageBits(uint64_t* outUsage0,
+ uint64_t* outUsage1, uint64_t producerUsage, uint64_t consumerUsage) {
+ AHardwareBuffer_convertFromGrallocUsageBits(outUsage0, outUsage1, producerUsage, consumerUsage);
}
} // namespace android
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index eaf9e91..4322105 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -1021,17 +1021,13 @@
env->ReleaseStringCritical(fileName, str);
}
- int fd = open(fileName8.string(), O_CREAT | O_WRONLY | O_NOFOLLOW, 0666); /* -rw-rw-rw- */
+ int fd = open(fileName8.string(), O_CREAT | O_WRONLY | O_NOFOLLOW | O_CLOEXEC | O_APPEND, 0666);
if (fd < 0) {
fprintf(stderr, "Can't open %s: %s\n", fileName8.string(), strerror(errno));
return;
}
- if (lseek(fd, 0, SEEK_END) < 0) {
- fprintf(stderr, "lseek: %s\n", strerror(errno));
- } else {
- dump_backtrace_to_file_timeout(pid, fd, timeoutSecs);
- }
+ dump_backtrace_to_file_timeout(pid, fd, timeoutSecs);
close(fd);
}
diff --git a/core/jni/android_os_seccomp.cpp b/core/jni/android_os_seccomp.cpp
index f1bc76e..dd5622d 100644
--- a/core/jni/android_os_seccomp.cpp
+++ b/core/jni/android_os_seccomp.cpp
@@ -14,128 +14,11 @@
* limitations under the License.
*/
-#include "JNIHelp.h"
#include "core_jni_helpers.h"
#include "JniConstants.h"
#include "utils/Log.h"
-#include "utils/misc.h"
-
-#if defined __arm__ || defined __aarch64__
-
-#include <vector>
-
-#include <sys/prctl.h>
-
-#include <linux/unistd.h>
-#include <linux/audit.h>
-#include <linux/filter.h>
-#include <linux/seccomp.h>
-
#include "seccomp_policy.h"
-#define syscall_nr (offsetof(struct seccomp_data, nr))
-#define arch_nr (offsetof(struct seccomp_data, arch))
-
-typedef std::vector<sock_filter> filter;
-
-// We want to keep the below inline functions for debugging and future
-// development even though they are not all sed currently.
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-function"
-
-static inline void Kill(filter& f) {
- f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL));
-}
-
-static inline void Trap(filter& f) {
- f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRAP));
-}
-
-static inline void Error(filter& f, __u16 retcode) {
- f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO + retcode));
-}
-
-inline static void Trace(filter& f) {
- f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE));
-}
-
-inline static void Allow(filter& f) {
- f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW));
-}
-
-#pragma clang diagnostic pop
-
-inline static void ExamineSyscall(filter& f) {
- f.push_back(BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_nr));
-}
-
-inline static int SetValidateArchitectureJumpTarget(size_t offset, filter& f) {
- size_t jump_length = f.size() - offset - 1;
- auto u8_jump_length = (__u8) jump_length;
- if (u8_jump_length != jump_length) {
- ALOGE("Can't set jump greater than 255 - actual jump is %zu",
- jump_length);
- return -1;
- }
- f[offset] = BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_ARM, u8_jump_length, 0);
- return 0;
-}
-
-inline static size_t ValidateArchitectureAndJumpIfNeeded(filter& f) {
- f.push_back(BPF_STMT(BPF_LD|BPF_W|BPF_ABS, arch_nr));
-
- f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_AARCH64, 2, 0));
- f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_ARM, 1, 0));
- Trap(f);
- return f.size() - 2;
-}
-
-static bool install_filter(filter const& f) {
- struct sock_fprog prog = {
- (unsigned short) f.size(),
- (struct sock_filter*) &f[0],
- };
-
- if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0) {
- ALOGE("SECCOMP: Could not set seccomp filter of size %zu: %s", f.size(), strerror(errno));
- return false;
- }
-
- ALOGI("SECCOMP: Global filter of size %zu installed", f.size());
- return true;
-}
-
-bool set_seccomp_filter() {
- filter f;
-
- // Note that for mixed 64/32 bit architectures, ValidateArchitecture inserts a
- // jump that must be changed to point to the start of the 32-bit policy
- // 32 bit syscalls will not hit the policy between here and the call to SetJump
- auto offset_to_32bit_filter =
- ValidateArchitectureAndJumpIfNeeded(f);
-
- // 64-bit filter
- ExamineSyscall(f);
-
- // arm64-only filter - autogenerated from bionic syscall usage
- for (size_t i = 0; i < arm64_filter_size; ++i)
- f.push_back(arm64_filter[i]);
- Trap(f);
-
- if (SetValidateArchitectureJumpTarget(offset_to_32bit_filter, f) != 0)
- return -1;
-
- // 32-bit filter
- ExamineSyscall(f);
-
- // arm32 filter - autogenerated from bionic syscall usage
- for (size_t i = 0; i < arm_filter_size; ++i)
- f.push_back(arm_filter[i]);
- Trap(f);
-
- return install_filter(f);
-}
-
static void Seccomp_setPolicy(JNIEnv* /*env*/) {
if (!set_seccomp_filter()) {
ALOGE("Failed to set seccomp policy - killing");
@@ -143,13 +26,6 @@
}
}
-#else // #if defined __arm__ || defined __aarch64__
-
-static void Seccomp_setPolicy(JNIEnv* /*env*/) {
-}
-
-#endif
-
static const JNINativeMethod method_table[] = {
NATIVE_METHOD(Seccomp, setPolicy, "()V"),
};
diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp
index c05ef26..90ed6eb 100644
--- a/core/jni/android_text_StaticLayout.cpp
+++ b/core/jni/android_text_StaticLayout.cpp
@@ -159,11 +159,12 @@
minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr);
Paint* paint = reinterpret_cast<Paint*>(nativePaint);
Typeface* typeface = reinterpret_cast<Typeface*>(nativeTypeface);
- minikin::FontCollection *font;
minikin::MinikinPaint minikinPaint;
- minikin::FontStyle style = MinikinUtils::prepareMinikinPaint(&minikinPaint, &font, paint,
+ Typeface* resolvedTypeface = Typeface::resolveDefault(typeface);
+ minikin::FontStyle style = MinikinUtils::prepareMinikinPaint(&minikinPaint, paint,
typeface);
- return b->addStyleRun(&minikinPaint, font, style, start, end, isRtl);
+ return b->addStyleRun(&minikinPaint, resolvedTypeface->fFontCollection, style, start, end,
+ isRtl);
}
// Accept width measurements for the run, passed in from Java
diff --git a/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h b/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h
index a5d0596..3545c56 100644
--- a/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h
+++ b/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h
@@ -41,12 +41,13 @@
/* Convert from AHARDWAREBUFFER_USAGE* flags to to gralloc usage flags. */
extern void android_hardware_HardwareBuffer_convertToGrallocUsageBits(
- uint64_t usage0, uint64_t usage1, uint64_t* outProducerUsage,
- uint64_t* outConsumerUsage);
+ uint64_t* outProducerUsage, uint64_t* outConsumerUsage, uint64_t usage0,
+ uint64_t usage1);
/* Convert from gralloc usage flags to to AHARDWAREBUFFER_USAGE0* flags. */
-extern uint64_t android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
- uint64_t producerUsage, uint64_t consumerUsage);
+extern void android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
+ uint64_t* outUsage0, uint64_t* outUsage1, uint64_t producerUsage,
+ uint64_t consumerUsage);
} // namespace android
diff --git a/media/java/android/media/IDescrambler.aidl b/core/proto/android/os/looper.proto
similarity index 67%
rename from media/java/android/media/IDescrambler.aidl
rename to core/proto/android/os/looper.proto
index fdf99eb..9fcc781 100644
--- a/media/java/android/media/IDescrambler.aidl
+++ b/core/proto/android/os/looper.proto
@@ -14,14 +14,17 @@
* limitations under the License.
*/
-package android.media;
+syntax = "proto3";
-import android.media.MediaDescrambler;
+package android.os;
-/** @hide */
-interface IDescrambler {
- void setMediaCasSession(in byte[] sessionId);
- boolean requiresSecureDecoderComponent(String mime);
- int descramble(in MediaDescrambler.DescrambleInfo descrambleInfo);
- void release();
-}
\ No newline at end of file
+option java_multiple_files = true;
+
+import "frameworks/base/core/proto/android/os/messagequeue.proto";
+
+message LooperProto {
+ string thread_name = 1;
+ int64 thread_id = 2;
+ int32 identity_hash_code = 3;
+ android.os.MessageQueueProto queue = 4;
+}
diff --git a/core/proto/android/os/message.proto b/core/proto/android/os/message.proto
new file mode 100644
index 0000000..604935d
--- /dev/null
+++ b/core/proto/android/os/message.proto
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.os;
+
+option java_multiple_files = true;
+
+message MessageProto {
+ int64 when = 1;
+ // Name of callback class.
+ string callback = 2;
+ // User-defined message code so that the recipient can identify what this
+ // message is about.
+ int32 what = 3;
+ int32 arg1 = 4;
+ int32 arg2 = 5;
+ // String representation of an arbitrary object to send to the recipient.
+ string obj = 6;
+ // Name of target class.
+ string target = 7;
+ int32 barrier = 8;
+}
diff --git a/media/java/android/media/MediaCas.aidl b/core/proto/android/os/messagequeue.proto
similarity index 68%
copy from media/java/android/media/MediaCas.aidl
copy to core/proto/android/os/messagequeue.proto
index cb8d0c6..9bff13e 100644
--- a/media/java/android/media/MediaCas.aidl
+++ b/core/proto/android/os/messagequeue.proto
@@ -14,10 +14,16 @@
* limitations under the License.
*/
-package android.media;
+syntax = "proto3";
-/** @hide */
-parcelable MediaCas.ParcelableCasPluginDescriptor cpp_header "media/MediaCasDefs.h";
+package android.os;
-/** @hide */
-parcelable MediaCas.ParcelableCasData cpp_header "media/MediaCasDefs.h";
\ No newline at end of file
+option java_multiple_files = true;
+
+import "frameworks/base/core/proto/android/os/message.proto";
+
+message MessageQueueProto {
+ repeated android.os.MessageProto messages = 1;
+ bool is_polling_locked = 2;
+ bool is_quitting = 3;
+}
diff --git a/media/java/android/media/MediaCas.aidl b/core/proto/android/os/worksource.proto
similarity index 70%
rename from media/java/android/media/MediaCas.aidl
rename to core/proto/android/os/worksource.proto
index cb8d0c6..c2aa5cb 100644
--- a/media/java/android/media/MediaCas.aidl
+++ b/core/proto/android/os/worksource.proto
@@ -14,10 +14,17 @@
* limitations under the License.
*/
-package android.media;
+syntax = "proto3";
-/** @hide */
-parcelable MediaCas.ParcelableCasPluginDescriptor cpp_header "media/MediaCasDefs.h";
+package android.os;
-/** @hide */
-parcelable MediaCas.ParcelableCasData cpp_header "media/MediaCasDefs.h";
\ No newline at end of file
+option java_multiple_files = true;
+
+message WorkSourceProto {
+ message WorkSourceContentProto {
+ int32 uid = 1;
+ string name = 2;
+ }
+
+ repeated WorkSourceContentProto work_source_contents = 1;
+}
\ No newline at end of file
diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto
new file mode 100644
index 0000000..326b0eb
--- /dev/null
+++ b/core/proto/android/service/package.proto
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.service.pm;
+
+option java_multiple_files = true;
+option java_outer_classname = "PackageServiceProto";
+
+message PackageServiceDumpProto {
+ message PackageShortProto {
+ // Name of package. e.g. "com.android.providers.telephony".
+ string name = 1;
+ // UID for this package as assigned by Android OS.
+ int32 uid = 2;
+ }
+ message SharedLibraryProto {
+ string name = 1;
+ // True if library path is not null (jar), false otherwise (apk)
+ bool is_jar = 2;
+ // Should be filled if is_jar is true
+ string path = 3;
+ // Should be filled if is_jar is false
+ string apk = 4;
+ }
+ message FeatureProto {
+ string name = 1;
+ int32 version = 2;
+ }
+ message SharedUserProto {
+ int32 user_id = 1;
+ string name = 2;
+ }
+
+ // Installed packages.
+ PackageShortProto required_verifier_package = 1;
+ PackageShortProto verifier_package = 2;
+ repeated SharedLibraryProto shared_libraries = 3;
+ repeated FeatureProto features = 4;
+ repeated PackageProto packages = 5;
+ repeated SharedUserProto shared_users = 6;
+ // Messages from the settings problem file
+ repeated string messages = 7;
+}
+
+message PackageProto {
+ message SplitProto {
+ string name = 1;
+ int32 revision_code = 2;
+ }
+ message UserInfoProto {
+ enum InstallType {
+ NOT_INSTALLED_FOR_USER = 0;
+ FULL_APP_INSTALL = 1;
+ INSTANT_APP_INSTALL = 2;
+ }
+ // Enum values gotten from PackageManger.java
+ enum EnabledState {
+ // This component or application is in its default enabled state
+ // (as specified in its manifest).
+ COMPONENT_ENABLED_STATE_DEFAULT = 0;
+ // This component or application has been explictily enabled, regardless
+ // of what it has specified in its manifest.
+ COMPONENT_ENABLED_STATE_ENABLED = 1;
+ // This component or application has been explicitly disabled, regardless of
+ // what it has specified in its manifest.
+ COMPONENT_ENABLED_STATE_DISABLED = 2;
+ // The user has explicitly disabled the application, regardless of what it has
+ // specified in its manifest.
+ COMPONENT_ENABLED_STATE_DISABLED_USER = 3;
+ // This application should be considered, until the point where the user actually
+ // wants to use it.
+ COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4;
+ }
+
+ int32 id = 1;
+ InstallType install_type = 2;
+ // Is the app restricted by owner / admin
+ bool is_hidden = 3;
+ bool is_suspended = 4;
+ bool is_stopped = 5;
+ bool is_launched = 6;
+ EnabledState enabled_state = 7;
+ string last_disabled_app_caller = 8;
+ }
+
+ // Name of package. e.g. "com.android.providers.telephony".
+ string name = 1;
+ // UID for this package as assigned by Android OS.
+ int32 uid = 2;
+ // Package's reported version.
+ int32 version_code = 3;
+ // Package's reported version string (what's displayed to the user).
+ string version_string = 4;
+ // UTC timestamp of install
+ int64 install_time_ms = 5;
+ // Millisecond UTC timestamp of latest update adjusted to Google's server clock.
+ int64 update_time_ms = 6;
+ // From "dumpsys package" - name of package which installed this one.
+ // Typically "" if system app or "com.android.vending" if Play Store.
+ string installer_name = 7;
+ // Split APKs.
+ repeated SplitProto splits = 8;
+ // Per-user package info.
+ repeated UserInfoProto users = 9;
+}
diff --git a/core/proto/android/service/power.proto b/core/proto/android/service/power.proto
new file mode 100644
index 0000000..1830dbf
--- /dev/null
+++ b/core/proto/android/service/power.proto
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.service.power;
+
+option java_multiple_files = true;
+option java_outer_classname = "PowerServiceProto";
+
+import "frameworks/base/core/proto/android/os/looper.proto";
+import "frameworks/base/core/proto/android/os/worksource.proto";
+import "frameworks/base/core/proto/android/service/wirelesschargerdetector.proto";
+
+message PowerServiceDumpProto {
+ message ConstantsProto {
+ bool is_no_cached_wake_locks = 1;
+ }
+ message ActiveWakeLocksProto {
+ bool is_cpu = 1;
+ bool is_screen_bright = 2;
+ bool is_screen_dim = 3;
+ bool is_button_bright = 4;
+ bool is_proximity_screen_off = 5;
+ // only set if already awake
+ bool is_stay_awake = 6;
+ bool is_doze = 7;
+ bool is_draw = 8;
+ }
+ message UserActivityProto {
+ bool is_screen_bright = 1;
+ bool is_screen_dim = 2;
+ bool is_screen_dream = 3;
+ }
+ message UidProto {
+ // Enum values gotten from ActivityManager.java
+ enum ProcessState {
+ // Process is a persistent system process.
+ PROCESS_STATE_PERSISTENT = 0;
+ // Process is a persistent system process and is doing UI.
+ PROCESS_STATE_PERSISTENT_UI = 1;
+ // Process is hosting the current top activities. Note that this
+ // covers all activities that are visible to the user.
+ PROCESS_STATE_TOP = 2;
+ // Process is hosting a foreground service due to a system binding.
+ PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 3;
+ // Process is hosting a foreground service.
+ PROCESS_STATE_FOREGROUND_SERVICE = 4;
+ // Same as {@link #PROCESS_STATE_TOP} but while device is sleeping.
+ PROCESS_STATE_TOP_SLEEPING = 5;
+ // Process is important to the user, and something they are aware of.
+ PROCESS_STATE_IMPORTANT_FOREGROUND = 6;
+ // Process is important to the user, but not something they are aware of.
+ PROCESS_STATE_IMPORTANT_BACKGROUND = 7;
+ // Process is in the background running a backup/restore operation.
+ PROCESS_STATE_BACKUP = 8;
+ // Process is in the background, but it can't restore its state so
+ // we want to try to avoid killing it.
+ PROCESS_STATE_HEAVY_WEIGHT = 9;
+ // Process is in the background running a service.
+ PROCESS_STATE_SERVICE = 10;
+ // Process is in the background running a receiver.
+ PROCESS_STATE_RECEIVER = 11;
+ // Process is in the background but hosts the home activity.
+ PROCESS_STATE_HOME = 12;
+ // Process is in the background but hosts the last shown activity.
+ PROCESS_STATE_LAST_ACTIVITY = 13;
+ // Process is being cached for later use and contains activities.
+ PROCESS_STATE_CACHED_ACTIVITY = 14;
+ // Process is being cached for later use and is a client of another
+ // cached process that contains activities.
+ PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 15;
+ // Process is being cached for later use and is empty.
+ PROCESS_STATE_CACHED_EMPTY = 16;
+ // Process does not exist.
+ PROCESS_STATE_NONEXISTENT = 17;
+ }
+ int32 uid = 1;
+ string uid_string = 2;
+ bool is_active = 3;
+ int32 num_wake_locks = 4;
+ bool is_process_state_unknown = 5;
+ ProcessState process_state = 6;
+ }
+
+ // Enum values gotten from PowerManagerInternal.java
+ enum Wakefulness {
+ WAKEFULNESS_ASLEEP = 0;
+ WAKEFULNESS_AWAKE = 1;
+ WAKEFULNESS_DREAMING = 2;
+ WAKEFULNESS_DOZING = 3;
+ WAKEFULNESS_UNKNOWN = 4;
+ }
+ // Enum values gotten from BatteryManager.java
+ enum PlugType {
+ PLUG_TYPE_NONE = 0;
+ PLUG_TYPE_PLUGGED_AC = 1;
+ PLUG_TYPE_PLUGGED_USB = 2;
+ PLUG_TYPE_PLUGGED_WIRELESS = 4;
+ }
+ // Enum values gotten from Intent.java
+ enum DockState {
+ DOCK_STATE_UNDOCKED = 0;
+ DOCK_STATE_DESK = 1;
+ DOCK_STATE_CAR = 2;
+ DOCK_STATE_LE_DESK = 3;
+ DOCK_STATE_HE_DESK = 4;
+ }
+
+ ConstantsProto constants = 1;
+ // A bitfield that indicates what parts of the power state have
+ // changed and need to be recalculated.
+ int32 dirty = 2;
+ // Indicates whether the device is awake or asleep or somewhere in between.
+ Wakefulness wakefulness = 3;
+ bool is_wakefulness_changing = 4;
+ // True if the device is plugged into a power source.
+ bool is_powered = 5;
+ // The current plug type
+ PlugType plug_type = 6;
+ // The current battery level percentage.
+ int32 battery_level = 7;
+ // The battery level percentage at the time the dream started.
+ int32 battery_level_when_dream_started = 8;
+ // The current dock state.
+ DockState dock_state = 9;
+ // True if the device should stay on.
+ bool is_stay_on = 10;
+ // True if the proximity sensor reads a positive result.
+ bool is_proximity_positive = 11;
+ // True if boot completed occurred. We keep the screen on until this happens.
+ bool is_boot_completed = 12;
+ // True if systemReady() has been called.
+ bool is_system_ready = 13;
+ // True if auto-suspend mode is enabled.
+ bool is_hal_auto_suspend_mode_enabled = 14;
+ // True if interactive mode is enabled.
+ bool is_hal_auto_interactive_mode_enabled = 15;
+ // Summarizes the state of all active wakelocks.
+ ActiveWakeLocksProto active_wake_locks = 16;
+ // Have we scheduled a message to check for long wake locks? This is when
+ // we will check. (In milliseconds timestamp)
+ int64 notify_long_scheduled_ms = 17;
+ // Last time we checked for long wake locks. (In milliseconds timestamp)
+ int64 notify_long_dispatched_ms = 18;
+ // The time we decided to do next long check. (In milliseconds timestamp)
+ int64 notify_long_next_check_ms = 19;
+ // Summarizes the effect of the user activity timer.
+ UserActivityProto user_activity = 20;
+ // If true, instructs the display controller to wait for the proximity
+ // sensor to go negative before turning the screen on.
+ bool is_request_wait_for_negative_proximity = 21;
+ // True if MSG_SANDMAN has been scheduled.
+ bool is_sandman_scheduled = 22;
+ // True if the sandman has just been summoned for the first time since entering
+ // the dreaming or dozing state. Indicates whether a new dream should begin.
+ bool is_sandman_summoned = 23;
+ // If true, the device is in low power mode.
+ bool is_low_power_mode_enabled = 24;
+ // True if the battery level is currently considered low.
+ bool is_battery_level_low = 25;
+ // True if we are currently in light device idle mode.
+ bool is_light_device_idle_mode = 26;
+ // True if we are currently in device idle mode.
+ bool is_device_idle_mode = 27;
+ // Set of app ids that we will always respect the wake locks for.
+ repeated int32 device_idle_whitelist = 28;
+ // Set of app ids that are temporarily allowed to acquire wakelocks due to
+ // high-pri message
+ repeated int32 device_idle_temp_whitelist = 29;
+ // Timestamp of the last time the device was awoken.
+ int64 last_wake_time_ms = 30;
+ // Timestamp of the last time the device was put to sleep.
+ int64 last_sleep_time_ms = 31;
+ // Timestamp of the last call to user activity.
+ int64 last_user_activity_time_ms = 32;
+ int64 last_user_activity_time_no_change_lights_ms = 33;
+ // Timestamp of last interactive power hint.
+ int64 last_interactive_power_hint_time_ms = 34;
+ // Timestamp of the last screen brightness boost.
+ int64 last_screen_brightness_boost_time_ms = 35;
+ // True if screen brightness boost is in progress.
+ bool is_screen_brightness_boost_in_progress = 36;
+ // True if the display power state has been fully applied, which means the
+ // display is actually on or actually off or whatever was requested.
+ bool is_display_ready = 37;
+ // True if the wake lock suspend blocker has been acquired.
+ bool is_holding_wake_lock_suspend_blocker = 38;
+ // The suspend blocker used to keep the CPU alive when the display is on, the
+ // display is getting ready or there is user activity (in which case the
+ // display must be on).
+ bool is_holding_display_suspend_blocker = 39;
+ // Settings and configuration
+ PowerServiceSettingsAndConfigurationDumpProto settings_and_configuration = 40;
+ // Sleep timeout in ms
+ sint32 sleep_timeout_ms = 41;
+ // Screen off timeout in ms
+ int32 screen_off_timeout_ms = 42;
+ // Screen dim duration in ms
+ int32 screen_dim_duration_ms = 43;
+ // We are currently in the middle of a batch change of uids.
+ bool are_uids_changing = 44;
+ // Some uids have actually changed while mUidsChanging was true.
+ bool are_uids_changed = 45;
+ // List of UIDs and their states
+ repeated UidProto uids = 46;
+ android.os.LooperProto looper = 47;
+ // List of all wake locks acquired by applications.
+ repeated WakeLockProto wake_locks = 48;
+ // List of all suspend blockers.
+ repeated SuspendBlockerProto suspend_blockers = 49;
+ WirelessChargerDetectorProto wireless_charger_detector = 50;
+}
+
+message SuspendBlockerProto {
+ string name = 1;
+ int32 reference_count = 2;
+}
+
+message WakeLockProto {
+ message WakeLockFlagsProto {
+ // Turn the screen on when the wake lock is acquired.
+ bool is_acquire_causes_wakeup = 1;
+ // When this wake lock is released, poke the user activity timer
+ // so the screen stays on for a little longer.
+ bool is_on_after_release = 2;
+ }
+
+ // Enum values gotten from PowerManager.java
+ enum LockLevel {
+ WAKE_LOCK_INVALID = 0;
+ // Ensures that the CPU is running.
+ PARTIAL_WAKE_LOCK = 1;
+ // Ensures that the screen is on (but may be dimmed).
+ SCREEN_DIM_WAKE_LOCK = 6;
+ // Ensures that the screen is on at full brightness.
+ SCREEN_BRIGHT_WAKE_LOCK = 10;
+ // Ensures that the screen and keyboard backlight are on at full brightness.
+ FULL_WAKE_LOCK = 26;
+ // Turns the screen off when the proximity sensor activates.
+ PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32;
+ // Put the screen in a low power state and allow the CPU to suspend
+ // if no other wake locks are held.
+ DOZE_WAKE_LOCK = 64;
+ // Keep the device awake enough to allow drawing to occur.
+ DRAW_WAKE_LOCK = 128;
+ }
+
+ LockLevel lock_level = 1;
+ string tag = 2;
+ WakeLockFlagsProto flags = 3;
+ bool is_disabled = 4;
+ // Acquire time in ms
+ int64 acq_ms = 5;
+ bool is_notified_long = 6;
+ // Owner UID
+ int32 uid = 7;
+ // Owner PID
+ int32 pid = 8;
+ android.os.WorkSourceProto work_source = 9;
+}
+
+message PowerServiceSettingsAndConfigurationDumpProto {
+ message StayOnWhilePluggedInProto {
+ bool is_stay_on_while_plugged_in_ac = 1;
+ bool is_stay_on_while_plugged_in_usb = 2;
+ bool is_stay_on_while_plugged_in_wireless = 3;
+ }
+ message ScreenBrightnessSettingLimitsProto {
+ int32 setting_minimum = 1;
+ int32 setting_maximum = 2;
+ int32 setting_default = 3;
+ int32 setting_for_vr_default = 4;
+ }
+
+ // Enum values gotten from Settings.java
+ enum ScreenBrightnessMode {
+ SCREEN_BRIGHTNESS_MODE_MANUAL = 0;
+ SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1;
+ }
+ // Enum values gotten from Display.java
+ enum DisplayState {
+ DISPLAY_STATE_UNKNOWN = 0;
+ DISPLAY_STATE_OFF = 1;
+ DISPLAY_STATE_ON = 2;
+ DISPLAY_STATE_DOZE = 3;
+ DISPLAY_STATE_DOZE_SUSPEND = 4;
+ DISPLAY_STATE_VR = 5;
+ }
+
+
+ // True to decouple auto-suspend mode from the display state.
+ bool is_decouple_hal_auto_suspend_mode_from_display_config = 1;
+ // True to decouple interactive mode from the display state.
+ bool is_decouple_hal_interactive_mode_from_display_config = 2;
+ // True if the device should wake up when plugged or unplugged.
+ bool is_wake_up_when_plugged_or_unplugged_config = 3;
+ // True if the device should wake up when plugged or unplugged in theater mode.
+ bool is_wake_up_when_plugged_or_unplugged_in_theater_mode_config = 4;
+ // True if theater mode is enabled
+ bool is_theater_mode_enabled = 5;
+ // True if the device should suspend when the screen is off due to proximity.
+ bool is_suspend_when_screen_off_due_to_proximity_config = 6;
+ // True if dreams are supported on this device.
+ bool are_dreams_supported_config = 7;
+ // Default value for dreams enabled
+ bool are_dreams_enabled_by_default_config = 8;
+ // Default value for dreams activate-on-sleep
+ bool are_dreams_activated_on_sleep_by_default_config = 9;
+ // Default value for dreams activate-on-dock
+ bool are_dreams_activated_on_dock_by_default_config = 10;
+ // True if dreams can run while not plugged in.
+ bool are_dreams_enabled_on_battery_config = 11;
+ // Minimum battery level to allow dreaming when powered.
+ // Use -1 to disable this safety feature.
+ sint32 dreams_battery_level_minimum_when_powered_config = 12;
+ // Minimum battery level to allow dreaming when not powered.
+ // Use -1 to disable this safety feature.
+ sint32 dreams_battery_level_minimum_when_not_powered_config = 13;
+ // If the battery level drops by this percentage and the user activity
+ // timeout has expired, then assume the device is receiving insufficient
+ // current to charge effectively and terminate the dream. Use -1 to disable
+ // this safety feature.
+ sint32 dreams_battery_level_drain_cutoff_config = 14;
+ // True if dreams are enabled by the user.
+ bool are_dreams_enabled_setting = 15;
+ // True if dreams should be activated on sleep.
+ bool are_dreams_activate_on_sleep_setting = 16;
+ // True if dreams should be activated on dock.
+ bool are_dreams_activate_on_dock_setting = 17;
+ // True if doze should not be started until after the screen off transition.
+ bool is_doze_after_screen_off_config = 18;
+ // If true, the device is in low power mode.
+ bool is_low_power_mode_setting = 19;
+ // Current state of whether the settings are allowing auto low power mode.
+ bool is_auto_low_power_mode_configured = 20;
+ // The user turned off low power mode below the trigger level
+ bool is_auto_low_power_mode_snoozing = 21;
+ // The minimum screen off timeout, in milliseconds.
+ int32 minimum_screen_off_timeout_config_ms = 22;
+ // The screen dim duration, in milliseconds.
+ int32 maximum_screen_dim_duration_config_ms = 23;
+ // The maximum screen dim time expressed as a ratio relative to the screen off timeout.
+ float maximum_screen_dim_ratio_config = 24;
+ // The screen off timeout setting value in milliseconds.
+ int32 screen_off_timeout_setting_ms = 25;
+ // The sleep timeout setting value in milliseconds.
+ sint32 sleep_timeout_setting_ms = 26;
+ // The maximum allowable screen off timeout according to the device administration policy.
+ int32 maximum_screen_off_timeout_from_device_admin_ms = 27;
+ bool is_maximum_screen_off_timeout_from_device_admin_enforced_locked = 28;
+ // The stay on while plugged in setting.
+ // A set of battery conditions under which to make the screen stay on.
+ StayOnWhilePluggedInProto stay_on_while_plugged_in = 29;
+ // The screen brightness setting, from 0 to 255.
+ // Use -1 if no value has been set.
+ sint32 screen_brightness_setting = 30;
+ // The screen auto-brightness adjustment setting, from -1 to 1.
+ // Use 0 if there is no adjustment.
+ float screen_auto_brightness_adjustment_setting = 31;
+ // The screen brightness mode.
+ ScreenBrightnessMode screen_brightness_mode_setting = 32;
+ // The screen brightness setting override from the window manager
+ // to allow the current foreground activity to override the brightness.
+ // Use -1 to disable.
+ sint32 screen_brightness_override_from_window_manager = 33;
+ // The user activity timeout override from the window manager
+ // to allow the current foreground activity to override the user activity
+ // timeout. Use -1 to disable.
+ sint64 user_activity_timeout_override_from_window_manager_ms = 34;
+ // The window manager has determined the user to be inactive via other means.
+ // Set this to false to disable.
+ bool is_user_inactive_override_from_window_manager = 35;
+ // The screen brightness setting override from the settings application
+ // to temporarily adjust the brightness until next updated,
+ // Use -1 to disable.
+ sint32 temporary_screen_brightness_setting_override = 36;
+ // The screen brightness adjustment setting override from the settings
+ // application to temporarily adjust the auto-brightness adjustment factor
+ // until next updated, in the range -1..1.
+ // Use NaN to disable.
+ float temporary_screen_auto_brightness_adjustment_setting_override = 37;
+ // The screen state to use while dozing.
+ DisplayState doze_screen_state_override_from_dream_manager = 38;
+ // The screen brightness to use while dozing.
+ float dozed_screen_brightness_override_from_dream_manager = 39;
+ // Screen brightness settings limits.
+ ScreenBrightnessSettingLimitsProto screen_brightness_setting_limits = 40;
+ // The screen brightness setting, from 0 to 255, to be used while in VR Mode.
+ int32 screen_brightness_for_vr_setting = 41;
+ // True if double tap to wake is enabled
+ bool is_double_tap_wake_enabled = 42;
+ // True if we are currently in VR Mode.
+ bool is_vr_mode_enabled = 43;
+}
diff --git a/core/proto/android/service/wirelesschargerdetector.proto b/core/proto/android/service/wirelesschargerdetector.proto
new file mode 100644
index 0000000..7ba7c17
--- /dev/null
+++ b/core/proto/android/service/wirelesschargerdetector.proto
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.service.power;
+
+option java_multiple_files = true;
+
+message WirelessChargerDetectorProto {
+ message VectorProto {
+ float x = 1;
+ float y = 2;
+ float z = 3;
+ }
+
+ // Previously observed wireless power state.
+ bool is_powered_wirelessly = 1;
+ // True if the device is thought to be at rest on a wireless charger.
+ bool is_at_rest = 2;
+ // The gravity vector most recently observed while at rest.
+ VectorProto rest = 3;
+ // True if detection is in progress.
+ bool is_detection_in_progress = 4;
+ // The time when detection was last performed.
+ int64 detection_start_time_ms = 5;
+ // True if the rest position should be updated if at rest.
+ bool is_must_update_rest_position = 6;
+ // The total number of samples collected.
+ int32 total_samples = 7;
+ // The number of samples collected that showed evidence of not being at rest.
+ int32 moving_samples = 8;
+ // The value of the first sample that was collected.
+ VectorProto first_sample = 9;
+ // The value of the last sample that was collected.
+ VectorProto last_sample = 10;
+}
\ No newline at end of file
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b3ae891..054fad2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3489,7 +3489,7 @@
<receiver android:name="com.android.server.updates.ApnDbInstallReceiver"
android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
- <action android:name="android.intent.action.UPDATE_APN_DB" />
+ <action android:name="com.android.internal.intent.action.UPDATE_APN_DB" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
</intent-filter>
</receiver>
diff --git a/core/res/res/layout/app_permission_item_money.xml b/core/res/res/layout/app_permission_item_money.xml
index 2056285..764c883 100644
--- a/core/res/res/layout/app_permission_item_money.xml
+++ b/core/res/res/layout/app_permission_item_money.xml
@@ -57,14 +57,14 @@
android:layout_alignParentStart="true"
android:layout_alignBottom="@+id/perm_money_label"
android:scaleType="fitCenter"
- android:tint="@color/perms_costs_money"
+ android:tint="?android:attr/colorError"
android:tintMode="src_in"
android:src="@android:drawable/ic_coins_s" />
<TextView
android:id="@+id/perm_money_label"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="16sp"
- android:textColor="@color/perms_costs_money"
+ android:textColor="?android:attr/colorError"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/perm_money_icon"
diff --git a/core/res/res/layout/autofill_dataset_picker.xml b/core/res/res/layout/autofill_dataset_picker.xml
index 40cce7b..9b90de6 100644
--- a/core/res/res/layout/autofill_dataset_picker.xml
+++ b/core/res/res/layout/autofill_dataset_picker.xml
@@ -15,7 +15,7 @@
-->
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/list"
+ android:id="@+id/autofill_dataset_picker"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:divider="?android:attr/listDivider"
diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml
index 8453cd35..dad9aad 100644
--- a/core/res/res/layout/autofill_save.xml
+++ b/core/res/res/layout/autofill_save.xml
@@ -16,6 +16,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/autofill_save"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingStart="16dip"
@@ -39,6 +40,13 @@
android:singleLine="true">
</TextView>
+ <TextView
+ android:id="@+id/autofill_save_subtitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="invisible">
+ </TextView>
+
<Space
android:layout_width="0dp"
android:layout_height="0dp"
diff --git a/core/res/res/layout/time_picker_text_input_material.xml b/core/res/res/layout/time_picker_text_input_material.xml
index f17b80e..632a4c1 100644
--- a/core/res/res/layout/time_picker_text_input_material.xml
+++ b/core/res/res/layout/time_picker_text_input_material.xml
@@ -77,7 +77,7 @@
android:layout_height="wrap_content"
android:layout_below="@id/input_hour"
android:layout_alignStart="@id/input_hour"
- android:textColor="?attr/textColorError"
+ android:textColor="?attr/colorError"
android:text="@string/time_picker_input_error" />
</RelativeLayout>
<Spinner
@@ -87,4 +87,4 @@
android:layout_alignBaseline="@id/input_block"
android:layout_alignParentEnd="true"/>
-</merge>
\ No newline at end of file
+</merge>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 6f50d5a..c7696b0 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tik om taal en uitleg te kies"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> teken oor ander programme"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g>-program verskyn bo-op."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Dele van hierdie program sal dalk altyd sigbaar wees. Skakel hierdie kenmerk af as dit nie reg werk nie."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"SKAKEL AF"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Berei tans <xliff:g id="NAME">%s</xliff:g> voor"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Kyk tans vir foute"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Nuwe <xliff:g id="NAME">%s</xliff:g> bespeur"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Tik tyd in"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Skakel oor na teksmodus vir die tydinvoer."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Skakel oor na horlosiemodus vir die tydinvoer."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 5d68f37..a031ff8 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ቋንቋ እና አቀማመጥን ለመምረጥ መታ ያድርጉ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> በሌሎች መተግበሪያዎች ላይ ሣል"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> መተግበሪያ ከላይ እየታየ ያለ።"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"የዚህ መተግበሪያ ክፍሎች በሁሉም ጊዜያት የሚታዩ እንደሆኑ ሊቆዩ ይችላሉ። ይህ ባህሪ በትክክል የማይሠራ ከሆነ ያጥፉት።"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"አጥፋ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g>ን በማዘጋጀት ላይ"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"ስህተቶች ካሉ በመፈተሽ ላይ"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"አዲስ <xliff:g id="NAME">%s</xliff:g> ተገኝቷል"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"ሰዓት ይተይቡ"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ለጊዜ ግቤቱ ወደ የጽሑፍ ግቤት ሁነታ ቀይር።"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ለጊዜ ግቤቱ ወደ የሰዓት ሁነታ ቀይር።"</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 92aa4fc..6d55ada 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1247,14 +1247,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"انقر لاختيار لغة وتنسيق"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789 أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"يتم عرض <xliff:g id="NAME">%s</xliff:g> فوق التطبيقات الأخرى"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"يتم عرض تطبيق <xliff:g id="NAME">%s</xliff:g> فوق التطبيقات."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"قد تظل أجزاء من هذا التطبيق مرئية في جميع الأوقات. فإذا كانت هذه الميزة لا تعمل بشكل صحيح، يمكنك إيقافها."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"إيقاف"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"جارٍ تحضير <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"جارٍ التحقق من الأخطاء"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"تم اكتشاف <xliff:g id="NAME">%s</xliff:g> جديدة"</string>
@@ -1836,4 +1832,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"يُرجى تحديد الوقت"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"يُرجى التبديل إلى وضع إدخال النص لإدخال الوقت."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"يُرجى التبديل إلى وضع الساعة لإدخال الوقت."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 43f0133..07ea197 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dil və tərtibatı seçmək üçün tıklayın"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCÇDEƏFGĞHXIİJKQLMNOÖPRSŞTUÜVYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCÇDEƏFGĞHİIJKLMNOÖPQRSŞTUÜVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> digər tətbiqlərin üzərinə çəkilir"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> tətbiqi üstdə göstərilir."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Bu tətbiqin hissələri həmişə görünən qala bilər. Bu funksiya düzgün işləmirsə, onu deaktiv edin."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DEAKTİV EDİN"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> hazırlanır"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Səhvlər yoxlanılır"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Yeni <xliff:g id="NAME">%s</xliff:g> aşkarlandı"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Zamanı daxil edin"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Zamanı daxil etmək üçün mətnlə daxiletmə rejiminə keçin"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Zamanı daxil etmək üçün saat rejiminə keçin"</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 9a02a43..894bd28 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1187,14 +1187,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite da biste izabrali jezik i raspored"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Aplikacija <xliff:g id="NAME">%s</xliff:g> se prikazuje preko drugih aplikacija"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Aplikacija <xliff:g id="NAME">%s</xliff:g> se prikazuje preko."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Delovi ove aplikacije mogu da ostanu vidljivi u svakom trenutku. Ako ova funkcija ne radi ispravno, isključite je."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ISKLJUČI"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> se priprema"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Proverava se da li postoje greške"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Novi uređaj <xliff:g id="NAME">%s</xliff:g> je otkriven"</string>
@@ -1743,4 +1739,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Unesite vreme"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Pređite u režim unosa teksta radi unosa vremena."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Pređite u režim sata radi unosa vremena."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 070dda7..d567c93 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1207,14 +1207,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Дакраніцеся, каб выбраць мову і раскладку"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГДЕЁЖЗІЙКЛМНОПРСТУЎФХЦЧШ\'ЫЬЭЮЯ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> паверх іншых праграм"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Праграма <xliff:g id="NAME">%s</xliff:g> паказваецца зверху."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Часткі гэтай праграмы могуць заставацца бачнымі ў любы час. Калі гэта функцыя не працуе належным чынам, адключыце яе."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"АДКЛЮЧЫЦЬ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Падрыхтоўка <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Праверка на наяўнасць памылак"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Выяўлены новы носьбіт <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1774,4 +1770,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Увядзіце час"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Пераключыцца на рэжым тэксту пры ўводзе часу."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Пераключыцца на рэжым гадзінніка пры ўводзе часу."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 10887a0..90d3bff 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Докоснете, за да изберете език и подредба"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> се изобразява върху други приложения"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> се показва в/у други прилож."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Части от това приложение може да останат видими за постоянно. Ако функцията не работи правилно, изключете я."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ИЗКЛЮЧВАНЕ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g>: Подготвя се"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Проверява се за грешки"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Открито е ново хранилище (<xliff:g id="NAME">%s</xliff:g>)"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Въведете часа"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Превключете към режима за въвеждане на текст, за да въведете часа."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Превключете към режима за часовник, за да въведете часа."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index b6ebd71..1f5b0a1 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ভাষা এবং লেআউট নির্বাচন করুন আলতো চাপ দিন"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> অন্যান্য অ্যাপের উপরেও দেখা যায়"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> অ্যাপ সবার উপরে দেখা যাচ্ছে।"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"এই অ্যাপের কিছু কিছু অংশ সব সময় স্ক্রিনে দেখা যেতে পারে। যদি এই বৈশিষ্ট্যটি ঠিক ভাবে কাজ না করে, তাহলে অ্যাপটি বন্ধ করে দিন।"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"বন্ধ করুন"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> প্রস্তুত করা হচ্ছে"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"ত্রুটি রয়েছে কিনা পরীক্ষা করা হচ্ছে"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"নতুন <xliff:g id="NAME">%s</xliff:g> সনাক্ত করা হয়েছে"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"সময় টাইপ করুন"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"সময় ইনপুট দেওয়ার জন্য পাঠ্য ইনপুট মোডে যান।"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"সময় ইনপুট দেওয়ার জন্য ঘড়ি মোডে যান।"</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index c63f92c..d0017ad 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1190,14 +1190,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite za odabir jezika i rasporeda"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Aplikacija <xliff:g id="NAME">%s</xliff:g> prekriva ostale aplikacije"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Apl. <xliff:g id="NAME">%s</xliff:g> prikazana je na vrhu."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Dijelovi aplikacije mogu ostati vidljivi sve vrijeme. Ako ta funkcija ne radi ispravno, isključite je."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ISKLJUČI"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Priprema se <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Provjera grešaka"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Novi uređaj <xliff:g id="NAME">%s</xliff:g> je otkriven"</string>
@@ -1746,4 +1742,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Upišite vrijeme"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Prebacite u način unosa teksta za unos vremena."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Prebacite u način rada kao sat za unos vremena."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 507bc59..2402232 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca per seleccionar l\'idioma i el disseny"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> se superposa a altres aplicacions"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"L\'aplicació <xliff:g id="NAME">%s</xliff:g> s\'està superposant."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Algunes parts d\'aquesta aplicació seran visibles en tot moment. Si aquesta funció presenta problemes, desactiva-la."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESACTIVA"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"S\'està preparant <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"S\'està comprovant si hi ha errors"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"S\'ha detectat <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Escriu l\'hora"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Canvia al mode d\'introducció de text per introduir l\'hora."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Canvia al mode de rellotge per introduir l\'hora."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 41dc69b..7d59c43 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1207,14 +1207,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Klepnutím vyberte jazyk a rozvržení"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Aplikace <xliff:g id="NAME">%s</xliff:g> se může vykreslovat přes ostatní aplikace"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Aplikace <xliff:g id="NAME">%s</xliff:g> se zobrazuje nahoře."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Části této aplikace mohou zůstat vždy viditelné. Pokud tato funkce nepracuje správně, vypněte ji."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"VYPNOUT"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Probíhá příprava úložiště <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Kontrola chyb"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Zjištěno nové úložiště <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1774,4 +1770,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Zadejte čas"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Chcete-li zadat čas, přepněte na režim textu."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Chcete-li zadat čas, přepněte na režim hodin."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 2d19eb6..c62cece 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tryk for at vælge sprog og layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> vises over andre apps"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Appen <xliff:g id="NAME">%s</xliff:g> vises øverst."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Dele af denne app kan være synlig hele tiden. Deaktiver denne funktion, hvis den ikke fungerer korrekt."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"SLÅ FRA"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Forbereder <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Kontrollerer for fejl"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Der blev registreret et nyt <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Angiv klokkeslæt"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Skift til teksttilstand for at angive klokkeslæt."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Skift til urtilstand for at angive klokkeslæt."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 054af7c..4564231 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Zum Auswählen von Sprache und Layout tippen"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> wird über anderen Apps eingeblendet"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Die App \"<xliff:g id="NAME">%s</xliff:g>\" wird über anderen Apps angezeigt."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Teile dieser App werden die ganze Zeit eingeblendet. Wenn diese Funktion nicht richtig funktioniert, deaktiviere sie."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DEAKTIVIEREN"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> wird vorbereitet"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Nach Fehlern wird gesucht"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Neue <xliff:g id="NAME">%s</xliff:g> entdeckt"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Uhrzeit eingeben"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"In den Texteingabemodus wechseln, um die Uhrzeit einzugeben."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"In den Uhrzeitmodus wechseln, um die Uhrzeit einzugeben."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 48bd718..cd6c67b 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Πατήστε για να επιλέξετε γλώσσα και διάταξη"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Η εφαρμογή <xliff:g id="NAME">%s</xliff:g> επικάλυψε άλλες εφαρμογές"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Η εφαρμογή <xliff:g id="NAME">%s</xliff:g> επικαλύπτει άλλες."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Ορισμένα τμήματα αυτής της εφαρμογής μπορεί να παραμένουν συνεχώς ορατά. Εάν αυτή η λειτουργία δεν εκτελείται σωστά, απενεργοποιήστε την."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ΑΠΕΝΕΡΓΟΠΟΙΗΣΗ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Προετοιμασία <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Έλεγχος για σφάλματα"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Εντοπίστηκε νέο μέσο αποθήκευσης <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Πληκτρολογήστε την ώρα"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Κάντε εναλλαγή στη λειτουργία εισαγωγής κειμένου, για την εισαγωγή της ώρας."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Κάντε εναλλαγή στη λειτουργία ρολογιού, για την εισαγωγή της ώρας."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 08fc5ba..04f9537 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> draw over other apps"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> app displaying on top."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Parts of this app may remain visible at all times. If this feature isn\'t working correctly, turn it off."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"TURN OFF"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparing <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Checking for errors"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"New <xliff:g id="NAME">%s</xliff:g> detected"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Type in time"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Switch to text input mode for the time input."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Switch to clock mode for the time input."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 08fc5ba..04f9537 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> draw over other apps"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> app displaying on top."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Parts of this app may remain visible at all times. If this feature isn\'t working correctly, turn it off."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"TURN OFF"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparing <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Checking for errors"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"New <xliff:g id="NAME">%s</xliff:g> detected"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Type in time"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Switch to text input mode for the time input."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Switch to clock mode for the time input."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 08fc5ba..04f9537 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> draw over other apps"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> app displaying on top."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Parts of this app may remain visible at all times. If this feature isn\'t working correctly, turn it off."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"TURN OFF"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparing <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Checking for errors"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"New <xliff:g id="NAME">%s</xliff:g> detected"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Type in time"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Switch to text input mode for the time input."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Switch to clock mode for the time input."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index f294d6f..8aaa2ea 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Presiona para seleccionar el idioma y el diseño"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> se muestra sobre otras apps"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> se muestra sobre otras apps"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Es posible que ciertas partes de esta app permanezcan visibles todo el tiempo. Si esta función tiene problemas, desactívala."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESACTIVAR"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparando el medio <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Verificando errores"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Se detectó un nuevo medio (<xliff:g id="NAME">%s</xliff:g>)."</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Ingresa la hora"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Cambia al modo de entrada de texto para ingresar la hora."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Cambia al modo de reloj para ingresar la hora."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 34aee0d..0ce96e7 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca para seleccionar el idioma y el diseño"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> se muestra sobre otras aplicaciones"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> se muestra en primer plano."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Es posible que algunas partes de esta aplicación permanezcan visibles en todo momento. Desactiva esta función si no funciona correctamente."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESACTIVAR"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparando <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Comprobando errores"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Nueva <xliff:g id="NAME">%s</xliff:g> detectada"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Escribe la hora"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Cambia al modo de introducción de texto para escribir la hora."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Cambia al modo de reloj para escribir la hora."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 7acb404..27cd957 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Puudutage keele ja paigutuse valimiseks"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Rakendus <xliff:g id="NAME">%s</xliff:g> joonistab teiste rakenduste peale"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Rakend. <xliff:g id="NAME">%s</xliff:g> kuvatakse kõige peal."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Selle rakenduse osad võivad alati nähtaval olla. Kui see funktsioon ei tööta korralikult, lülitage see välja."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"LÜLITA VÄLJA"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Üksuse <xliff:g id="NAME">%s</xliff:g> ettevalmistamine"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Vigade kontrollimine"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Tuvastati uus üksus <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Sisestage kellaaeg"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Aktiveerige kellaaja sisestamiseks tekstisisestusrežiim."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Aktiveerige kellaaja sisestamiseks kellarežiim."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 2fb79ec..5fb9998 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Hizkuntza eta diseinua hautatzeko, sakatu hau"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> zerbitzuak beste aplikazio batzuk gainjarri ditu pantailan"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> gainjarri da pantailan."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Aplikazioaren atal batzuk ikusgai gera litezke uneoro. Eginbideak behar bezala funtzionatzen ez badu, desaktiba ezazu."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESAKTIBATU"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> prestatzen"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Errorerik dagoen egiaztatzen"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"<xliff:g id="NAME">%s</xliff:g> berria hauteman da"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Idatzi ordua"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Aldatu testu modura ordua zehazteko."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Aldatu erloju modura ordua zehazteko."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 81606dd..51eb178 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"برای انتخاب زبان و چیدمان ضربه بزنید"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"نمایش <xliff:g id="NAME">%s</xliff:g> روی برنامههای دیگر"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"نمایش برنامه <xliff:g id="NAME">%s</xliff:g> در بالا."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"ممکن است قسمتهایی از این برنامه همیشه قابل مشاهده بمانند. اگر این قابلیت بهدرستی کار نمیکند، آن را خاموش کنید."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"خاموش کردن"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"در حال آمادهسازی <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"در حال بررسی برای خطاها"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"<xliff:g id="NAME">%s</xliff:g> جدید شناسایی شد"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"زمان را تایپ کنید"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"برای وارد کردن زمان، به حالت وارد کردن نوشتار تغییر وضعیت دهید."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"برای وارد کردن زمان، به حالت ساعت تغییر وضعیت دهید."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 1169f57..87f3214 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Valitse kieli ja asettelu koskettamalla."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> piirtää muiden sovellusten päälle"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Sovellus <xliff:g id="NAME">%s</xliff:g> näkyy päällä"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Osia sovelluksesta voi olla aina näkyvissä. Jos ominaisuus ei toimi oikein, poista se käytöstä."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"POISTA KÄYTÖSTÄ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Valmistellaan kohdetta <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Tarkistetaan virheiden varalta."</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Uusi <xliff:g id="NAME">%s</xliff:g> on havaittu."</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Kirjoita aika"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Vaihda ajan syöttämiseen tekstitilassa."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Vaihda ajan syöttämiseen kellotilassa."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 43ff0cf..7b05c74 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Touchez pour sélectionner la langue et la configuration du clavier"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> se superpose aux autres applications"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> s\'affiche par-dessus les autres"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Certaines parties de cette application restent visibles en tout temps. Si cette option ne fonctionne pas correctement, désactivez-la."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DÉSACTIVER"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Préparation de « <xliff:g id="NAME">%s</xliff:g> » en cours"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Recherche d\'erreurs en cours..."</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Une nouvelle mémoire « <xliff:g id="NAME">%s</xliff:g> » a été détectée"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Entrez l\'heure"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Passer au mode Entrée de texte pour entrer l\'heure."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Passer au mode Horloge pour entrer l\'heure."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 50ee5be..40172d0 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Appuyer pour sélectionner la langue et la disposition"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> se superpose aux autres applications"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Superposition de l\'application <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Certaines sections de cette application peuvent rester visibles en permanence. Si cette fonctionnalité ne s\'exécute pas correctement, désactivez-la."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DÉSACTIVER"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Préparation mémoire \"<xliff:g id="NAME">%s</xliff:g>\" en cours"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Recherche d\'erreurs"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Une nouvelle mémoire de stockage \"<xliff:g id="NAME">%s</xliff:g>\" a été détectée."</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Indiquez l\'heure"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Passer en mode saisie de texte pour la saisie de l\'heure."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Passer en mode horloge pour la saisie de l\'heure."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 0ee956a..0e024b4 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca para seleccionar o idioma e o deseño"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> superponse a outras aplicacións"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"A aplicación <xliff:g id="NAME">%s</xliff:g> móstrase enriba."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Partes desta aplicación poden permanecer visibles en todo momento. Se esta función non traballa correctamente, desactívaa."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESACTIVAR"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparando a <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Comprobando se hai erros"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Detectouse unha <xliff:g id="NAME">%s</xliff:g> nova"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Escribe a hora"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Cambia ao modo de entrada de texto para introducir a hora."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Cambiar ao modo de reloxo para introducir a hora."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 1693c32..511a843 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ભાષા અને લેઆઉટ પસંદ કરવા માટે ટૅપ કરો"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> અન્ય ઍપ્લિકેશનો પર ડ્રો કરે છે"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> ઍપ્લિકેશન સૌથી ઉપર દેખાઈ રહી છે."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"આ ઍપ્લિકેશનના ભાગ હંમેશાં દૃશ્યક્ષમ રહી શકે છે. જો આ સુવિધા યોગ્ય રીતે કાર્ય કરી રહી ન હોય, તો તેને બંધ કરો."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"બંધ કરો"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> ને તૈયાર કરી રહ્યું છે"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"ભૂલો માટે તપાસી રહ્યું છે"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"નવું <xliff:g id="NAME">%s</xliff:g> મળ્યું"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"સમય લખો"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"સમય દાખલ કરવા માટે ટેક્સ્ટ ઇનપુટ મોડમાં સ્વિચ કરો."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"સમય દાખલ કરવા માટે ઘડિયાળ મોડમાં સ્વિચ કરો."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index fbf2eaf..0a5d130 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -148,7 +148,7 @@
<string name="fcComplete" msgid="3118848230966886575">"सुविधा कोड पूर्ण."</string>
<string name="fcError" msgid="3327560126588500777">"कनेक्शन समस्या या अमान्य सुविधा कोड."</string>
<string name="httpErrorOk" msgid="1191919378083472204">"ठीक है"</string>
- <string name="httpError" msgid="7956392511146698522">"कोई नेटवर्क त्रुटि हुई थी."</string>
+ <string name="httpError" msgid="7956392511146698522">"कोई नेटवर्क गड़बड़ी हुई थी."</string>
<string name="httpErrorLookup" msgid="4711687456111963163">"URL नहीं मिल सका."</string>
<string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"साइट प्रमाणीकरण योजना समर्थित नहीं है."</string>
<string name="httpErrorAuth" msgid="1435065629438044534">"प्रमाणीकृत नहीं किया जा सका."</string>
@@ -163,7 +163,7 @@
<string name="httpErrorFile" msgid="2170788515052558676">"फ़ाइल पर नहीं पहुंचा जा सका."</string>
<string name="httpErrorFileNotFound" msgid="6203856612042655084">"अनुरोधित फ़ाइल नहीं मिल सकी."</string>
<string name="httpErrorTooManyRequests" msgid="1235396927087188253">"बहुत सारे अनुरोधों का संसाधन हो रहा है. बाद में पुन: प्रयास करें."</string>
- <string name="notification_title" msgid="8967710025036163822">"<xliff:g id="ACCOUNT">%1$s</xliff:g> के लिए प्रवेश त्रुटि"</string>
+ <string name="notification_title" msgid="8967710025036163822">"<xliff:g id="ACCOUNT">%1$s</xliff:g> के लिए प्रवेश गड़बड़ी"</string>
<string name="contentServiceSync" msgid="8353523060269335667">"समन्वयन"</string>
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"समन्वयन"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"बहुत से <xliff:g id="CONTENT_TYPE">%s</xliff:g> हटाए जाते हैं."</string>
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा और लेआउट चुनने के लिए टैप करें"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> दूसरे ऐप पर आरेखण करते हैं"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> ऐप ऊपर दिखा रहा है."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"हो सकता है कि इस ऐप के कुछ हिस्से हर समय दृश्यमान रहें. अगर यह सुविधा ठीक तरह से काम नहीं कर रही है, तो इसे बंद कर दें."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"बंद करें"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> को तैयार किया जा रहा है"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"त्रुटियों की जांच कर रहा है"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"नए <xliff:g id="NAME">%s</xliff:g> का पता लगा"</string>
@@ -1258,7 +1254,7 @@
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"हमेशा-चालू VPN कनेक्ट हो रहा है…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"हमेशा-चालू VPN कनेक्ट है"</string>
<string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"हमेशा-चालू VPN डिस्कनेक्ट है"</string>
- <string name="vpn_lockdown_error" msgid="6009249814034708175">"हमेशा-चालू VPN त्रुटि"</string>
+ <string name="vpn_lockdown_error" msgid="6009249814034708175">"हमेशा-चालू VPN गड़बड़ी"</string>
<string name="vpn_lockdown_config" msgid="5099330695245008680">"सेट करने के लिए टैप करें"</string>
<string name="upload_file" msgid="2897957172366730416">"फ़ाइल चुनें"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"कोई फ़ाइल चुनी नहीं गई"</string>
@@ -1454,7 +1450,7 @@
<string name="user_switching_message" msgid="2871009331809089783">"<xliff:g id="NAME">%1$s</xliff:g> पर स्विच किया जा रहा है…"</string>
<string name="user_logging_out_message" msgid="8939524935808875155">"<xliff:g id="NAME">%1$s</xliff:g> द्वारा प्रस्थान किया जा रहा है…"</string>
<string name="owner_name" msgid="2716755460376028154">"स्वामी"</string>
- <string name="error_message_title" msgid="4510373083082500195">"त्रुटि"</string>
+ <string name="error_message_title" msgid="4510373083082500195">"गड़बड़ी"</string>
<string name="error_message_change_not_allowed" msgid="1347282344200417578">"यह बदलाव आपके व्यवस्थापक द्वारा अनुमत नहीं है"</string>
<string name="app_not_found" msgid="3429141853498927379">"इस कार्यवाही को प्रबंधित करने के लिए कोई ऐप्स नहीं मिला"</string>
<string name="revoke" msgid="5404479185228271586">"निरस्त करें"</string>
@@ -1542,7 +1538,7 @@
<string name="mediasize_unknown_portrait" msgid="3088043641616409762">"अज्ञात पोर्ट्रेट"</string>
<string name="mediasize_unknown_landscape" msgid="4876995327029361552">"अज्ञात लैंडस्केप"</string>
<string name="write_fail_reason_cancelled" msgid="7091258378121627624">"रद्द कर दी गई"</string>
- <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"सामग्री लिखने में त्रुटि"</string>
+ <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"सामग्री लिखने में गड़बड़ी"</string>
<string name="reason_unknown" msgid="6048913880184628119">"अज्ञात"</string>
<string name="reason_service_unavailable" msgid="7824008732243903268">"प्रिंट सेवा सक्षम नहीं है"</string>
<string name="print_service_installed_title" msgid="2246317169444081628">"<xliff:g id="NAME">%s</xliff:g> सेवा इंस्टॉल की गई"</string>
@@ -1633,8 +1629,8 @@
<string name="zen_mode_default_weekends_name" msgid="2786495801019345244">"सप्ताहांत"</string>
<string name="zen_mode_default_events_name" msgid="8158334939013085363">"इवेंट"</string>
<string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> द्वारा म्यूट किया गया"</string>
- <string name="system_error_wipe_data" msgid="6608165524785354962">"आपके डिवाइस के साथ कोई आंतरिक त्रुटि हुई और यह तब तक अस्थिर रह सकता है, जब तक आप फ़ैक्टरी डेटा रीसेट नहीं करते हैं."</string>
- <string name="system_error_manufacturer" msgid="8086872414744210668">"आपके डिवाइस के साथ कोई आंतरिक त्रुटि हुई. विवरणों के लिए अपने निर्माता से संपर्क करें."</string>
+ <string name="system_error_wipe_data" msgid="6608165524785354962">"आपके डिवाइस के साथ कोई आंतरिक गड़बड़ी हुई और यह तब तक अस्थिर रह सकता है, जब तक आप फ़ैक्टरी डेटा रीसेट नहीं करते हैं."</string>
+ <string name="system_error_manufacturer" msgid="8086872414744210668">"आपके डिवाइस के साथ कोई आंतरिक गड़बड़ी हुई. विवरणों के लिए अपने निर्माता से संपर्क करें."</string>
<string name="stk_cc_ussd_to_dial" msgid="5202342984749947872">"USSD अनुरोध को DIAL अनुरोध में बदल दिया गया है."</string>
<string name="stk_cc_ussd_to_ss" msgid="2345360594181405482">"USSD अनुरोध को SS अनुरोध में बदल दिया गया है."</string>
<string name="stk_cc_ussd_to_ussd" msgid="7466087659967191653">"USSD अनुरोध को नए USSD अनुरोध में बदल दिया गया है."</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"समय लिखें"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"समय इनपुट के लिए लेख इनपुट मोड पर जाएं."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"समय इनपुट के लिए घड़ी मोड पर जाएं."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 1b97a4e..89058a5 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1187,14 +1187,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite da biste odabrali jezik i raspored"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Aplikacija <xliff:g id="NAME">%s</xliff:g> prikazuje se preko drugih aplikacija"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Aplikacija <xliff:g id="NAME">%s</xliff:g> prikazuje se gore."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Dijelovi ove aplikacije mogu ostati vidljivi cijelo vrijeme. Ako ta značajka ne funkcionira pravilno, isključite je."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ISKLJUČI"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Priprema uređaja <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Traženje pogrešaka"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Otkriven je novi uređaj <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1743,4 +1739,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Unesite vrijeme"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Prijeđite na način unosa teksta da biste unijeli vrijeme."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Prijeđite na način rada sata da biste unijeli vrijeme."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index b67b29f..a4028ee 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Koppintson a nyelv és a billentyűzetkiosztás kiválasztásához"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"A(z) <xliff:g id="NAME">%s</xliff:g> a többi alkalmazás felett jelenik meg"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"A(z) <xliff:g id="NAME">%s</xliff:g> legfelül jelenik meg."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Előfordulhat, hogy ezen alkalmazás egyes részei mindig láthatók maradnak. Ha ez a funkció nem működik megfelelően, kapcsolja ki."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"KIKAPCSOLÁS"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> előkészítése"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Hibák keresése"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Új <xliff:g id="NAME">%s</xliff:g> észlelve"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Adja meg az időt"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Időbevitelhez váltson szövegbeviteli módba."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Időbevitelhez váltson óramódba."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index fa332b0..ad375eb 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Հպեք՝ լեզուն և դասավորությունն ընտրելու համար"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՈՒՓՔԵւՕՖ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> ցուցադրել այլ հավելվածների վերևում"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է վերևում։"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Այս հավելվածի որոշ հատվածներ կարող են միշտ տեսանելի լինել։ Եթե այս գործառույթն ինչպես հարկն է չի աշխատում, անջատեք այն։"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ԱՆՋԱՏԵԼ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g>-ի նախապատրաստում"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Սխալների ստուգում"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Հայտնաբերվել է նոր <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Մուտքագրեք ժամը"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Ժամը մուտքագրելու համար միացրեք տեքստի մուտքագրման ռեժիմը:"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Ժամը մուտքագրելու համար միացրեք ժամացույցի ռեժիմը:"</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index ac898e4..ab32838 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ketuk untuk memilih bahasa dan tata letak"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> muncul di atas aplikasi lain"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Aplikasi <xliff:g id="NAME">%s</xliff:g> muncul di atas."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Sebagian aplikasi ini mungkin selalu terlihat. Jika fitur ini tidak berfungsi dengan baik, nonaktifkan."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"NONAKTIFKAN"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Menyiapkan <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Memeriksa kesalahan"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"<xliff:g id="NAME">%s</xliff:g> baru terdeteksi"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Ketik waktu"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Beralih ke mode masukan teks untuk masukan waktu."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Beralih ke mode jam untuk masukan waktu."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index a1b2be8..3cbc17e 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ýttu til að velja tungumál og útlit"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁBCDÐEÉFGHIÍJKLMNOÓPQRSTUÚVWXYÝZÞÆÖ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AÁBCDÐEÉFGHIÍJKLMNOÓPQRSTUÚVWXYÝZÞÆÖ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> teiknar yfir önnur forrit"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> forritið birtist efst."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Hluti af þessu forriti gæti verið ávallt sýnilegur. Ef þessi eiginleiki virkar ekki sem skyldi skaltu slökkva á honum."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"SLÖKKVA"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Undirbýr <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Leitar að villum"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Nýtt <xliff:g id="NAME">%s</xliff:g> fannst"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Færðu inn tíma"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Skipta yfir í textastillingu til að færa inn tíma."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Skipta yfir í klukkustillingu til að færa inn tíma."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index f5aab8e..89b0113 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tocca per selezionare la lingua e il layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> visualizzata sopra altre app"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"App <xliff:g id="NAME">%s</xliff:g> visualizzata sulle altre."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Alcune parti di questa app possono rimanere sempre visibili. Disattiva la funzione qualora non funzionasse correttamente."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DISATTIVA"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparazione della <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Ricerca errori"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Nuova <xliff:g id="NAME">%s</xliff:g> rilevata"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Digita l\'ora"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Passa alla modalità di immissione testo per inserire l\'ora."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Passa alla modalità orologio per inserire l\'ora."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 9f90a38..c6e02d2 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1207,14 +1207,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"הקש כדי לבחור שפה ופריסה"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> יכולה להופיע מעל אפליקציות אחרות"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> מופיעה מעל אפליקציות אחרות."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"חלקים באפליקציה הזו עשויים להופיע במסך כל הזמן. כבה את התכונה הזו אם היא לא עובדת כראוי."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"כבה"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"הכנת <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"בודק אם יש שגיאות"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"זוהה <xliff:g id="NAME">%s</xliff:g> חדש"</string>
@@ -1774,4 +1770,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"הקלד את השעה"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"העבר למצב קלט טקסט לצורך הזנת השעה"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"העבר למצב שעון לצורך הזנת השעה"</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index b4d2d83..857999f 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -296,8 +296,8 @@
<string name="permdesc_receiveSms" msgid="6424387754228766939">"SMSメッセージの受信と処理をアプリに許可します。これにより、アプリが端末に届いたメッセージを表示することなく監視または削除できるようになります。"</string>
<string name="permlab_receiveMms" msgid="1821317344668257098">"テキストメッセージ(MMS)の受信"</string>
<string name="permdesc_receiveMms" msgid="533019437263212260">"MMSメッセージの受信と処理をアプリに許可します。これにより、アプリが端末に届いたメッセージを表示することなく監視または削除できるようになります。"</string>
- <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"緊急警報SMSの読み取り"</string>
- <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"端末で受信した緊急警報SMSの読み取りをアプリに許可します。緊急警報は、緊急事態を警告する目的で一部の地域に配信されます。緊急警報の受信時に、悪意のあるアプリによって端末の動作や処理が妨害される恐れがあります。"</string>
+ <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"緊急速報メール SMS の読み取り"</string>
+ <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"端末で受信した緊急速報メール SMS の読み取りをアプリに許可します。緊急速報メールは、緊急事態を警告する目的で一部の地域に配信されます。緊急速報メールの受信時に、悪意のあるアプリによって端末の動作や処理が妨害される恐れがあります。"</string>
<string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"登録したフィードの読み取り"</string>
<string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"現在同期されているフィードの詳細を取得することをアプリに許可します。"</string>
<string name="permlab_sendSms" msgid="7544599214260982981">"SMSメッセージの送信と表示"</string>
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"タップして言語とレイアウトを選択してください"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g>を他のアプリの上に重ねて表示"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g>を重ねて表示中"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"このアプリの一部は常に表示され続けます。この機能が正常に動作しない場合は OFF にしてください。"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"OFF にする"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g>を準備中"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"エラーを確認中"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"新しい<xliff:g id="NAME">%s</xliff:g>が検出されました"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"時刻を入力"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"時刻をテキストで入力するモードに切り替えます。"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"時刻を時計で入力するモードに切り替えます。"</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 80c9dec..5d970b6 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"შეეხეთ ენისა და განლაგების ასარჩევად"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g>-ის სხვა აპების ინტერფეისზე გადაწერა"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> აპის მიერ ზემოდან ჩვენება."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"აპის გარკვეული ნაწილები შესაძლოა ყოველთვის ხილული იყოს. თუ ეს ფუნქცია გამართულად არ მუშაობს, გამორთეთ."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"გამორთვა"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g>-ის მომზადება"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"შეცდომების შემოწმება"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"აღმოჩენილია ახალი <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"აკრიფეთ დრო"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"დროის შეყვანისთვის ტექსტის შეყვანის რეჟიმზე გადართვა."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"დროის შეყვანისთვის საათის რეჟიმზე გადართვა."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 6732ca3..3e77e9c 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Тіл мен пернетақта схемасын таңдау үшін түртіңіз"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> басқа қолданбалардың үстінен көрсетіледі"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> қолданбасы жоғарғы жағында көрсетіледі."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Бұл қолданбаның бір бөлігі үнемі көрініп тұруы мүмкін. Егер бұл функция дұрыс жұмыс істемесе, оны өшіріңіз."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ӨШІРУ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> дайындалуда"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Қателер тексерілуде"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Жаңа <xliff:g id="NAME">%s</xliff:g> анықталды"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Уақытты енгізіңіз"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Уақытты енгізу үшін мәтін енгізу режиміне өтіңіз."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Уақытты енгізу үшін сағат режиміне өтіңіз."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index e906c45..e07bc41 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1169,14 +1169,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ប៉ះដើម្បីជ្រើសភាសា និងប្លង់"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> គូរពីលើកម្មវិធីផ្សេងទៀត"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"កម្មវិធី <xliff:g id="NAME">%s</xliff:g> បង្ហាញនៅលើគេ។"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"ផ្នែកខ្លះនៃកម្មវិធីនេះនឹងនៅតែអាចមើលឃើញបានគ្រប់ពេល។ ប្រសិនបើមុខងារនេះដំណើរការមិនប្រក្រតីទេ សូមបិទវា។"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"បិទ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"កំពុងរៀបចំ <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"កំពុងពិនិត្យរកកំហុស"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"បានរកឃើញ <xliff:g id="NAME">%s</xliff:g> ថ្មី"</string>
@@ -1714,4 +1710,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"វាយបញ្ចូលម៉ោង"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ប្តូរទៅមុខងារបញ្ចូលអក្សរសម្រាប់ការបញ្ចូលម៉ោង។"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ប្តូរទៅមុខងារនាឡិកាសម្រាប់ការបញ្ចូលម៉ោង។"</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 6cccbc2..2fedb79 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ಭಾಷೆ ಮತ್ತು ವಿನ್ಯಾಸವನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"ಇತರ ಅಪ್ಲಿಕೇಶನ್ಗಳ ಮೇಲೆ <xliff:g id="NAME">%s</xliff:g> ಎಳೆಯಿರಿ"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> ಅಪ್ಲಿಕೇಶನ್ ಮೇಲೆ ಕಾಣಿಸುತ್ತಿದೆ."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"ಈ ಅಪ್ಲಿಕೇಶನ್ನ ಭಾಗಗಳು ಎಲ್ಲ ಸಮಯದಲ್ಲೂ ಕಾಣುತ್ತಿರುತ್ತದೆ. ಈ ವೈಶಿಷ್ಟ್ಯವು ಸರಿಯಾಗಿ ಕೆಲಸ ಮಾಡದಿದ್ದರೆ, ಆಫ್ ಮಾಡಿ."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ಆಫ್ ಮಾಡಿ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> ಅನ್ನು ಸಿದ್ಧಪಡಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"ದೋಷಗಳನ್ನು ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"ಹೊಸ <xliff:g id="NAME">%s</xliff:g> ಪತ್ತೆಯಾಗಿದೆ"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"ಸಮಯದಲ್ಲಿ ಟೈಪ್ ಮಾಡಿ"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ಸಮಯವನ್ನು ನಮೂದಿಸಲು ಪಠ್ಯದ ನಮೂನೆಗೆ ಬದಲಿಸಿ."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ಸಮಯವನ್ನು ನಮೂದಿಸಲು ಗಡಿಯಾರದ ನಮೂನೆಗೆ ಬದಲಿಸಿ."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index cf1289c..22d6dc6 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"탭하여 언어와 레이아웃을 선택하세요."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g>이(가) 다른 앱 위에 표시됨"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> 앱이 상단에 표시됨"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"이 앱의 일부는 항상 표시될 수도 있습니다. 기능이 제대로 작동되지 않으면 사용 중지하세요."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"사용 중지"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> 준비 중"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"오류 확인 중"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"새로운 <xliff:g id="NAME">%s</xliff:g> 감지됨"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"시간 입력"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"시간 입력을 위해 텍스트 입력 모드로 전환합니다."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"시간 입력을 위해 시계 모드로 전환합니다."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 33f72db..99d0ffd 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Тил жана калып тандоо үчүн таптап коюңуз"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> колдонмосун башка терезелердин үстүнөн көрсөтүү"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> колд-сун эң үстүндө көрсөтүү"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Бул колдонмонун бөлүктөрү дайыма көрүнүп турушу мүмкүн. Эгер бул функция туура иштебесе, аны өчүрүп коюңуз."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ӨЧҮРҮҮ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> даярдалууда"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Каталар текшерилүүдө"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Жаңы <xliff:g id="NAME">%s</xliff:g> аныкталды"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Убакытты жазыңыз"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Убакытты текст киргизүү режиминде киргизиңиз."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Убакытты дубал саатынын режиминде киргизиңиз."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index ba71473..654d8e6 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ແຕະເພື່ອເລືອກພາສາ ແລະ ໂຄງແປ້ນພິມ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> ແຕ້ມທັບແອັບອື່ນ"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"ແອັບ <xliff:g id="NAME">%s</xliff:g> ກຳລັງສະແດງຢູ່ໜ້າສຸດ."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"ບາງພາກສ່ວນຂອງແອັບນີ້ຈະປາກົດຢູ່ຕະຫຼອດເວລາ. ຫາກຄຸນສົມບັດນີ້ໃຊ້ໄດ້ບໍ່ດີ, ໃຫ້ປິດມັນໄວ້."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ປິດໄວ້"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"ກຳລັງກຽມ <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"ກຳລັງກວດຫາຂໍ້ຜິດພາດ"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"ກວດພົບ <xliff:g id="NAME">%s</xliff:g> ໃໝ່ແລ້ວ"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"ພິມເວລາໃສ່"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ສະຫຼັບໄປໃຊ້ໂໝດປ້ອນຂໍ້ຄວາມສຳລັບການປ້ອນເວລາ."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ສະຫຼັບໄປໃຊ້ໂໝດໂມງສຳລັບການປ້ອນເວລາ."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 07e730c..f808a99 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1207,14 +1207,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Palieskite, kad pasirinktumėte kalbą ir išdėstymą"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> programa rodoma virš kitų programų"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> programa rodoma virš kitų."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Šios programos dalys gali likti matomos visą laiką. Jei ši funkcija tinkamai neveikia, išjunkite ją."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"IŠJUNGTI"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Ruošiama <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Tikrinama, ar nėra klaidų"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Aptikta nauja <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1774,4 +1770,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Įveskite laiką"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Laiko įvestį pateikti perjungus į teksto įvesties režimą."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Laiko įvestį pateikti perjungus į laikrodžio režimą."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 06bcd6b..e7b4800 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1187,14 +1187,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Pieskarieties, lai atlasītu valodu un izkārtojumu"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Lietotne <xliff:g id="NAME">%s</xliff:g> tiek rādīta pāri citām lietotnēm"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Lietotne <xliff:g id="NAME">%s</xliff:g> ir redzama virspusē."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Šīs lietotnes daļas joprojām var būt redzamas visu laiku. Ja šī funkcija nedarbojas pareizi, izslēdziet to."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"IZSLĒGT"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Notiek <xliff:g id="NAME">%s</xliff:g> sagatavošana"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Tiek meklētas kļūdas"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Tika atrasta jauna <xliff:g id="NAME">%s</xliff:g>."</string>
@@ -1743,4 +1739,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Ierakstiet laiku"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Lai ievadītu laiku, ieslēdziet teksta ievades režīmu."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Lai ievadītu laiku, ieslēdziet pulksteņa režīmu."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index efb339b..8dae798 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -83,10 +83,10 @@
<string name="RuacMmi" msgid="7827887459138308886">"Одбивање несакани вознемирувачки повици"</string>
<string name="CndMmi" msgid="3116446237081575808">"Испорака на повикувачки број"</string>
<string name="DndMmi" msgid="1265478932418334331">"Не вознемирувај"</string>
- <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Стандардно, повикувачот со овој ИД е ограничен. Следен повик: ограничен"</string>
- <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Стандардно, повикувачот со овој ИД е ограничен. Следен повик: не е ограничен"</string>
- <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Стандардно, повикувачот со овој ИД не е ограничен. Следен повик: ограничен"</string>
- <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Стандардно, повикувачот со овој ИД не е ограничен. Следен повик: не е ограничен"</string>
+ <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Стандардно, повикувачот со овој ID е ограничен. Следен повик: ограничен"</string>
+ <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Стандардно, повикувачот со овој ID е ограничен. Следен повик: не е ограничен"</string>
+ <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Стандардно, повикувачот со овој ID не е ограничен. Следен повик: ограничен"</string>
+ <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Стандардно, повикувачот со овој ID не е ограничен. Следен повик: не е ограничен"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Услугата не е предвидена."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Не може да го промените поставувањето за ID на повикувач."</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Услугата за податоци е блокирана."</string>
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Допрете за избирање јазик и распоред"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> пишува врз други апликации"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Апликацијата <xliff:g id="NAME">%s</xliff:g> е одозгора."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Делови од апликацијава може да бидат видливи цело време. Ако функцијава не работи правилно, исклучете ја."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ИСКЛУЧИ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Се подготвува <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Се проверува за грешки"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Откриена е нова <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1715,4 +1711,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Внесете време"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Префрлете се на режимот за внесување текст за да внесете време."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Префрлете се на режимот за часовник за да внесете време."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 13a2c6b..0226a85 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ഭാഷയും ലേഔട്ടും തിരഞ്ഞെടുക്കുന്നതിന് ടാപ്പുചെയ്യുക"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> മറ്റ് ആപ്പുകൾക്ക് മുകളിൽ പ്രവർത്തിക്കും"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> മുകളിൽ ദൃശ്യമാകുന്നു."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"ഈ ആപ്പിന്റെ ഭാഗങ്ങൾ തുടർന്നും ദൃശ്യമായേക്കാം. ഈ ഫീച്ചർ ശരിയായി പ്രവർത്തിക്കുന്നില്ലെങ്കിൽ അത് ഓഫ് ചെയ്യുക."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ഓഫാക്കുക"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> തയ്യാറാകുന്നു"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"പിശകുകളുണ്ടോയെന്നു പരിശോധിക്കുന്നു"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"പുതിയ <xliff:g id="NAME">%s</xliff:g> എന്നതിനെ തിരിച്ചറിഞ്ഞു"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"സമയത്തിൽ ടൈപ്പുചെയ്യുക"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"സമയം നൽകുന്നതിന് ടെക്സ്റ്റ് ഇൻപുട്ട് മോഡിലേക്ക് മാറുക."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"സമയം നൽകുന്നതിന് ക്ലോക്ക് മോഡിലേക്ക് മാറുക."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 7131be3..2af2a21 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Хэл болон бүдүүвчийг сонгохын тулд дарна уу"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> бусад аппын дээр гарч ирсэн"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> апп дээр харагдаж байна."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Энэ аппын зарим хэсэг нь тогтмол харагдана. Энэ онцлог буруу ажиллаж байвал унтраана уу."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"УНТРААХ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g>-ыг бэлдэж байна"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Алдааг шалгаж байна"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Шинэ <xliff:g id="NAME">%s</xliff:g> илэрлээ"</string>
@@ -1710,4 +1706,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Хугацааг бичнэ үү"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Цагийг оруулахын тулд текст оруулах горимд шилжүүлнэ үү."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Цагийг оруулахын тулд цагийн горимд шилжүүлнэ үү."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 370564d..de3bed5 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -515,8 +515,8 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"होल्डरला वाहकद्वारे-प्रदान केलेल्या कॉन्फिगरेशन अॅपची विनंती करण्याची अनुमती देते. सामान्य अॅप्ससाठी कधीही आवश्यक नसावे."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"नेटवर्क स्थितींवरील निरीक्षणांसाठी ऐका"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"अनु्प्रयोगाला नेटवर्क स्थितींवरील निरीक्षणे ऐकण्यासाठी अनुमती देते. सामान्य अॅप्ससाठी कधीही आवश्यक नसावे."</string>
- <string name="permlab_setInputCalibration" msgid="4902620118878467615">"इनपुट डिव्हाइस अंशांकन बदला"</string>
- <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"स्पर्श स्क्रीनची मापन प्राचले सुधारित करण्यासाठी अॅप ला अनुमती देते. सामान्य अॅप्स साठी कधीही आवश्यक नसते."</string>
+ <string name="permlab_setInputCalibration" msgid="4902620118878467615">"इनपुट डिव्हाइस कॅलिब्रेशन बदला"</string>
+ <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"स्पर्श स्क्रीनची कॅलिब्रेशन प्राचले सुधारित करण्यासाठी अॅप ला अनुमती देते. सामान्य अॅप्स साठी कधीही आवश्यक नसते."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM प्रमाणपत्रांवर प्रवेश करा"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"DRM प्रमाणपत्रांची तरतूद करण्यासाठी आणि वापरण्यासाठी अनुप्रयोगास अनुमती देते. सामान्य अॅप्सकरिता कधीही आवश्यकता नसते."</string>
<string name="permlab_handoverStatus" msgid="7820353257219300883">"Android बीम स्थानांतरण स्थिती प्राप्त करा"</string>
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा आणि लेआउट निवडण्यासाठी टॅप करा"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> इतर अॅप्सवर काढा"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> अॅप शीर्षस्थानी प्रदर्शित होत आहे"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"या अॅपचे भाग सर्व वेळी दृश्यमान असू शकतात. हे वैशिष्ट्य बरोबर काम करत नसल्यास, ते बंद करा."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"बंद करा"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> तयार करीत आहे"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"त्रुटींसाठी तपासत आहे"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"नवीन <xliff:g id="NAME">%s</xliff:g> आढळले"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"वेळ टाइप करा"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"वेळ इनपुटसाठी मजकूर इनपुट मोडवर स्विच करा."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"वेळ इनपुटसाठी घड्याळ मोडवर स्विच करा."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 39c950a..171a02a 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ketik untuk memilih bahasa dan susun atur"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> melukis di atas apl lain"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Apl <xliff:g id="NAME">%s</xliff:g> dipaparkan di bahagian atas."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Sebahagian daripada apl ini mungkin kekal kelihatan pada sepanjang masa. Jika ciri ini tidak berfungsi dengan betul, matikan ciri ini."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"MATIKAN"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Menyediakan <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Menyemak untuk mengesan ralat"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"<xliff:g id="NAME">%s</xliff:g> baharu dikesan"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Taipkan masa"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Beralih ke mod input teks untuk input masa."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Beralih ke mod jam untuk input masa."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index b9269af..9bd2602 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ဘာသာစကားနှင့် အသွင်အပြင်ရွေးချယ်ရန် တို့ပါ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> သည် အခြားအက်ပ်များအပေါ်တွင် ပေါ်ပါမည်"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> အက်ပ်ကို အပေါ်ဆုံးတွင် ပြမည်။"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"ဤအက်ပ်၏ တစ်စိတ်တစ်ဒေသကို အမြဲမြင်တွေ့နိုင်ပါမည်။ အကယ်၍ ဤဝန်ဆောင်မှုသည် မှန်မှန်ကန်ကန် အလုပ်မလုပ်လျှင် ၎င်းကို ပိတ်လိုက်ပါ။"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ပိတ်ပါ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> ပြင်ဆင်နေသည်"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"အမှားအယွင်းများ စစ်ဆေးနေသည်"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"<xliff:g id="NAME">%s</xliff:g> အသစ်တွေ့ရှိပါသည်"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"အချိန်ကို ရိုက်ရန်"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"အချိန်ထည့်သွင်းရန် စာသားထည့်သွင်းမှုမုဒ်သို့ ပြောင်းပါ။"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"အချိန်ထည့်သွင်းမှုအတွက် နာရီမုဒ်သို့ ပြောင်းပါ။"</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 090cb9e..8643a2e 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Trykk for å velge språk og layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> ligger over andre apper"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g>-appen vises øverst."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Deler av denne appen kan være synlige til enhver tid. Slå denne funksjonen av hvis den ikke fungerer som den skal."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"SLÅ AV"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Forbereder <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Sjekker for feil"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"<xliff:g id="NAME">%s</xliff:g> ble oppdaget"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Skriv inn klokkeslett"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Bytt til tekstinndatamodus for tidsinndata."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Bytt til klokkemodus for tidsinndata."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 0b028a2..f41269a 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1173,14 +1173,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा र लेआउट चयन गर्न ट्याप गर्नुहोस्"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> लाई अन्य अनुप्रयोगहरूमा देखिन दिनुहोस्"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> अनुप्रयोग शीर्षमा देखाउँदै।"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"यो अनुप्रयोगका केही अंशहरू सधैँ देखिरहन सक्छन्। यो सुविधाले सही ढंगले काम गरिरहेको छैन भने, यसलाई बन्द गर्नुहोस्।"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"निष्क्रिय पार्नुहोस्"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"तयारी गर्दै <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"त्रुटिहरूको लागि जाँच गर्दै"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"नयाँ <xliff:g id="NAME">%s</xliff:g> भेटियो"</string>
@@ -1718,4 +1714,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"समय टाइप गर्नुहोस्"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"समय इनपुट गर्न पाठ इनपुट मोडमा स्विच गर्नुहोस्।"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"समय इनपुट गर्न घडी मोडमा स्विच गर्नुहोस्।"</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 1c707f9..60f3363 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tik om een taal en indeling te selecteren"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> wordt weergegeven over andere apps"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g>-app bovenop weergeven."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Delen van deze app blijven altijd zichtbaar. Als deze functie niet correct werkt, schakel je deze uit."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"UITSCHAKELEN"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> voorbereiden"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Controleren op fouten"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Nieuwe <xliff:g id="NAME">%s</xliff:g> gedetecteerd"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Typ een tijd"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Schakel naar de tekstinvoermodus om de tijd in te voeren."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Schakel naar de klokmodus om de tijd in te voeren."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 182b3a5..34c0396 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ਭਾਸ਼ਾ ਅਤੇ ਖਾਕਾ ਚੁਣਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> ਹੋਰਾਂ ਐਪਾਂ ਉੱਤੇ ਪਸਰ ਸਕਦੀ ਹੈ"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> ਐਪ ਹੋਰ ਐਪਾਂ ਉੱਤੇ ਪਸਰੀ ਦਿਸ ਰਹੀ ਹੈ।"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਇਸ ਐਪ ਦੇ ਕੁਝ ਹਿੱਸੇ ਹਰ ਸਮੇਂ ਵਿਖਾਈ ਦੇਣ। ਜੇਕਰ ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਨਹੀਂ ਕਰ ਰਹੀ ਹੈ, ਤਾਂ ਇਸਨੂੰ ਬੰਦ ਕਰੋ।"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ਬੰਦ ਕਰੋ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> ਤਿਆਰ ਹੋ ਰਿਹਾ ਹੈ"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"ਤਰੁੱਟੀਆਂ ਦੀ ਜਾਂਚ ਕਰ ਰਿਹਾ ਹੈ"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"ਨਵੇਂ <xliff:g id="NAME">%s</xliff:g> ਦਾ ਪਤਾ ਲਗਾਇਆ ਗਿਆ"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"ਸਮਾਂ ਟਾਈਪ ਕਰੋ"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ਸਮਾਂ ਇਨਪੁੱਟ ਕਰਨ ਲਈ ਲਿਖਤ ਇਨਪੁੱਟ ਮੋਡ \'ਤੇ ਬਦਲੀ ਕਰੋ।"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ਸਮਾਂ ਇਨਪੁੱਟ ਕਰਨ ਲਈ ਘੜੀ ਮੋਡ \'ਤੇ ਬਦਲੀ ਕਰੋ।"</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 29c91b6..9ce2f69 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1207,14 +1207,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Kliknij, by wybrać język i układ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Aplikacja <xliff:g id="NAME">%s</xliff:g> wyświetla się nad innymi"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Aplikacja <xliff:g id="NAME">%s</xliff:g> jest nad innymi."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Fragmenty tej aplikacji mogą być widoczne przez cały czas. Jeśli ta funkcja nie działa prawidłowo, wyłącz ją."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"WYŁĄCZ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Przygotowuję: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Sprawdzanie w poszukiwaniu błędów"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Wykryto nowy nośnik: <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1774,4 +1770,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Podaj czas"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Aby wprowadzić czas, włącz tryb wprowadzania tekstu."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Aby wprowadzić czas, włącz tryb zegara."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index f66df7d..92dcc90b 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Sobreposição do <xliff:g id="NAME">%s</xliff:g> a outros apps"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> exibido na parte superior da tela."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Partes desse app podem ficar sempre visíveis. Se esse recurso não estiver funcionando corretamente, desative-o."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESATIVAR"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparando <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Procurando erros"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Novo <xliff:g id="NAME">%s</xliff:g> detectado"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Digite o horário"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Alterne para o modo de entrada de texto para informar o horário."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Alterne para o modo de relógio para informar o horário."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index c4e0fbc..dfc64d3 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o esquema"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Sobrepor a aplicação <xliff:g id="NAME">%s</xliff:g> a outras aplicações"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Aplic. <xliff:g id="NAME">%s</xliff:g> apresentada por cima."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"É possível que partes desta aplicação permaneçam sempre visíveis. Se esta funcionalidade não estiver a funcionar corretamente, desative-a."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESATIVAR"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"A preparar o <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"A verificar a presença de erros"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Novo <xliff:g id="NAME">%s</xliff:g> detetado"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Introduza a hora"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Mude para o modo de introdução de texto para a introdução da hora."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Mude para o modo de relógio para a introdução da hora."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index f66df7d..92dcc90b 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Sobreposição do <xliff:g id="NAME">%s</xliff:g> a outros apps"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> exibido na parte superior da tela."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Partes desse app podem ficar sempre visíveis. Se esse recurso não estiver funcionando corretamente, desative-o."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESATIVAR"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparando <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Procurando erros"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Novo <xliff:g id="NAME">%s</xliff:g> detectado"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Digite o horário"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Alterne para o modo de entrada de texto para informar o horário."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Alterne para o modo de relógio para informar o horário."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index c4416f8..d95e715 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1187,14 +1187,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Atingeți pentru a selecta limba și aspectul"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> afișează deasupra altor aplicații"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> se afișează deasupra."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Este posibil ca unele părți ale acestei aplicații să rămână vizibile permanent. Dacă această caracteristică nu funcționează corect, dezactivați-o."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DEZACTIVAȚI"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Se pregătește <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Se verifică dacă există erori"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"A fost detectat un nou <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1743,4 +1739,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Introduceți ora"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Pentru a introduce ora, comutați la modul de introducere a textului."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Pentru a introduce ora, comutați la modul ceas."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 518023d..97c7b987 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1207,14 +1207,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Нажмите, чтобы выбрать язык и раскладку"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Интерфейс этих приложений показывается поверх других окон: <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g>: показ поверх других окон"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Некоторые элементы интерфейса этого приложения могут всегда находиться поверх других окон. Если функция работает некорректно, отключите ее."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ОТКЛЮЧИТЬ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Подготовка карты \"<xliff:g id="NAME">%s</xliff:g>\"…"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Поиск ошибок"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Обнаружена новая карта \"<xliff:g id="NAME">%s</xliff:g>\""</string>
@@ -1774,4 +1770,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Введите время"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Чтобы ввести время, перейдите в режим ввода текста."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Чтобы ввести время, перейдите в режим часов."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index a8f6713..ff0c7d5 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1169,14 +1169,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"භාෂාව හා පිරිසැලසුම තේරීමට තට්ටු කරන්න"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"අනෙක් යෙදුම්වලට උඩින් <xliff:g id="NAME">%s</xliff:g> අදින්න"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> යෙදුම ඉහළින්ම සංදර්ශනය වේ."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"මෙම යෙදුමෙහි කොටස් සැම විටම දෘශ්යමානව පවතිනු ඇත. මෙම විශේෂාංගය නිවැරදිව ක්රියා නොකරන්නේ නම්, එය ක්රියාවිරහිත කරන්න."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ක්රියා විරහිත කරන්න"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> සූදානම් කරමින්"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"වැරදි සඳහා පරීක්ෂා කරමින්"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"නව <xliff:g id="NAME">%s</xliff:g> අනාවරණය කරන ලදි"</string>
@@ -1714,4 +1710,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"වේලාව ටයිප් කරන්න"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"වේලා ආදානය සඳහා ආදාන ප්රකාරය වෙත මාරු වෙන්න."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"වේලා ආදානය සඳහා ඔරලෝසු ප්රකාරය වෙත මාරු වෙන්න."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 20fcda5..660a256 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1207,14 +1207,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Klepnutím vyberte jazyk a rozloženie"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁÄBCČDĎDZDŽEÉFGHCHIÍJKLĽMNŇOÓÔPRŔSŠTŤUÚVWXYÝZŽ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Aplikácia <xliff:g id="NAME">%s</xliff:g> sa vykreslí nad ostatnými aplikáciami"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Apl. <xliff:g id="NAME">%s</xliff:g> sa zobrazuje navrchu."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Časti tejto aplikácie môžu zostať neustále viditeľné. Ak táto funkcia nepracuje správne, vypnite ju."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"VYPNÚŤ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Pripravuje sa úložisko <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Prebieha kontrola chýb"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Bolo zistené nové úložisko <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1774,4 +1770,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Zadajte čas"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Ak chcete zadať čas, prepnite na textový režim vstupu"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Ak chcete zadať čas, prepnite na režim hodín."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index eca5c21..0abd212 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1207,14 +1207,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dotaknite se, če želite izbrati jezik in postavitev."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Aplikacija <xliff:g id="NAME">%s</xliff:g> riše čez druge aplikacije"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Apl. <xliff:g id="NAME">%s</xliff:g> se prikazuje čez druge."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Deli te aplikacije lahko ostanejo vseskozi vidni. Če ta funkcija ne deluje pravilno, jo izklopite."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"IZKLOP"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Pripravljanje shrambe <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Iskanje napak"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Zaznana je bila nova shramba <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1774,4 +1770,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Vnesite uro"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Preklopite na način za vnašanje besedila, da vnesete čas."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Preklopite na način ure, da vnesete čas."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 25905d5..cc740a6 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Trokit për të zgjedhur gjuhën dhe strukturën"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> mbivendoset mbi aplikacionet e tjera"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Aplikacioni <xliff:g id="NAME">%s</xliff:g> po shfaqet në krye."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Disa pjesë të këtij aplikacioni mund të mbeten të dukshme gjatë të gjithë kohës. Nëse ky funksion nuk po funksionon si duhet, çaktivizoje atë."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ÇAKTIVIZO"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Po përgatit <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Po kontrollon për gabime"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"U zbulua karta e re <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Shkruaj kohën"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Kalo te modaliteti i hyrjes së tekstit për hyrjen e kohës."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Kalo te modaliteti i orës për hyrjen e kohës."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index e81f074..27f780a 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1187,14 +1187,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Додирните да бисте изабрали језик и распоред"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Апликација <xliff:g id="NAME">%s</xliff:g> се приказује преко других апликација"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Апликација <xliff:g id="NAME">%s</xliff:g> се приказује преко."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Делови ове апликације могу да остану видљиви у сваком тренутку. Ако ова функција не ради исправно, искључите је."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ИСКЉУЧИ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> се припрема"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Проверава се да ли постоје грешке"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Нови уређај <xliff:g id="NAME">%s</xliff:g> је откривен"</string>
@@ -1743,4 +1739,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Унесите време"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Пређите у режим уноса текста ради уноса времена."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Пређите у режим сата ради уноса времена."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 4562231..7410322 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tryck om du vill välja språk och layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> gör överlagringar på andra appar"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Appen <xliff:g id="NAME">%s</xliff:g> visas ovanpå."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Delar av den här appen kanske alltid är synliga. Inaktivera funktionen om den inte fungerar som den ska."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"INAKTIVERA"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Förbereder ditt <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Söker efter fel"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Nytt <xliff:g id="NAME">%s</xliff:g> har hittats"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Ange tid"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Byt till textinmatningsläget och ange tid."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Byt till klockläget och ange tid."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index a85d1dc..f266496 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1165,14 +1165,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Gonga ili uchague lugha na muundo"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> huchomoza kwenye programu zingine"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Programu ya <xliff:g id="NAME">%s</xliff:g> inaonekana juu ya zingine."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Huenda sehemu za programu hii zikaendelea kuonekana kila wakati. Zima kipengele hiki kama hakifanyi kazi vizuri."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ZIMA"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Inaandaa <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Inakagua hitilafu"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"<xliff:g id="NAME">%s</xliff:g> mpya imegunduliwa"</string>
@@ -1710,4 +1706,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Andika wakati"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Badilisha iwe katika hali ya maandishi wakati wa kuweka muda."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Badilisha umbo liwe la saa ya mishale wakati wa kuweka muda."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 4c97780..7ab8c79 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"மொழியையும் தளவமைப்பையும் தேர்ந்தெடுக்க, தட்டவும்"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"பிற பயன்பாடுகளின் மேல் <xliff:g id="NAME">%s</xliff:g> செயல்படும்"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"பிற பயன்பாடுகளின் மேலே <xliff:g id="NAME">%s</xliff:g> பயன்பாடு காட்டப்படுகிறது."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"இந்தப் பயன்பாட்டின் பகுதிகள், எல்லா நேரமும் காட்டப்படக்கூடும். இந்த அம்சம் சரியாகச் செயல்படவில்லை எனில், அதை முடக்கவும்."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"முடக்கு"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> தயாராகிறது"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"பிழைகள் உள்ளதா எனப் பார்க்கிறது"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"புதிய <xliff:g id="NAME">%s</xliff:g> கண்டறியப்பட்டது"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"நேரத்தை உள்ளிடவும்"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"உரை உள்ளீட்டிற்காக, கடிகாரப் பயன்முறைக்கு மாற்றும்."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"நேர உள்ளீட்டிற்காக, கடிகாரப் பயன்முறைக்கு மாற்றும்."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 090b43c..905ccbe 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"భాష మరియు లేఅవుట్ను ఎంచుకోవడానికి నొక్కండి"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g>ని ఇతర అనువర్తనాలలో చూపండి"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"ఎగువన <xliff:g id="NAME">%s</xliff:g> అనువర్తనం కనిపిస్తోంది."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"ఈ అనువర్తనంలోని భాగాలు అన్ని సమయాల్లో కనిపిస్తూ ఉండవచ్చు. ఈ లక్షణం సరిగ్గా పని చేయకపోతే, దీన్ని ఆఫ్ చేయండి."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ఆఫ్ చేయి"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g>ని సిద్ధం చేస్తోంది"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"లోపాల కోసం తనిఖీ చేస్తోంది"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"కొత్త <xliff:g id="NAME">%s</xliff:g> గుర్తించబడింది"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"సమయంలో టైప్ చేయండి"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"సమయాన్ని నమోదు చేయడం కోసం వచన నమోదు మోడ్కి మారండి."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"సమయాన్ని నమోదు చేయడం కోసం గడియారం మోడ్కు మారండి."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 992944a..bb893fb 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -322,8 +322,8 @@
<string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"แอปนี้สามารถปรากฏเหนือแอปอื่นๆ หรือส่วนอื่นของหน้าจอ ซึ่งอาจรบกวนการใช้งานตามปกติของแอปและทำให้ลักษณะการแสดงแอปอื่นๆ เปลี่ยนไป"</string>
<string name="permlab_runInBackground" msgid="7365290743781858803">"ทำงานในพื้นหลัง"</string>
<string name="permdesc_runInBackground" msgid="7370142232209999824">"แอปนี้สามารถทำงานในพื้นหลัง ซึ่งอาจทำให้แบตเตอรี่หมดเร็วขึ้น"</string>
- <string name="permlab_useDataInBackground" msgid="8694951340794341809">"ใช้เน็ตมือถือในพื้นหลัง"</string>
- <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"แอปนี้สามารถใช้เน็ตมือถือในพื้นหลัง ซึ่งอาจเพิ่มปริมาณการใช้อินเทอร์เน็ต"</string>
+ <string name="permlab_useDataInBackground" msgid="8694951340794341809">"ใช้เน็ตในพื้นหลัง"</string>
+ <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"แอปนี้สามารถใช้เน็ตในพื้นหลัง ซึ่งอาจเพิ่มปริมาณการใช้อินเทอร์เน็ต"</string>
<string name="permlab_persistentActivity" msgid="8841113627955563938">"ทำให้แอปพลิเคชันทำงานเสมอ"</string>
<string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"อนุญาตให้แอปพลิเคชันทำให้ส่วนหนึ่งของตัวเองคงอยู่ถาวรในหน่วยความจำ ซึ่งจะจำกัดพื้นที่หน่วยความจำที่ใช้งานได้ของแอปพลิเคชันอื่นๆ และทำให้แท็บเล็ตทำงานช้าลง"</string>
<string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"อนุญาตให้แอปทำให้บางส่วนของแอปนั้นอยู่ในหน่วยความจำเสมอ ซึ่งอาจจำกัดพื้นที่หน่วยความจำสำหรับแอปอื่นและทำให้ทีวีช้าลง"</string>
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"แตะเพื่อเลือกภาษาและรูปแบบ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> แสดงทับแอปอื่น"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"แอป <xliff:g id="NAME">%s</xliff:g> แสดงอยู่ด้านบนสุด"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"ส่วนต่างๆ ของแอปนี้อาจปรากฏอยู่ตลอดเวลา หากคุณลักษณะนี้ไม่ทำงานอย่างถูกต้อง ให้ปิดแอป"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ปิด"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"กำลังเตรียม <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"กำลังตรวจหาข้อผิดพลาด"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"ตรวจพบ <xliff:g id="NAME">%s</xliff:g> ใหม่"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"พิมพ์เวลา"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"สลับไปโหมดป้อนข้อความเพื่อป้อนเวลา"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"สลับไปโหมดนาฬิกาเพื่อป้อนเวลา"</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 4ec0d13..05ae6bf 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"I-tap upang pumili ng wika at layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"I-draw over ang <xliff:g id="NAME">%s</xliff:g> sa iba pang app"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Ipinapakita ang <xliff:g id="NAME">%s</xliff:g> app sa itaas."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Maaaring manatiling nakikita ang mga bahagi ng app na ito sa lahat ng oras. Kung hindi gumagana nang tama ang feature na ito, i-off ito."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"I-OFF"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Inihahanda ang <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Sinusuri para sa mga error"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Na-detect ang bagong <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"I-type ang oras"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Lumipat sa pamamaraan ng pag-input ng text para sa input na oras."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Lumipat sa mode ng orasan para sa input na oras."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index f9cd837..b56d466 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dili ve düzeni seçmek için hafifçe dokunun"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> diğer uygulamaların üzerinde görüntüleniyor"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> üstte gösteriliyor."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Bu uygulamanın bazı bölümleri her zaman görünür durumda kalabilir. Bu özellik düzgün çalışmıyorsa kapatın."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"KAPAT"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> hazırlanıyor"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Hatalar denetleniyor"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Yeni <xliff:g id="NAME">%s</xliff:g> algılandı"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Zamanı yazın"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Zaman girişi için metin girişi moduna geçin."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Zaman girişi için saat moduna geçin."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index acf6614..e99d88b 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1207,14 +1207,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Торкніться, щоб вибрати мову та розкладку"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> відображається поверх інших додатків"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> відображається поверх."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Частина цього додатка може постійно залишатися видимою. Якщо ця функція працює неправильно, вимкніть її."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ВИМКНУТИ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Підготовка пристрою пам’яті <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Виявлення помилок"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Виявлено новий пристрій пам’яті (<xliff:g id="NAME">%s</xliff:g>)"</string>
@@ -1774,4 +1770,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Введіть час"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Перейти в текстовий режим, щоб ввести час."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Перейти в режим годинника, щоб ввести час."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 7e8b110..41c265d 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"زبان اور لے آؤٹ منتخب کرنے کیلئے تھپتھپائیں"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> کو دیگر ایپس پر ڈرا کریں"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> ایپ اوپر ڈسپلے ہورہی ہے۔"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"ممکن ہے اس ایپ کے حصے ہر وقت مرئی رہیں۔ اگر یہ خصوصیت ٹھیک سے کام نہیں کررہی ہے، تو اسے آف کردیں۔"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"آف کریں"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> تیار کیا جا رہا ہے"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"خرابیوں کیلئے چیک کیا جا رہا ہے"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"نئے <xliff:g id="NAME">%s</xliff:g> کا پتا چلا"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"وقت ٹائپ کریں"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"وقت ان پٹ کے لیے ٹیکسٹ ان پٹ وضع پر سوئچ کریں۔"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"وقت ان پٹ کے لیے گھڑی وضع پر سوئچ کریں۔"</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 3210143..5309181 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1168,14 +1168,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Til va sxemani belgilash uchun bosing"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> boshqa ilovalar ustidan ochiladi"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> eng tepada ochilgan."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Bu ilovaning ba’zi qismlari har doim ko‘rinib qolishi mumkin. Agar bu funksiya to‘g‘ri ishlamasa, uni o‘chirib qo‘ying."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"O‘CHIRIB QO‘YISH"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> tayyorlanmoqda"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Xatolar qidirilmoqda"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Yangi <xliff:g id="NAME">%s</xliff:g> kartasi aniqlandi"</string>
@@ -1713,4 +1709,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Vaqtni kiriting"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Vaqtni kiritish uchun matn kiritish rejimiga o‘ting."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Vaqtni kiritish uchun soat rejimiga o‘ting."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 4ed7dc9..69e0ec3 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Nhấn để chọn ngôn ngữ và bố cục"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> vẽ lên các ứng dụng khác"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Ứng dụng <xliff:g id="NAME">%s</xliff:g> hiển thị ở trên cùng."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Các phần của ứng dụng này có thể vẫn hiển thị mọi lúc. Nếu tính năng này không hoạt động bình thường, hãy tắt tính năng này."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"TẮT"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Đang chuẩn bị <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Đang kiểm tra lỗi"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Đã phát hiện <xliff:g id="NAME">%s</xliff:g> mới"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Nhập thời gian"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Chuyển sang chế độ nhập văn bản để nhập thời gian."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Chuyển sang chế độ đồng hồ để nhập thời gian."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 1e71448..2236f1f 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"点按即可选择语言和布局"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g>会在其他应用的上层显示内容"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g>应用目前显示在上层。"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"此应用的某些部分可能会一直保持可见状态。如果此功能未能正常运行,请将其关闭。"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"关闭"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"正在准备<xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"检查是否有错误"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"检测到新的<xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"请输入时间"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"切换到文字输入模式来输入时间。"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"切换到时钟模式来输入时间。"</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index b1273f4..db98761 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"輕按即可選取語言和鍵盤配置"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"「<xliff:g id="NAME">%s</xliff:g>」會覆蓋其他應用程式"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"「<xliff:g id="NAME">%s</xliff:g>」應用程式目前在最上層顯示。"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"畫面上可能會一直保持顯示此應用程式的某些部分。如果此功能無法正常運作,請將其關閉。"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"關閉"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"正在準備<xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"正在檢查錯誤"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"已偵測到新<xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"輸入時間"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"切換至文字輸入模式即可輸入時間。"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"切換至時鐘模式即可輸入時間。"</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index b3b7e18..7f4c01b 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -321,9 +321,9 @@
<string name="permlab_systemAlertWindow" msgid="7238805243128138690">"這個應用程式可顯示在其他應用程式上方"</string>
<string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"這個應用程式可顯示在其他應用程式上方或畫面中的其他位置。你可能會無法照常使用應用程式,且其他應用程式的顯示方式可能會受到影響。"</string>
<string name="permlab_runInBackground" msgid="7365290743781858803">"在背景執行"</string>
- <string name="permdesc_runInBackground" msgid="7370142232209999824">"這個應用程式可在背景執行,這樣可能會加快耗電速度。"</string>
+ <string name="permdesc_runInBackground" msgid="7370142232209999824">"這個應用程式可在背景執行,這樣可能導致耗電速度加快。"</string>
<string name="permlab_useDataInBackground" msgid="8694951340794341809">"在背景使用行動數據連線"</string>
- <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"這個應用程式可在背景使用行動數據連線,這樣可能會增加數據用量。"</string>
+ <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"這個應用程式可在背景使用行動數據連線,這樣可能導致數據用量增加。"</string>
<string name="permlab_persistentActivity" msgid="8841113627955563938">"一律執行應用程式"</string>
<string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"允許應用程式的部分內容常駐在記憶體中。這項設定可能會限制其他應用程式可用的記憶體,並拖慢平板電腦運作速度。"</string>
<string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"允許應用程式的部分內容常駐在記憶體中。這項設定可能會限制其他應用程式可用的記憶體,造成電視的運作速度變慢。"</string>
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"輕觸即可選取語言和版面配置"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g>會在其他應用程式上層繪製內容"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g>應用程式目前顯示在最上層。"</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"這個應用程式的某些部分會一直保持顯示。如果這項功能未正常運作,請將它關閉。"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"關閉"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"正在準備「<xliff:g id="NAME">%s</xliff:g>」"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"正在檢查錯誤"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"偵測到新的「<xliff:g id="NAME">%s</xliff:g>」"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"輸入時間"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"切換至文字輸入模式來輸入時間。"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"切換至時鐘模式來輸入時間。"</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 6a82ed5..dadd6c0 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1167,14 +1167,10 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Thepha ukuze ukhethe ulimi nesakhiwo"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <!-- no translation found for alert_windows_notification_channel_name (7443890103456396837) -->
- <skip />
- <!-- no translation found for alert_windows_notification_title (5399998516035621282) -->
- <skip />
- <!-- no translation found for alert_windows_notification_message (2456738662997073459) -->
- <skip />
- <!-- no translation found for alert_windows_notification_turn_off_action (3367294525884949878) -->
- <skip />
+ <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"I-<xliff:g id="NAME">%s</xliff:g> yokudweba ngaphezu kwezinye izinhlelo zokusebenza"</string>
+ <string name="alert_windows_notification_title" msgid="5399998516035621282">"Uhlelo lokusebenza lwe-<xliff:g id="NAME">%s</xliff:g> liboniswa ngaphezulu."</string>
+ <string name="alert_windows_notification_message" msgid="2456738662997073459">"Izingxenye zalolu hlelo lokusebenza zingahlala zibonakala ngazo zonke izikhathi. Uma lesi sici singasebenzi ngokufanelekile, sivale."</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"VALA"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Ilungiselela i-<xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Ihlolela amaphutha"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"I-<xliff:g id="NAME">%s</xliff:g> entsha itholiwe"</string>
@@ -1712,4 +1708,18 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Thayipha isikhathi"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Shintshela kumodi yokufaka umbhalo ngokufaka isikhathi."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Shintshela kumodi yewashi ngokufakwa kwesikhathi."</string>
+ <!-- no translation found for autofill_save_title (7081244500504163245) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (4977385733042555659) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 8031f19..be77603 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -66,6 +66,9 @@
<attr name="primaryContentAlpha" format="float" />
<!-- The alpha applied to the foreground color to create the secondary text color. -->
<attr name="secondaryContentAlpha" format="float" />
+ <!-- Color used for error states and things that need to be drawn to
+ the users attention.. -->
+ <attr name="colorError" format="reference|color" />
<!-- Default background dim amount when a menu, dialog, or something similar pops up. -->
<attr name="backgroundDimAmount" format="float" />
<!-- Control whether dimming behind the window is enabled. The default
@@ -135,9 +138,6 @@
<!-- Color of list item text in alert dialogs. -->
<attr name="textColorAlertDialogListItem" format="reference|color" />
- <!-- Text color for errors. -->
- <attr name="textColorError" format="reference|color" />
-
<!-- Search widget more corpus result item background. -->
<attr name="searchWidgetCorpusItemBackground" format="reference|color" />
@@ -4721,18 +4721,19 @@
</attr>
<!-- Specify the type of auto-size. Note that this feature is not supported by EditText,
works only for TextView -->
- <attr name="autoSizeText" format="enum">
+ <attr name="autoSizeTextType" format="enum">
<!-- No auto-sizing (default). -->
<enum name="none" value="0" />
- <!-- Uniform horizontal and vertical scaling. -->
+ <!-- Uniform horizontal and vertical text size scaling to fit within the
+ container -->
<enum name="uniform" value="1" />
</attr>
- <!-- Specify the auto-size step size if <code>autoSizeText</code> is set to
- <code>xy</code>. The default is 1px. Overwrites
+ <!-- Specify the auto-size step size if <code>autoSizeTextType</code> is set to
+ <code>uniform</code>. The default is 1px. Overwrites
<code>autoSizePresetSizes</code> if set. -->
<attr name="autoSizeStepGranularity" format="dimension" />
- <!-- Array of dimensions to be used in conjunction with
- <code>autoSizeText</code> set to <code>xy</code>. Overwrites
+ <!-- Resource array of dimensions to be used in conjunction with
+ <code>autoSizeTextType</code> set to <code>uniform</code>. Overrides
<code>autoSizeStepGranularity</code> if set. -->
<attr name="autoSizePresetSizes"/>
<!-- The minimum text size constraint to be used when auto-sizing text -->
@@ -8531,4 +8532,6 @@
<attr name="reverseLayout" format="boolean" />
<attr name="stackFromEnd" format="boolean" />
</declare-styleable>
+
+ <attr name="lockPatternStyle" format="reference" />
</resources>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index b28c6f2..6015ed5 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -75,8 +75,6 @@
<drawable name="input_method_fullscreen_background">#fff9f9f9</drawable>
<color name="input_method_navigation_guard">#ff000000</color>
- <color name="system_error">#fff4511e</color> <!-- deep orange 600 -->
-
<!-- For date picker widget -->
<drawable name="selected_day_background">#ff0092f4</drawable>
@@ -88,7 +86,6 @@
<color name="perms_dangerous_grp_color">#33b5e5</color>
<color name="perms_dangerous_perm_color">#33b5e5</color>
<color name="shadow">#cc222222</color>
- <color name="perms_costs_money">#fff4511e</color>
<!-- For search-related UIs -->
<color name="search_url_text_normal">#7fa87f</color>
@@ -121,7 +118,6 @@
<!-- LockPatternView -->
<color name="lock_pattern_view_regular_color">#ffffffff</color>
<color name="lock_pattern_view_success_color">#ffffffff</color>
- <color name="lock_pattern_view_error_color">@color/system_error</color>
<!-- FaceLock -->
<color name="facelock_spotlight_mask">#CC000000</color>
@@ -156,7 +152,6 @@
<color name="accessibility_focus_highlight">#bf39b500</color>
<color name="system_notification_accent_color">#ff607D8B</color>
- <color name="battery_saver_mode_color">#fff4511e</color><!-- deep orange 600 -->
<!-- Default user icon colors -->
<color name="user_icon_1">#ff00bcd4</color><!-- cyan 500 -->
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 0a24565..e0cc5b5 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -46,6 +46,7 @@
<color name="button_material_dark">#ff5a595b</color>
<color name="button_material_light">#ffd6d7d7</color>
+ <color name="error_color_material">#F4511E</color>
<color name="switch_thumb_normal_material_dark">#ffbdbdbd</color>
<color name="switch_thumb_normal_material_light">#fff1f1f1</color>
@@ -65,9 +66,6 @@
<!-- 70% white -->
<color name="secondary_text_default_material_dark">#b3ffffff</color>
- <color name="error_text_material_light">@color/material_red_A700</color>
- <color name="error_text_material_dark">@color/material_red_A100</color>
-
<item name="hint_alpha_material_dark" format="float" type="dimen">0.50</item>
<item name="hint_alpha_material_light" format="float" type="dimen">0.38</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d233e24..2843f46 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1273,19 +1273,6 @@
config_enableFusedLocationOverlay is false. -->
<string name="config_fusedLocationProviderPackageName" translatable="false">com.android.location.fused</string>
- <!-- A list of potential packages, in priority order, that may contain a
- network recommendation provider. A network recommendation provider must:
- * Be granted the SCORE_NETWORKS permission.
- * Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action
- protected by the BIND_NETWORK_RECOMMENDATION_SERVICE permission.
-
- This may be empty if network scoring and recommending isn't supported.
- -->
- <string-array name="config_networkRecommendationPackageNames" translatable="false">
- <!-- The standard AOSP network recommendation provider -->
- <item>com.android.networkrecommendation</item>
- </string-array>
-
<!-- The package name of the default network recommendation app.
A network recommendation provider must:
* Be granted the SCORE_NETWORKS permission.
@@ -2748,8 +2735,8 @@
<!-- Flag indicates that whether non-system apps can be installed on internal storage. -->
<bool name="config_allow3rdPartyAppOnInternal">true</bool>
- <!-- Component name of the default cell broadcast receiver -->
- <string name="config_defaultCellBroadcastReceiverComponent" translatable="false">com.android.cellbroadcastreceiver/.PrivilegedCellBroadcastReceiver</string>
+ <!-- Package name of the default cell broadcast receiver -->
+ <string name="config_defaultCellBroadcastReceiverPkg" translatable="false">com.android.cellbroadcastreceiver</string>
<!-- Specifies the path that is used by AdaptiveIconDrawable class to crop launcher icons. -->
<string name="config_icon_mask" translatable="false">"M50,0L100,0 100,100 0,100 0,0z"</string>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 78549b5..01737e7 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2765,7 +2765,7 @@
<public name="font" />
<public name="fontWeight" />
<public name="tooltipText" />
- <public name="autoSizeText" />
+ <public name="autoSizeTextType" />
<public name="autoSizeStepGranularity" />
<public name="autoSizePresetSizes" />
<public name="autoSizeMinTextSize" />
@@ -2780,7 +2780,7 @@
<public name="targetProcess" />
<public name="nextClusterForward" />
<public name="__removed1" />
- <public name="textColorError" />
+ <public name="colorError" />
<public name="focusedByDefault" />
<public name="appCategory" />
<public name="autoSizeMaxTextSize" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6abc009..b0c532c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4510,11 +4510,22 @@
<!-- Accessibility string used for describing the button in time picker that changes the dialog to circular clock mode. [CHAR LIMIT=NONE] -->
<string name="time_picker_radial_mode_description">Switch to clock mode for the time input.</string>
- <!-- Title for the auto-fill save dialog shown when the user entered savable text [CHAR LIMIT=NONE] -->
+ <!-- Title for the auto-fill save dialog shown when the the contents of the activity can be saved
+ by an auto-fill service, but the service does not know what the activity represents [CHAR LIMIT=NONE] -->
<string name="autofill_save_title">Save to <xliff:g id="label" example="MyPass">%1$s</xliff:g>?</string>
+ <!-- Title for the auto-fill save dialog shown when the the contents of the activity can be saved
+ by an auto-fill service, and the service does knows what the activity represents (for example, credit card info) [CHAR LIMIT=NONE] -->
+ <string name="autofill_save_title_with_type">Save <xliff:g id="type" example="Credit Card">%1$s</xliff:g> to <xliff:g id="label" example="MyPass">%2$s</xliff:g>?</string>
<!-- Label for the auto-fill save button [CHAR LIMIT=NONE] -->
<string name="autofill_save_yes">Save</string>
<!-- Label for the auto-fill cancel button [CHAR LIMIT=NONE] -->
<string name="autofill_save_no">No thanks</string>
+ <!-- Label for the type of data being saved for auto-fill when it represent user credentials with a password [CHAR LIMIT=NONE] -->
+ <string name="autofill_save_type_password">password</string>
+ <!-- Label for the type of data being saved for auto-fill when it represent an address (street, city, etc.) [CHAR LIMIT=NONE] -->
+ <string name="autofill_save_type_address">address</string>
+ <!-- Label for the type of data being saved for auto-fill when it represents a credit card [CHAR LIMIT=NONE] -->
+ <string name="autofill_save_type_credit_card">credit card</string>
+
</resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index faf451b..25873d2 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1475,4 +1475,10 @@
<item name="padding">16dp</item>
</style>
+ <style name="Widget.LockPatternView">
+ <item name="regularColor">@color/lock_pattern_view_regular_color</item>
+ <item name="errorColor">?attr/colorError</item>
+ <item name="successColor">@color/lock_pattern_view_success_color</item>
+ </style>
+
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e7d3ec9..15abf74 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1195,7 +1195,6 @@
<java-symbol type="drawable" name="btn_check_off" />
<java-symbol type="color" name="lock_pattern_view_regular_color" />
<java-symbol type="color" name="lock_pattern_view_success_color" />
- <java-symbol type="color" name="lock_pattern_view_error_color" />
<java-symbol type="dimen" name="lock_pattern_dot_line_width" />
<java-symbol type="dimen" name="lock_pattern_dot_size" />
<java-symbol type="dimen" name="lock_pattern_dot_size_activated" />
@@ -2310,7 +2309,6 @@
<java-symbol type="layout" name="select_dialog_singlechoice_material" />
<java-symbol type="layout" name="select_dialog_multichoice_material" />
<java-symbol type="array" name="no_ems_support_sim_operators" />
- <java-symbol type="color" name="battery_saver_mode_color" />
<java-symbol type="color" name="system_notification_accent_color" />
<java-symbol type="dimen" name="text_handle_min_size" />
<java-symbol type="id" name="transitionTransform" />
@@ -2787,7 +2785,6 @@
<java-symbol type="layout" name="notification_template_material_ambient" />
<!-- Network Recommendation -->
- <java-symbol type="array" name="config_networkRecommendationPackageNames" />
<java-symbol type="string" name="config_defaultNetworkRecommendationProviderPackage" />
<!-- Whether allow 3rd party apps on internal storage. -->
@@ -2798,7 +2795,7 @@
<java-symbol type="drawable" name="lockscreen_selected" />
<java-symbol type="string" name="notification_header_divider_symbol_with_spaces" />
- <java-symbol type="string" name="config_defaultCellBroadcastReceiverComponent" />
+ <java-symbol type="string" name="config_defaultCellBroadcastReceiverPkg" />
<java-symbol type="color" name="notification_primary_text_color_light" />
<java-symbol type="color" name="notification_primary_text_color_dark" />
@@ -2840,12 +2837,17 @@
<java-symbol type="layout" name="autofill_save"/>
<java-symbol type="layout" name="autofill_dataset_picker"/>
<java-symbol type="id" name="autofill_save_title" />
+ <java-symbol type="id" name="autofill_save_subtitle" />
<java-symbol type="id" name="autofill_save_no" />
<java-symbol type="id" name="autofill_save_yes" />
<java-symbol type="id" name="autofill_save_close" />
<java-symbol type="string" name="autofill_save_title" />
+ <java-symbol type="string" name="autofill_save_title_with_type" />
<java-symbol type="string" name="autofill_save_yes" />
<java-symbol type="string" name="autofill_save_no" />
+ <java-symbol type="string" name="autofill_save_type_password" />
+ <java-symbol type="string" name="autofill_save_type_address" />
+ <java-symbol type="string" name="autofill_save_type_credit_card" />
<!-- Accessibility fingerprint gestures -->
<java-symbol type="string" name="capability_title_canCaptureFingerprintGestures" />
@@ -2853,7 +2855,7 @@
<!-- android.service.trust -->
<java-symbol type="bool" name="config_allowEscrowTokenForTrustAgent"/>
-
+
<!-- Time picker -->
<java-symbol type="id" name="toggle_mode"/>
<java-symbol type="id" name="input_mode"/>
@@ -2880,6 +2882,8 @@
<java-symbol type="string" name="alert_windows_notification_message" />
<java-symbol type="string" name="alert_windows_notification_turn_off_action" />
<java-symbol type="drawable" name="alert_window_layer" />
+ <java-symbol type="style" name="Widget.LockPatternView" />
+ <java-symbol type="attr" name="lockPatternStyle" />
<!-- Colon separated list of package names that should be granted Notification Listener access -->
<java-symbol type="string" name="config_defaultListenerAccessPackages" />
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index e357678..d100c63 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -63,6 +63,7 @@
<item name="colorControlHighlight">@color/legacy_button_pressed</item>
<item name="colorButtonNormal">@color/legacy_button_normal</item>
<item name="colorEdgeEffect">?attr/colorPrimary</item>
+ <item name="colorError">@color/red</item>
<item name="disabledAlpha">0.5</item>
<item name="backgroundDimAmount">0.6</item>
@@ -93,7 +94,6 @@
<item name="textColorLink">@color/link_text_dark</item>
<item name="textColorLinkInverse">@color/link_text_light</item>
<item name="textColorAlertDialogListItem">@color/primary_text_light_disable_only</item>
- <item name="textColorError">@color/red</item>
<item name="textAppearanceLarge">@style/TextAppearance.Large</item>
<item name="textAppearanceMedium">@style/TextAppearance.Medium</item>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 400fb47..008c817 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -51,6 +51,7 @@
<item name="primaryContentAlpha">@dimen/primary_content_alpha_material_dark</item>
<item name="secondaryContentAlpha">@dimen/secondary_content_alpha_material_dark</item>
<item name="backgroundDimAmount">0.6</item>
+ <item name="colorError">@color/error_color_material</item>
<!-- Text styles -->
<item name="textAppearance">@style/TextAppearance.Material</item>
@@ -73,7 +74,6 @@
<item name="textColorLinkInverse">?attr/colorAccent</item>
<item name="textColorSearchUrl">@color/search_url_text_material_dark</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_dark</item>
- <item name="textColorError">@color/error_text_material_dark</item>
<item name="textAppearanceLarge">@style/TextAppearance.Material.Large</item>
<item name="textAppearanceLargeInverse">@style/TextAppearance.Material.Large.Inverse</item>
@@ -441,7 +441,6 @@
<item name="textColorLinkInverse">?attr/colorAccent</item>
<item name="textColorSearchUrl">@color/search_url_text_material_light</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_light</item>
- <item name="textColorError">@color/error_text_material_light</item>
<item name="textAppearanceLarge">@style/TextAppearance.Material.Large</item>
<item name="textAppearanceLargeInverse">@style/TextAppearance.Material.Large.Inverse</item>
@@ -823,7 +822,6 @@
<item name="textColorHighlightInverse">@color/highlighted_text_material</item>
<item name="textColorSearchUrl">@color/search_url_text_material_light</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_light</item>
- <item name="textColorError">@color/error_text_material_light</item>
<item name="textCheckMark">@drawable/indicator_check_mark_light</item>
<item name="textCheckMarkInverse">@drawable/indicator_check_mark_dark</item>
@@ -856,7 +854,6 @@
<item name="textColorHighlightInverse">@color/highlighted_text_material</item>
<item name="textColorSearchUrl">@color/search_url_text_material_dark</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_dark</item>
- <item name="textColorError">@color/error_text_material_dark</item>
<item name="textCheckMark">@drawable/indicator_check_mark_dark</item>
<item name="textCheckMarkInverse">@drawable/indicator_check_mark_light</item>
diff --git a/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java b/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java
index bdc0200..497bc5c 100644
--- a/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java
+++ b/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java
@@ -3,61 +3,62 @@
import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT;
import static android.net.NetworkRecommendationProvider.EXTRA_SEQUENCE;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.fail;
+import static junit.framework.TestCase.assertEquals;
+
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+
+import android.Manifest.permission;
import android.content.Context;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
import android.os.IRemoteCallback;
-import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* Unit test for the {@link NetworkRecommendationProvider}.
*/
-public class NetworkRecommendationProviderTest extends InstrumentationTestCase {
+@RunWith(AndroidJUnit4.class)
+public class NetworkRecommendationProviderTest {
@Mock private IRemoteCallback mMockRemoteCallback;
+ @Mock private Context mContext;
private NetworkRecProvider mRecProvider;
- private Handler mHandler;
private INetworkRecommendationProvider mStub;
private CountDownLatch mRecRequestLatch;
private CountDownLatch mScoreRequestLatch;
private NetworkKey[] mTestNetworkKeys;
- @Override
+ @Before
public void setUp() throws Exception {
- super.setUp();
-
- // Configuration needed to make mockito/dexcache work.
- final Context context = getInstrumentation().getTargetContext();
- System.setProperty("dexmaker.dexcache",
- context.getCacheDir().getPath());
- ClassLoader newClassLoader = getInstrumentation().getClass().getClassLoader();
- Thread.currentThread().setContextClassLoader(newClassLoader);
-
MockitoAnnotations.initMocks(this);
- HandlerThread thread = new HandlerThread("NetworkRecommendationProviderTest");
- thread.start();
+ Executor executor = Executors.newSingleThreadExecutor();
mRecRequestLatch = new CountDownLatch(1);
mScoreRequestLatch = new CountDownLatch(1);
- mHandler = new Handler(thread.getLooper());
- mRecProvider = new NetworkRecProvider(mHandler, mRecRequestLatch, mScoreRequestLatch);
+ mRecProvider = new NetworkRecProvider(mContext, executor, mRecRequestLatch,
+ mScoreRequestLatch);
mStub = INetworkRecommendationProvider.Stub.asInterface(mRecProvider.getBinder());
mTestNetworkKeys = new NetworkKey[2];
mTestNetworkKeys[0] = new NetworkKey(new WifiKey("\"ssid_01\"", "00:00:00:00:00:11"));
mTestNetworkKeys[1] = new NetworkKey(new WifiKey("\"ssid_02\"", "00:00:00:00:00:22"));
}
- @MediumTest
+ @Test
public void testRecommendationRequestReceived() throws Exception {
final RecommendationRequest request = new RecommendationRequest.Builder().build();
final int sequence = 100;
@@ -71,7 +72,23 @@
assertEquals(expectedResultCallback, mRecProvider.mCapturedCallback);
}
- @SmallTest
+ @Test
+ public void testRecommendationRequest_permissionsEnforced() throws Exception {
+ final RecommendationRequest request = new RecommendationRequest.Builder().build();
+ final int sequence = 100;
+ Mockito.doThrow(new SecurityException())
+ .when(mContext)
+ .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString());
+
+ try {
+ mStub.requestRecommendation(request, mMockRemoteCallback, sequence);
+ fail("SecurityException expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
public void testResultCallbackOnResult() throws Exception {
final int sequence = 100;
final NetworkRecommendationProvider.ResultCallback callback =
@@ -87,7 +104,7 @@
assertSame(result, capturedBundle.getParcelable(EXTRA_RECOMMENDATION_RESULT));
}
- @SmallTest
+ @Test
public void testResultCallbackOnResult_runTwice_throwsException() throws Exception {
final int sequence = 100;
final NetworkRecommendationProvider.ResultCallback callback =
@@ -104,7 +121,7 @@
}
}
- @MediumTest
+ @Test
public void testScoreRequestReceived() throws Exception {
mStub.requestScores(mTestNetworkKeys);
@@ -114,7 +131,7 @@
assertSame(mTestNetworkKeys, mRecProvider.mCapturedNetworks);
}
- @MediumTest
+ @Test
public void testScoreRequest_nullInput() throws Exception {
mStub.requestScores(null);
@@ -122,7 +139,7 @@
assertFalse(mScoreRequestLatch.await(200, TimeUnit.MILLISECONDS));
}
- @MediumTest
+ @Test
public void testScoreRequest_emptyInput() throws Exception {
mStub.requestScores(new NetworkKey[0]);
@@ -130,6 +147,20 @@
assertFalse(mScoreRequestLatch.await(200, TimeUnit.MILLISECONDS));
}
+ @Test
+ public void testScoreRequest_permissionsEnforced() throws Exception {
+ Mockito.doThrow(new SecurityException())
+ .when(mContext)
+ .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString());
+
+ try {
+ mStub.requestScores(mTestNetworkKeys);
+ fail("SecurityException expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
private static class NetworkRecProvider extends NetworkRecommendationProvider {
private final CountDownLatch mRecRequestLatch;
private final CountDownLatch mScoreRequestLatch;
@@ -137,9 +168,9 @@
ResultCallback mCapturedCallback;
NetworkKey[] mCapturedNetworks;
- NetworkRecProvider(Handler handler, CountDownLatch recRequestLatch,
+ NetworkRecProvider(Context context, Executor executor, CountDownLatch recRequestLatch,
CountDownLatch networkRequestLatch) {
- super(handler);
+ super(context, executor);
mRecRequestLatch = recRequestLatch;
mScoreRequestLatch = networkRequestLatch;
}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index da6a294..105a351 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -281,6 +281,7 @@
Settings.Global.RADIO_NFC,
Settings.Global.RADIO_WIFI,
Settings.Global.RADIO_WIMAX,
+ Settings.Global.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS,
Settings.Global.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT,
Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT,
Settings.Global.RETAIL_DEMO_MODE_CONSTANTS,
@@ -393,6 +394,7 @@
Settings.Secure.BACKUP_TRANSPORT,
Settings.Secure.BLUETOOTH_HCI_LOG,
Settings.Secure.CARRIER_APPS_HANDLED,
+ Settings.Secure.CMAS_ADDITIONAL_BROADCAST_PKG,
Settings.Secure.COMPLETED_CATEGORY_PREFIX,
Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS,
Settings.Secure.DEFAULT_INPUT_METHOD,
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 1080a9f..3dfecc6 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -16,6 +16,17 @@
package com.android.internal.app;
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.LauncherApps;
+import android.content.pm.PackageManager;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.graphics.drawable.Icon;
+import android.os.SystemClock;
import com.android.internal.R;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
@@ -48,25 +59,31 @@
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.isA;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
/**
* Chooser activity instrumentation tests
*/
@RunWith(AndroidJUnit4.class)
public class ChooserActivityTest {
+ private Instrumentation instrumentation;
+
+ @Before
+ public void setUp() {
+ instrumentation = InstrumentationRegistry.getInstrumentation();
+ sOverrides.reset();
+ }
+
@Rule
public ActivityTestRule<ChooserWrapperActivity> mActivityRule =
new ActivityTestRule<>(ChooserWrapperActivity.class, false,
false);
- @Before
- public void cleanOverrideData() {
- sOverrides.reset();
- }
-
@Test
public void customTitle() throws InterruptedException {
Intent sendIntent = createSendImageIntent();
@@ -235,7 +252,6 @@
chosen[0] = targetInfo.getResolveInfo();
return true;
};
-
// Make a stable copy of the components as the original list may be modified
List<ResolvedComponentInfo> stableCopy =
createResolvedComponentsForTestWithOtherProfile(2);
@@ -324,6 +340,32 @@
assertThat(chosen[0], is(toChoose));
}
+ public void pushedChooserTarget() {
+ ResolveInfo[] chosen = new ResolveInfo[1];
+ sOverrides.onSafelyStartCallback = targetInfo -> {
+ chosen[0] = targetInfo.getResolveInfo();
+ return true;
+ };
+
+ setChooserShortcuts(1);
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+ Intent sendIntent = createSendImageIntent();
+ final ChooserWrapperActivity activity = mActivityRule
+ .launchActivity(Intent.createChooser(sendIntent, null));
+
+ waitForIdle();
+
+ onView(withText("short chooser label 0"))
+ .perform(click());
+ waitForIdle();
+ assertThat(chosen[0].resolvePackageName,
+ is(ResolverDataProvider.createActivityInfo(0).packageName));
+ }
+
private Intent createSendImageIntent() {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
@@ -371,4 +413,48 @@
}
return packageStats.mChooserCounts.get(action).getOrDefault(annotation, 0);
}
+
+ private void setChooserShortcuts(int numShortcuts) {
+ ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
+ for (int i = 0; i < numShortcuts; i++) {
+ shortcuts.add(makeShortcut(i));
+ }
+ when(sOverrides.launcherApps.getShortcuts(
+ Mockito.isA(LauncherApps.ShortcutQuery.class),
+ Mockito.eq(UserHandle.SYSTEM)))
+ .thenReturn(shortcuts);
+ }
+
+ private ShortcutInfo makeShortcut(int i) {
+ try {
+ IntentFilter filter = new IntentFilter(Intent.ACTION_SEND, "image/jpeg");
+
+ ComponentName component = new ComponentName("foo.bar", "foo.bar" + ".MainActivity");
+ ShortcutInfo.Builder b = new ShortcutInfo.Builder(instrumentation.getContext(), "" + i)
+ .setActivity(component)
+ .setShortLabel("short chooser label " + i)
+ .setLongLabel("long chooser label" + i)
+ .setRank(i)
+ .setIntent(createSendImageIntent())
+ .setIcon(Icon.createWithResource(instrumentation.getContext(),
+ android.R.drawable.ic_menu_add))
+ .addChooserIntentFilter(
+ filter,
+ component);
+
+ sOverrides.createPackageManager = pm -> {
+ final PackageManager spied = spy(pm);
+ try {
+ doAnswer(invocation -> ResolverDataProvider.createActivityInfo(i))
+ .when(spied).getActivityInfo(
+ Mockito.isA(ComponentName.class), Mockito.anyInt());
+ } catch (Exception e) {
+ // this is ok, just not found
+ e.printStackTrace();
+ }
+ return spied;
+ };
+ return b.build();
+ } catch (Exception e) {return null;}
+ }
}
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index c446f3c..0dac260 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -18,6 +18,7 @@
import android.app.usage.UsageStatsManager;
import android.content.Context;
+import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import java.util.function.Function;
@@ -74,6 +75,11 @@
return super.getPackageManager();
}
+ @Override
+ public LauncherApps getLauncherApps() {
+ return sOverrides.launcherApps;
+ }
+
/**
* We cannot directly mock the activity created since instrumentation creates it.
* <p>
@@ -82,6 +88,7 @@
static class OverrideData {
@SuppressWarnings("Since15")
public Function<PackageManager, PackageManager> createPackageManager;
+ public LauncherApps launcherApps;
public Function<TargetInfo, Boolean> onSafelyStartCallback;
public ResolverListController resolverListController;
public Boolean isVoiceInteraction;
@@ -90,6 +97,7 @@
onSafelyStartCallback = null;
isVoiceInteraction = null;
createPackageManager = null;
+ launcherApps = mock(LauncherApps.class);
resolverListController = mock(ResolverListController.class);
}
}
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index d8e6db7..76598a0 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -1,8 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- All fonts without names are added to the default list. Fonts are chosen
- based on a match: full BCP-47 language tag including script, then just
- language, and finally order (the first font containing the glyph).
+ WARNING: Parsing of this file by third-party apps is not supported. The
+ file, and the font files it refers to, will be renamed and/or moved out
+ from their respective location in the next Android release, and/or the
+ format or syntax of the file may change significantly. You must not
+ parse this file for information about system fonts. Instead, you must
+ call android.text.FontManager#getSystemFonts(). For example, it can be
+ called as context.getSystemService(FontManager.class).getSystemFonts().
+ Note that the returned FontConfig includes data on all the defined font
+ families and all the details about weight, style, etc. It also provides
+ an open file descriptor to each font file. Note that callers of the API
+ should ensure they close the given file descriptors once they are done
+ using them.
+
+ In this file, all fonts without names are added to the default list.
+ Fonts are chosen based on a match: full BCP-47 language tag including
+ script, then just language, and finally order (the first font containing
+ the glyph).
Order of appearance is also the tiebreaker for weight matching. This is
the reason why the 900 weights of Roboto precede the 700 weights - we
diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java
index ff21cac..33d19d4 100644
--- a/graphics/java/android/graphics/Color.java
+++ b/graphics/java/android/graphics/Color.java
@@ -1023,9 +1023,9 @@
"The color space must use a color model with at most 3 components");
}
- @HalfFloat short r = Half.valueOf(red);
- @HalfFloat short g = Half.valueOf(green);
- @HalfFloat short b = Half.valueOf(blue);
+ @HalfFloat short r = Half.toHalf(red);
+ @HalfFloat short g = Half.toHalf(green);
+ @HalfFloat short b = Half.toHalf(blue);
int a = (int) (Math.max(0.0f, Math.min(alpha, 1.0f)) * 1023.0f + 0.5f);
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index ec00c45..b1a433c 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -805,7 +805,8 @@
*/
public enum Adaptation {
/**
- * Bradford matrix for the von Kries chromatic adaptation transform.
+ * Bradford chromatic adaptation transform, as defined in the
+ * CIECAM97s color appearance model.
*/
BRADFORD(new float[] {
0.8951f, -0.7502f, 0.0389f,
@@ -813,12 +814,21 @@
-0.1614f, 0.0367f, 1.0296f
}),
/**
- * von Kries matrix for the von Kries chromatic adaptation transform.
+ * von Kries chromatic adaptation transform.
*/
VON_KRIES(new float[] {
0.40024f, -0.22630f, 0.00000f,
0.70760f, 1.16532f, 0.00000f,
-0.08081f, 0.04570f, 0.91822f
+ }),
+ /**
+ * CIECAT02 chromatic adaption transform, as defined in the
+ * CIECAM02 color appearance model.
+ */
+ CIECAT02(new float[] {
+ 0.7328f, -0.7036f, 0.0030f,
+ 0.4296f, 1.6975f, 0.0136f,
+ -0.1624f, 0.0061f, 0.9834f
});
final float[] mTransform;
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index fe82a93..a24b970 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -16,9 +16,11 @@
package android.graphics.drawable;
+import android.annotation.NonNull;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
+import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
@@ -31,10 +33,10 @@
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.shapes.Shape;
-import android.content.res.Resources.Theme;
import android.util.AttributeSet;
import com.android.internal.R;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -69,7 +71,7 @@
* @attr ref android.R.styleable#ShapeDrawable_height
*/
public class ShapeDrawable extends Drawable {
- private ShapeState mShapeState;
+ private @NonNull ShapeState mShapeState;
private PorterDuffColorFilter mTintFilter;
private boolean mMutated;
@@ -77,7 +79,7 @@
* ShapeDrawable constructor.
*/
public ShapeDrawable() {
- this(new ShapeState(null), null);
+ this(new ShapeState(), null);
}
/**
@@ -86,7 +88,7 @@
* @param s the Shape that this ShapeDrawable should be
*/
public ShapeDrawable(Shape s) {
- this(new ShapeState(null), null);
+ this(new ShapeState(), null);
mShapeState.mShape = s;
}
@@ -402,7 +404,7 @@
}
// Update local properties.
- updateLocalState(r);
+ updateLocalState();
}
@Override
@@ -426,7 +428,7 @@
}
// Update local properties.
- updateLocalState(t.getResources());
+ updateLocalState();
}
private void updateStateFromTypedArray(TypedArray a) {
@@ -447,10 +449,10 @@
dither = a.getBoolean(R.styleable.ShapeDrawable_dither, dither);
paint.setDither(dither);
- setIntrinsicWidth((int) a.getDimension(
- R.styleable.ShapeDrawable_width, state.mIntrinsicWidth));
- setIntrinsicHeight((int) a.getDimension(
- R.styleable.ShapeDrawable_height, state.mIntrinsicHeight));
+ state.mIntrinsicWidth = (int) a.getDimension(
+ R.styleable.ShapeDrawable_width, state.mIntrinsicWidth);
+ state.mIntrinsicHeight = (int) a.getDimension(
+ R.styleable.ShapeDrawable_height, state.mIntrinsicHeight);
final int tintMode = a.getInt(R.styleable.ShapeDrawable_tintMode, -1);
if (tintMode != -1) {
@@ -494,21 +496,8 @@
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
- if (mShapeState.mPaint != null) {
- mShapeState.mPaint = new Paint(mShapeState.mPaint);
- } else {
- mShapeState.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- }
- if (mShapeState.mPadding != null) {
- mShapeState.mPadding = new Rect(mShapeState.mPadding);
- } else {
- mShapeState.mPadding = new Rect();
- }
- try {
- mShapeState.mShape = mShapeState.mShape.clone();
- } catch (CloneNotSupportedException e) {
- return null;
- }
+ mShapeState = new ShapeState(mShapeState);
+ updateLocalState();
mMutated = true;
}
return this;
@@ -525,12 +514,13 @@
/**
* Defines the intrinsic properties of this ShapeDrawable's Shape.
*/
- final static class ShapeState extends ConstantState {
- int[] mThemeAttrs;
+ static final class ShapeState extends ConstantState {
+ final @NonNull Paint mPaint;
+
@Config int mChangingConfigurations;
- Paint mPaint;
+ int[] mThemeAttrs;
Shape mShape;
- ColorStateList mTint = null;
+ ColorStateList mTint;
Mode mTintMode = DEFAULT_TINT_MODE;
Rect mPadding;
int mIntrinsicWidth;
@@ -538,21 +528,43 @@
int mAlpha = 255;
ShaderFactory mShaderFactory;
- ShapeState(ShapeState orig) {
- if (orig != null) {
- mThemeAttrs = orig.mThemeAttrs;
- mPaint = orig.mPaint;
- mShape = orig.mShape;
- mTint = orig.mTint;
- mTintMode = orig.mTintMode;
- mPadding = orig.mPadding;
- mIntrinsicWidth = orig.mIntrinsicWidth;
- mIntrinsicHeight = orig.mIntrinsicHeight;
- mAlpha = orig.mAlpha;
- mShaderFactory = orig.mShaderFactory;
- } else {
- mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ /**
+ * Constructs a new ShapeState.
+ */
+ ShapeState() {
+ mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ }
+
+ /**
+ * Constructs a new ShapeState that contains a deep copy of the
+ * specified ShapeState.
+ *
+ * @param orig the state to create a deep copy of
+ */
+ ShapeState(@NonNull ShapeState orig) {
+ mChangingConfigurations = orig.mChangingConfigurations;
+ mPaint = new Paint(orig.mPaint);
+ mThemeAttrs = orig.mThemeAttrs;
+ if (mShape != null) {
+ try {
+ mShape = orig.mShape.clone();
+ } catch (CloneNotSupportedException e) {
+ // Well, at least we tried.
+ mShape = orig.mShape;
+ }
}
+ mTint = orig.mTint;
+ mTintMode = orig.mTintMode;
+ if (orig.mPadding != null) {
+ mPadding = new Rect(orig.mPadding);
+ }
+ mIntrinsicWidth = orig.mIntrinsicWidth;
+ mIntrinsicHeight = orig.mIntrinsicHeight;
+ mAlpha = orig.mAlpha;
+
+ // We don't have any way to clone a shader factory, so hopefully
+ // this class doesn't contain any local state.
+ mShaderFactory = orig.mShaderFactory;
}
@Override
@@ -585,7 +597,7 @@
private ShapeDrawable(ShapeState state, Resources res) {
mShapeState = state;
- updateLocalState(res);
+ updateLocalState();
}
/**
@@ -593,7 +605,7 @@
* after significant state changes, e.g. from the One True Constructor and
* after inflating or applying a theme.
*/
- private void updateLocalState(Resources res) {
+ private void updateLocalState() {
mTintFilter = updateTintFilter(mTintFilter, mShapeState.mTint, mShapeState.mTintMode);
}
@@ -617,8 +629,4 @@
*/
public abstract Shader resize(int width, int height);
}
-
- // other subclass could wack the Shader's localmatrix based on the
- // resize params (e.g. scaletofit, etc.). This could be used to scale
- // a bitmap to fill the bounds without needing any other special casing.
}
diff --git a/graphics/java/android/graphics/drawable/shapes/ArcShape.java b/graphics/java/android/graphics/drawable/shapes/ArcShape.java
index c4b239f..85ba0a9 100644
--- a/graphics/java/android/graphics/drawable/shapes/ArcShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/ArcShape.java
@@ -21,31 +21,47 @@
import android.graphics.Paint;
/**
- * Creates an arc shape. The arc shape starts at a specified
- * angle and sweeps clockwise, drawing slices of pie.
- * The arc can be drawn to a Canvas with its own draw() method,
- * but more graphical control is available if you instead pass
- * the ArcShape to a {@link android.graphics.drawable.ShapeDrawable}.
+ * Creates an arc shape. The arc shape starts at a specified angle and sweeps
+ * clockwise, drawing slices of pie.
+ * <p>
+ * The arc can be drawn to a {@link Canvas} with its own
+ * {@link #draw(Canvas, Paint)} method, but more graphical control is available
+ * if you instead pass the ArcShape to a
+ * {@link android.graphics.drawable.ShapeDrawable}.
*/
public class ArcShape extends RectShape {
- private float mStart;
- private float mSweep;
-
+ private final float mStartAngle;
+ private final float mSweepAngle;
+
/**
- * ArcShape constructor.
- *
+ * ArcShape constructor.
+ *
* @param startAngle the angle (in degrees) where the arc begins
- * @param sweepAngle the sweep angle (in degrees). Anything equal to or
+ * @param sweepAngle the sweep angle (in degrees). Anything equal to or
* greater than 360 results in a complete circle/oval.
*/
public ArcShape(float startAngle, float sweepAngle) {
- mStart = startAngle;
- mSweep = sweepAngle;
+ mStartAngle = startAngle;
+ mSweepAngle = sweepAngle;
}
-
+
+ /**
+ * @return the angle (in degrees) where the arc begins
+ */
+ public final float getStartAngle() {
+ return mStartAngle;
+ }
+
+ /**
+ * @return the sweep angle (in degrees)
+ */
+ public final float getSweepAngle() {
+ return mSweepAngle;
+ }
+
@Override
public void draw(Canvas canvas, Paint paint) {
- canvas.drawArc(rect(), mStart, mSweep, true, paint);
+ canvas.drawArc(rect(), mStartAngle, mSweepAngle, true, paint);
}
@Override
@@ -53,5 +69,10 @@
// Since we don't support concave outlines, arc shape does not attempt
// to provide an outline.
}
+
+ @Override
+ public ArcShape clone() throws CloneNotSupportedException {
+ return (ArcShape) super.clone();
+ }
}
diff --git a/graphics/java/android/graphics/drawable/shapes/OvalShape.java b/graphics/java/android/graphics/drawable/shapes/OvalShape.java
index c9473f0..fb87d28 100644
--- a/graphics/java/android/graphics/drawable/shapes/OvalShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/OvalShape.java
@@ -22,7 +22,8 @@
import android.graphics.RectF;
/**
- * Defines an oval shape.
+ * Defines an oval shape.
+ * <p>
* The oval can be drawn to a Canvas with its own draw() method,
* but more graphical control is available if you instead pass
* the OvalShape to a {@link android.graphics.drawable.ShapeDrawable}.
@@ -42,5 +43,10 @@
outline.setOval((int) Math.ceil(rect.left), (int) Math.ceil(rect.top),
(int) Math.floor(rect.right), (int) Math.floor(rect.bottom));
}
+
+ @Override
+ public OvalShape clone() throws CloneNotSupportedException {
+ return (OvalShape) super.clone();
+ }
}
diff --git a/graphics/java/android/graphics/drawable/shapes/PathShape.java b/graphics/java/android/graphics/drawable/shapes/PathShape.java
index 30b7347..ce5552b 100644
--- a/graphics/java/android/graphics/drawable/shapes/PathShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/PathShape.java
@@ -16,41 +16,44 @@
package android.graphics.drawable.shapes;
+import android.annotation.NonNull;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
/**
* Creates geometric paths, utilizing the {@link android.graphics.Path} class.
+ * <p>
* The path can be drawn to a Canvas with its own draw() method,
* but more graphical control is available if you instead pass
* the PathShape to a {@link android.graphics.drawable.ShapeDrawable}.
*/
public class PathShape extends Shape {
- private Path mPath;
- private float mStdWidth;
- private float mStdHeight;
-
- private float mScaleX; // cached from onResize
- private float mScaleY; // cached from onResize
-
+ private final float mStdWidth;
+ private final float mStdHeight;
+
+ private Path mPath;
+
+ private float mScaleX; // cached from onResize
+ private float mScaleY; // cached from onResize
+
/**
* PathShape constructor.
- *
- * @param path a Path that defines the geometric paths for this shape
- * @param stdWidth the standard width for the shape. Any changes to the
- * width with resize() will result in a width scaled based
- * on the new width divided by this width.
- * @param stdHeight the standard height for the shape. Any changes to the
- * height with resize() will result in a height scaled based
- * on the new height divided by this height.
+ *
+ * @param path a Path that defines the geometric paths for this shape
+ * @param stdWidth the standard width for the shape. Any changes to the
+ * width with resize() will result in a width scaled based
+ * on the new width divided by this width.
+ * @param stdHeight the standard height for the shape. Any changes to the
+ * height with resize() will result in a height scaled based
+ * on the new height divided by this height.
*/
- public PathShape(Path path, float stdWidth, float stdHeight) {
+ public PathShape(@NonNull Path path, float stdWidth, float stdHeight) {
mPath = path;
mStdWidth = stdWidth;
mStdHeight = stdHeight;
}
-
+
@Override
public void draw(Canvas canvas, Paint paint) {
canvas.save();
@@ -58,7 +61,7 @@
canvas.drawPath(mPath, paint);
canvas.restore();
}
-
+
@Override
protected void onResize(float width, float height) {
mScaleX = width / mStdWidth;
@@ -67,7 +70,7 @@
@Override
public PathShape clone() throws CloneNotSupportedException {
- PathShape shape = (PathShape) super.clone();
+ final PathShape shape = (PathShape) super.clone();
shape.mPath = new Path(mPath);
return shape;
}
diff --git a/graphics/java/android/graphics/drawable/shapes/RectShape.java b/graphics/java/android/graphics/drawable/shapes/RectShape.java
index 04cf293..e339a21 100644
--- a/graphics/java/android/graphics/drawable/shapes/RectShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/RectShape.java
@@ -23,6 +23,7 @@
/**
* Defines a rectangle shape.
+ * <p>
* The rectangle can be drawn to a Canvas with its own draw() method,
* but more graphical control is available if you instead pass
* the RectShape to a {@link android.graphics.drawable.ShapeDrawable}.
diff --git a/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java b/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java
index e5253b8..f5cbb24 100644
--- a/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java
@@ -16,6 +16,7 @@
package android.graphics.drawable.shapes;
+import android.annotation.Nullable;
import android.graphics.Canvas;
import android.graphics.Outline;
import android.graphics.Paint;
@@ -24,40 +25,41 @@
/**
* Creates a rounded-corner rectangle. Optionally, an inset (rounded) rectangle
- * can be included (to make a sort of "O" shape).
+ * can be included (to make a sort of "O" shape).
+ * <p>
* The rounded rectangle can be drawn to a Canvas with its own draw() method,
* but more graphical control is available if you instead pass
* the RoundRectShape to a {@link android.graphics.drawable.ShapeDrawable}.
*/
public class RoundRectShape extends RectShape {
private float[] mOuterRadii;
- private RectF mInset;
+ private RectF mInset;
private float[] mInnerRadii;
private RectF mInnerRect;
- private Path mPath; // this is what we actually draw
+ private Path mPath; // this is what we actually draw
/**
* RoundRectShape constructor.
+ * <p>
* Specifies an outer (round)rect and an optional inner (round)rect.
*
* @param outerRadii An array of 8 radius values, for the outer roundrect.
- * The first two floats are for the
- * top-left corner (remaining pairs correspond clockwise).
- * For no rounded corners on the outer rectangle,
- * pass null.
- * @param inset A RectF that specifies the distance from the inner
- * rect to each side of the outer rect.
- * For no inner, pass null.
+ * The first two floats are for the top-left corner
+ * (remaining pairs correspond clockwise). For no rounded
+ * corners on the outer rectangle, pass {@code null}.
+ * @param inset A RectF that specifies the distance from the inner
+ * rect to each side of the outer rect. For no inner, pass
+ * {@code null}.
* @param innerRadii An array of 8 radius values, for the inner roundrect.
- * The first two floats are for the
- * top-left corner (remaining pairs correspond clockwise).
- * For no rounded corners on the inner rectangle,
- * pass null.
- * If inset parameter is null, this parameter is ignored.
+ * The first two floats are for the top-left corner
+ * (remaining pairs correspond clockwise). For no rounded
+ * corners on the inner rectangle, pass {@code null}. If
+ * inset parameter is {@code null}, this parameter is
+ * ignored.
*/
- public RoundRectShape(float[] outerRadii, RectF inset,
- float[] innerRadii) {
+ public RoundRectShape(@Nullable float[] outerRadii, @Nullable RectF inset,
+ @Nullable float[] innerRadii) {
if (outerRadii != null && outerRadii.length < 8) {
throw new ArrayIndexOutOfBoundsException("outer radii must have >= 8 values");
}
@@ -97,8 +99,7 @@
final RectF rect = rect();
outline.setRoundRect((int) Math.ceil(rect.left), (int) Math.ceil(rect.top),
- (int) Math.floor(rect.right), (int) Math.floor(rect.bottom),
- radius);
+ (int) Math.floor(rect.right), (int) Math.floor(rect.bottom), radius);
}
@Override
@@ -128,7 +129,7 @@
@Override
public RoundRectShape clone() throws CloneNotSupportedException {
- RoundRectShape shape = (RoundRectShape) super.clone();
+ final RoundRectShape shape = (RoundRectShape) super.clone();
shape.mOuterRadii = mOuterRadii != null ? mOuterRadii.clone() : null;
shape.mInnerRadii = mInnerRadii != null ? mInnerRadii.clone() : null;
shape.mInset = new RectF(mInset);
diff --git a/graphics/java/android/graphics/drawable/shapes/Shape.java b/graphics/java/android/graphics/drawable/shapes/Shape.java
index eab8666..30b28f3 100644
--- a/graphics/java/android/graphics/drawable/shapes/Shape.java
+++ b/graphics/java/android/graphics/drawable/shapes/Shape.java
@@ -23,21 +23,25 @@
/**
* Defines a generic graphical "shape."
- * Any Shape can be drawn to a Canvas with its own draw() method,
- * but more graphical control is available if you instead pass
- * it to a {@link android.graphics.drawable.ShapeDrawable}.
+ * <p>
+ * Any Shape can be drawn to a Canvas with its own draw() method, but more
+ * graphical control is available if you instead pass it to a
+ * {@link android.graphics.drawable.ShapeDrawable}.
+ * <p>
+ * Custom Shape classes must implement {@link #clone()} and return an instance
+ * of the custom Shape class.
*/
public abstract class Shape implements Cloneable {
private float mWidth;
private float mHeight;
-
+
/**
* Returns the width of the Shape.
*/
public final float getWidth() {
return mWidth;
}
-
+
/**
* Returns the height of the Shape.
*/
@@ -46,9 +50,10 @@
}
/**
- * Draw this shape into the provided Canvas, with the provided Paint.
+ * Draws this shape into the provided Canvas, with the provided Paint.
+ * <p>
* Before calling this, you must call {@link #resize(float,float)}.
- *
+ *
* @param canvas the Canvas within which this shape should be drawn
* @param paint the Paint object that defines this shape's characteristics
*/
@@ -56,8 +61,9 @@
/**
* Resizes the dimensions of this shape.
+ * <p>
* Must be called before {@link #draw(Canvas,Paint)}.
- *
+ *
* @param width the width of the shape (in pixels)
* @param height the height of the shape (in pixels)
*/
@@ -74,30 +80,34 @@
onResize(width, height);
}
}
-
+
/**
* Checks whether the Shape is opaque.
- * Default impl returns true. Override if your subclass can be opaque.
- *
- * @return true if any part of the drawable is <em>not</em> opaque.
+ * <p>
+ * Default impl returns {@code true}. Override if your subclass can be
+ * opaque.
+ *
+ * @return true if any part of the drawable is <em>not</em> opaque.
*/
public boolean hasAlpha() {
return true;
}
-
+
/**
* Callback method called when {@link #resize(float,float)} is executed.
- *
+ *
* @param width the new width of the Shape
* @param height the new height of the Shape
*/
protected void onResize(float width, float height) {}
/**
- * Compute the Outline of the shape and return it in the supplied Outline
- * parameter. The default implementation does nothing and {@code outline} is not changed.
+ * Computes the Outline of the shape and return it in the supplied Outline
+ * parameter. The default implementation does nothing and {@code outline}
+ * is not changed.
*
- * @param outline The Outline to be populated with the result. Should not be null.
+ * @param outline the Outline to be populated with the result. Must be
+ * non-{@code null}.
*/
public void getOutline(@NonNull Outline outline) {}
@@ -105,5 +115,4 @@
public Shape clone() throws CloneNotSupportedException {
return (Shape) super.clone();
}
-
}
diff --git a/keystore/java/android/security/IKeyChainAliasCallback.aidl b/keystore/java/android/security/IKeyChainAliasCallback.aidl
index 1ea9521..b9d3753 100644
--- a/keystore/java/android/security/IKeyChainAliasCallback.aidl
+++ b/keystore/java/android/security/IKeyChainAliasCallback.aidl
@@ -20,7 +20,7 @@
*
* @hide
*/
-interface IKeyChainAliasCallback {
+oneway interface IKeyChainAliasCallback {
void alias(String alias);
}
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index c365b5d..c64a89d 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -153,8 +153,8 @@
// minikin may modify the original paint
Paint paint(origPaint);
- minikin::Layout layout;
- MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, start, count, contextCount);
+ minikin::Layout layout = MinikinUtils::doLayout(
+ &paint, bidiFlags, typeface, text, start, count, contextCount);
size_t nGlyphs = layout.nGlyphs();
std::unique_ptr<uint16_t[]> glyphs(new uint16_t[nGlyphs]);
@@ -205,8 +205,8 @@
void Canvas::drawTextOnPath(const uint16_t* text, int count, int bidiFlags, const SkPath& path,
float hOffset, float vOffset, const Paint& paint, Typeface* typeface) {
Paint paintCopy(paint);
- minikin::Layout layout;
- MinikinUtils::doLayout(&layout, &paintCopy, bidiFlags, typeface, text, 0, count, count);
+ minikin::Layout layout = MinikinUtils::doLayout(
+ &paintCopy, bidiFlags, typeface, text, 0, count, count);
hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
// Set align to left for drawing, as we don't want individual
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index cbae0a0..ba4e3a4 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -91,7 +91,7 @@
return mAxes;
}
-minikin::MinikinFont* MinikinFontSkia::createFontWithVariation(
+std::shared_ptr<minikin::MinikinFont> MinikinFontSkia::createFontWithVariation(
const std::vector<minikin::FontVariation>& variations) const {
SkFontMgr::FontParameters params;
@@ -110,7 +110,8 @@
sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
sk_sp<SkTypeface> face(fm->createFromStream(stream, params));
- return new MinikinFontSkia(std::move(face), mFontData, mFontSize, ttcIndex, variations);
+ return std::make_shared<MinikinFontSkia>(std::move(face), mFontData, mFontSize, ttcIndex,
+ variations);
}
uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
diff --git a/libs/hwui/hwui/MinikinSkia.h b/libs/hwui/hwui/MinikinSkia.h
index db59fe5..6c12485 100644
--- a/libs/hwui/hwui/MinikinSkia.h
+++ b/libs/hwui/hwui/MinikinSkia.h
@@ -45,7 +45,7 @@
size_t GetFontSize() const;
int GetFontIndex() const;
const std::vector<minikin::FontVariation>& GetAxes() const;
- minikin::MinikinFont* createFontWithVariation(
+ std::shared_ptr<minikin::MinikinFont> createFontWithVariation(
const std::vector<minikin::FontVariation>&) const;
static uint32_t packPaintFlags(const SkPaint* paint);
diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp
index 713e509..d1871ff 100644
--- a/libs/hwui/hwui/MinikinUtils.cpp
+++ b/libs/hwui/hwui/MinikinUtils.cpp
@@ -27,9 +27,8 @@
namespace android {
minikin::FontStyle MinikinUtils::prepareMinikinPaint(minikin::MinikinPaint* minikinPaint,
- minikin::FontCollection** pFont, const Paint* paint, Typeface* typeface) {
+ const Paint* paint, Typeface* typeface) {
const Typeface* resolvedFace = Typeface::resolveDefault(typeface);
- *pFont = resolvedFace->fFontCollection;
minikin::FontStyle resolved = resolvedFace->fStyle;
/* Prepare minikin FontStyle */
@@ -54,23 +53,23 @@
return minikinStyle;
}
-void MinikinUtils::doLayout(minikin::Layout* layout, const Paint* paint, int bidiFlags,
+minikin::Layout MinikinUtils::doLayout(const Paint* paint, int bidiFlags,
Typeface* typeface, const uint16_t* buf, size_t start, size_t count,
size_t bufSize) {
- minikin::FontCollection *font;
minikin::MinikinPaint minikinPaint;
- minikin::FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, &font, paint, typeface);
- layout->setFontCollection(font);
- layout->doLayout(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint);
+ minikin::FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, paint, typeface);
+ minikin::Layout layout(Typeface::resolveDefault(typeface)->fFontCollection);
+ layout.doLayout(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint);
+ return layout;
}
float MinikinUtils::measureText(const Paint* paint, int bidiFlags, Typeface* typeface,
const uint16_t* buf, size_t start, size_t count, size_t bufSize, float *advances) {
- minikin::FontCollection *font;
minikin::MinikinPaint minikinPaint;
- minikin::FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, &font, paint, typeface);
+ minikin::FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, paint, typeface);
+ Typeface* resolvedTypeface = Typeface::resolveDefault(typeface);
return minikin::Layout::measureText(buf, start, count, bufSize, bidiFlags, minikinStyle,
- minikinPaint, font, advances);
+ minikinPaint, resolvedTypeface->fFontCollection, advances);
}
bool MinikinUtils::hasVariationSelector(Typeface* typeface, uint32_t codepoint, uint32_t vs) {
diff --git a/libs/hwui/hwui/MinikinUtils.h b/libs/hwui/hwui/MinikinUtils.h
index d6f64d2..0f22adc 100644
--- a/libs/hwui/hwui/MinikinUtils.h
+++ b/libs/hwui/hwui/MinikinUtils.h
@@ -35,9 +35,9 @@
class MinikinUtils {
public:
ANDROID_API static minikin::FontStyle prepareMinikinPaint(minikin::MinikinPaint* minikinPaint,
- minikin::FontCollection** pFont, const Paint* paint, Typeface* typeface);
+ const Paint* paint, Typeface* typeface);
- ANDROID_API static void doLayout(minikin::Layout* layout, const Paint* paint, int bidiFlags,
+ ANDROID_API static minikin::Layout doLayout(const Paint* paint, int bidiFlags,
Typeface* typeface, const uint16_t* buf, size_t start, size_t count,
size_t bufSize);
@@ -56,11 +56,11 @@
ANDROID_API static void forFontRun(const minikin::Layout& layout, Paint* paint, F& f) {
float saveSkewX = paint->getTextSkewX();
bool savefakeBold = paint->isFakeBoldText();
- minikin::MinikinFont* curFont = NULL;
+ const minikin::MinikinFont* curFont = nullptr;
size_t start = 0;
size_t nGlyphs = layout.nGlyphs();
for (size_t i = 0; i < nGlyphs; i++) {
- minikin::MinikinFont* nextFont = layout.getFont(i);
+ const minikin::MinikinFont* nextFont = layout.getFont(i);
if (i > 0 && nextFont != curFont) {
MinikinFontSkia::populateSkPaint(paint, curFont, layout.getFakery(start));
f(start, i);
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index 9f9fac6..4b8575a 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -64,7 +64,6 @@
Typeface* result = new Typeface;
if (result != nullptr) {
result->fFontCollection = resolvedFace->fFontCollection;
- result->fFontCollection->Ref();
result->fSkiaStyle = style;
result->fBaseWeight = resolvedFace->fBaseWeight;
resolveStyle(result);
@@ -83,7 +82,6 @@
// None of passed axes are supported by this collection.
// So we will reuse the same collection with incrementing reference count.
result->fFontCollection = resolvedFace->fFontCollection;
- result->fFontCollection->Ref();
}
result->fSkiaStyle = resolvedFace->fSkiaStyle;
result->fBaseWeight = resolvedFace->fBaseWeight;
@@ -97,7 +95,6 @@
Typeface* result = new Typeface;
if (result != nullptr) {
result->fFontCollection = resolvedFace->fFontCollection;
- result->fFontCollection->Ref();
result->fSkiaStyle = resolvedFace->fSkiaStyle;
result->fBaseWeight = weight;
resolveStyle(result);
@@ -105,18 +102,19 @@
return result;
}
-Typeface* Typeface::createFromFamilies(const std::vector<minikin::FontFamily*>& families) {
+Typeface* Typeface::createFromFamilies(
+ std::vector<std::shared_ptr<minikin::FontFamily>>&& families) {
Typeface* result = new Typeface;
- result->fFontCollection = new minikin::FontCollection(families);
+ result->fFontCollection.reset(new minikin::FontCollection(families));
if (families.empty()) {
ALOGW("createFromFamilies creating empty collection");
result->fSkiaStyle = SkTypeface::kNormal;
} else {
const minikin::FontStyle defaultStyle;
- minikin::FontFamily* firstFamily = reinterpret_cast<minikin::FontFamily*>(families[0]);
- minikin::MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font;
- if (mf != NULL) {
- SkTypeface* skTypeface = reinterpret_cast<MinikinFontSkia*>(mf)->GetSkTypeface();
+ const std::shared_ptr<minikin::FontFamily>& firstFamily = families[0];
+ const minikin::MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font;
+ if (mf != nullptr) {
+ SkTypeface* skTypeface = reinterpret_cast<const MinikinFontSkia*>(mf)->GetSkTypeface();
// TODO: probably better to query more precise style from family, will be important
// when we open up API to access 100..900 weights
result->fSkiaStyle = skTypeface->style();
@@ -129,11 +127,6 @@
return result;
}
-void Typeface::unref() {
- fFontCollection->Unref();
- delete this;
-}
-
void Typeface::setDefault(Typeface* face) {
gDefaultTypeface = face;
}
@@ -150,15 +143,12 @@
sk_sp<SkTypeface> typeface = SkTypeface::MakeFromStream(fontData.release());
LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", kRobotoFont);
- minikin::MinikinFont* font = new MinikinFontSkia(std::move(typeface), data, st.st_size, 0,
- std::vector<minikin::FontVariation>());
- minikin::FontFamily* family = new minikin::FontFamily(
- std::vector<minikin::Font>({ minikin::Font(font, minikin::FontStyle()) }));
- font->Unref();
-
- std::vector<minikin::FontFamily*> typefaces = { family };
- minikin::FontCollection *collection = new minikin::FontCollection(typefaces);
- family->Unref();
+ std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>(
+ std::move(typeface), data, st.st_size, 0, std::vector<minikin::FontVariation>());
+ std::shared_ptr<minikin::FontFamily> family = std::make_shared<minikin::FontFamily>(
+ std::vector<minikin::Font>({ minikin::Font(std::move(font), minikin::FontStyle()) }));
+ std::shared_ptr<minikin::FontCollection> collection =
+ std::make_shared<minikin::FontCollection>(std::move(family));
Typeface* hwTypeface = new Typeface();
hwTypeface->fFontCollection = collection;
diff --git a/libs/hwui/hwui/Typeface.h b/libs/hwui/hwui/Typeface.h
index 4392ebc..19a4f6c5 100644
--- a/libs/hwui/hwui/Typeface.h
+++ b/libs/hwui/hwui/Typeface.h
@@ -23,11 +23,12 @@
#include <cutils/compiler.h>
#include <minikin/FontCollection.h>
#include <vector>
+#include <memory>
namespace android {
struct ANDROID_API Typeface {
- minikin::FontCollection *fFontCollection;
+ std::shared_ptr<minikin::FontCollection> fFontCollection;
// style used for constructing and querying Typeface objects
SkTypeface::Style fSkiaStyle;
@@ -37,8 +38,6 @@
// resolved style actually used for rendering
minikin::FontStyle fStyle;
- void unref();
-
static Typeface* resolveDefault(Typeface* src);
static Typeface* createFromTypeface(Typeface* src, SkTypeface::Style style);
@@ -48,7 +47,8 @@
static Typeface* createWeightAlias(Typeface* src, int baseweight);
- static Typeface* createFromFamilies(const std::vector<minikin::FontFamily*>& families);
+ static Typeface* createFromFamilies(
+ std::vector<std::shared_ptr<minikin::FontFamily>>&& families);
static void setDefault(Typeface* face);
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index fc31f32..8f341a8 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -113,5 +113,6 @@
// for reporting callback completion
void locationCallbackFinished(ILocationListener listener);
-
+ // used by gts tests to verify throttling whitelist
+ String[] getBackgroundThrottlingWhitelist();
}
diff --git a/media/java/android/media/AudioFocusRequest.java b/media/java/android/media/AudioFocusRequest.java
new file mode 100644
index 0000000..1b75a78
--- /dev/null
+++ b/media/java/android/media/AudioFocusRequest.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.media.AudioManager.OnAudioFocusChangeListener;
+import android.os.Handler;
+import android.os.Looper;
+
+/**
+ * A class to encapsulate information about an audio focus request.
+ * An {@code AudioFocusRequest} instance is built by {@link Builder}, and is used to
+ * request and abandon audio focus, respectively
+ * with {@link AudioManager#requestAudioFocus(AudioFocusRequest)} and
+ * {@link AudioManager#abandonAudioFocusRequest(AudioFocusRequest)}.
+ * <p>In the context of describing audio focus, the term "ducking" is used. It describes a temporary
+ * lowering of the audio level of an application in response to another application playing audio
+ * concurrently. An example is during the playback of driving directions,
+ * a user listening to music expects the music to "duck" during the playback of the message
+ * announcing directions.
+ */
+// TODO use this class to provide more documentation about audio focus and the new behaviors
+// describe up to N, and after.
+public final class AudioFocusRequest {
+
+ // default attributes for the request when not specified
+ private final static AudioAttributes FOCUS_DEFAULT_ATTR = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_MEDIA).build();
+
+ private final OnAudioFocusChangeListener mFocusListener; // may be null
+ private final Handler mListenerHandler; // may be null
+ private final AudioAttributes mAttr; // never null
+ private final int mFocusGain;
+ private final int mFlags;
+
+ //TODO implement use of optional handler
+ private AudioFocusRequest(OnAudioFocusChangeListener listener, Handler handler,
+ AudioAttributes attr, int focusGain, int flags) {
+ mFocusListener = listener;
+ mListenerHandler = handler;
+ mFocusGain = focusGain;
+ mAttr = attr;
+ mFlags = flags;
+ }
+
+ /**
+ * @hide
+ * Checks whether a focus gain constant is a valid value for an audio focus request.
+ * @param focusGain value to check
+ * @return true if focusGain is a valid value for an audio focus request.
+ */
+ final static boolean isValidFocusGain(int focusGain) {
+ switch (focusGain) {
+ case AudioManager.AUDIOFOCUS_GAIN:
+ case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:
+ case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:
+ case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Returns the focus change listener set for this {@code AudioFocusRequest}.
+ * @return null if no {@link AudioManager.OnAudioFocusChangeListener} was set.
+ */
+ public @Nullable OnAudioFocusChangeListener getOnAudioFocusChangeListener() {
+ return mFocusListener;
+ }
+
+ /**
+ * Returns the {@link Handler} to be used for the focus change listener.
+ * @return the same {@code Handler} set in.
+ * {@link Builder#setOnAudioFocusChangeListener(OnAudioFocusChangeListener, Handler)}, or null
+ * if no listener was set.
+ */
+ public @Nullable Handler getOnAudioFocusChangeListenerHandler() {
+ return mListenerHandler;
+ }
+
+ /**
+ * Returns the {@link AudioAttributes} set for this {@code AudioFocusRequest}, or the default
+ * attributes if none were set.
+ * @return non-null {@link AudioAttributes}.
+ */
+ public @NonNull AudioAttributes getAudioAttributes() {
+ return mAttr;
+ }
+
+ /**
+ * Returns the type of audio focus request configured for this {@code AudioFocusRequest}.
+ * @return one of {@link AudioManager#AUDIOFOCUS_GAIN},
+ * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
+ * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and
+ * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}.
+ */
+ public int getFocusGain() {
+ return mFocusGain;
+ }
+
+ /**
+ * Returns whether the application that would use this {@code AudioFocusRequest} would pause
+ * when it is requested to duck.
+ * @return the duck/pause behavior.
+ */
+ public boolean willPauseWhenDucked() {
+ return (mFlags & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS)
+ == AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS;
+ }
+
+ /**
+ * Returns whether the application that would use this {@code AudioFocusRequest} supports
+ * a focus gain granted after a temporary request failure.
+ * @return whether delayed focus gain is supported.
+ */
+ public boolean acceptsDelayedFocusGain() {
+ return (mFlags & AudioManager.AUDIOFOCUS_FLAG_DELAY_OK)
+ == AudioManager.AUDIOFOCUS_FLAG_DELAY_OK;
+ }
+
+ int getFlags() {
+ return mFlags;
+ }
+
+ /**
+ * Builder class for {@link AudioFocusRequest} objects.
+ * <p> Here is an example where {@code Builder} is used to define the
+ * {@link AudioFocusRequest} for requesting audio focus:
+ *
+ * <pre class="prettyprint">
+ * mAudioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE);
+ * mPlaybackAttributes = new AudioAttributes.Builder()
+ * .setUsage(AudioAttributes.USAGE_GAME)
+ * .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
+ * .build();
+ * mFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
+ * .setAudioAttributes(mPlaybackAttributes)
+ * .setAcceptsDelayedFocusGain(true)
+ * .setOnAudioFocusChangeListener(mMyFocusListener, mMyHandler)
+ * .build();
+ * mMediaPlayer = new MediaPlayer();
+ * ...
+ * mMediaPlayer.setAudioAttributes(mPlaybackAttributes);
+ * ...
+ * mAudioManager.requestAudioFocus(mFocusRequest);
+ * ...
+ * mAudioManager.abandonAudioFocusRequest(mFocusRequest);
+ * </pre>
+ *
+ */
+ public static final class Builder {
+ private OnAudioFocusChangeListener mFocusListener;
+ private Handler mListenerHandler;
+ private AudioAttributes mAttr = FOCUS_DEFAULT_ATTR;
+ private int mFocusGain;
+ private boolean mPausesOnDuck = false;
+ private boolean mDelayedFocus = false;
+
+ /**
+ * Constructs a new {@code Builder}, and specifies how audio focus
+ * will be requested. Valid values for focus requests are
+ * {@link AudioManager#AUDIOFOCUS_GAIN}, {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
+ * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and
+ * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}.
+ * <p>By default there is no focus change listener, and the <code>AudioAttributes</code>
+ * have a usage of {@link AudioAttributes#USAGE_MEDIA}.
+ * @param focusGain the type of audio focus gain that will be requested
+ * @throws IllegalArgumentException thrown when an invalid focus gain type is used
+ */
+ public Builder(int focusGain) {
+ setFocusGain(focusGain);
+ }
+
+ /**
+ * Constructs a new {@code Builder} with all the properties of the {@code AudioFocusRequest}
+ * passed as parameter.
+ * Use this method when you want a new request to differ only by some properties.
+ * @param requestToCopy the non-null {@code AudioFocusRequest} to build a duplicate from.
+ * @throws IllegalArgumentException thrown when a null {@code AudioFocusRequest} is used.
+ */
+ public Builder(@NonNull AudioFocusRequest requestToCopy) {
+ if (requestToCopy == null) {
+ throw new IllegalArgumentException("Illegal null AudioFocusRequest");
+ }
+ mAttr = requestToCopy.mAttr;
+ mFocusListener = requestToCopy.mFocusListener;
+ mListenerHandler = requestToCopy.mListenerHandler;
+ mFocusGain = requestToCopy.mFocusGain;
+ mPausesOnDuck = requestToCopy.willPauseWhenDucked();
+ mDelayedFocus = requestToCopy.acceptsDelayedFocusGain();
+ }
+
+ /**
+ * Sets the type of focus gain that will be requested.
+ * Use this method to replace the focus gain when building a request by modifying an
+ * existing {@code AudioFocusRequest} instance.
+ * @param focusGain the type of audio focus gain that will be requested.
+ * @return this {@code Builder} instance
+ * @throws IllegalArgumentException thrown when an invalid focus gain type is used
+ */
+ public @NonNull Builder setFocusGain(int focusGain) {
+ if (!isValidFocusGain(focusGain)) {
+ throw new IllegalArgumentException("Illegal audio focus gain type " + focusGain);
+ }
+ mFocusGain = focusGain;
+ return this;
+ }
+
+ /**
+ * Sets the listener called when audio focus changes after being requested with
+ * {@link AudioManager#requestAudioFocus(AudioFocusRequest)}, and until being abandoned
+ * with {@link AudioManager#abandonAudioFocusRequest(AudioFocusRequest)}.
+ * Note that only focus changes (gains and losses) affecting the focus owner are reported,
+ * not gains and losses of other focus requesters in the system.
+ * @param listener the listener receiving the focus change notifications.
+ * @param handler the {@link Handler} for the thread on which to execute
+ * the notifications. If {@code null}, the {@code Handler} associated with the main
+ * {@link Looper} will be used.
+ * @return this {@code Builder} instance.
+ * @throws IllegalArgumentException thrown when a non-null handler is used with a null
+ * listener.
+ */
+ public @NonNull Builder setOnAudioFocusChangeListener(
+ @Nullable OnAudioFocusChangeListener listener, @Nullable Handler handler) {
+ if (listener == null && handler != null) {
+ throw new IllegalArgumentException(
+ "Illegal non-null handler without a focus listener");
+ }
+ mFocusListener = listener;
+ mListenerHandler = handler;
+ return this;
+ }
+
+ /**
+ * Sets the {@link AudioAttributes} to be associated with the focus request, and which
+ * describe the use case describing why focus is requested.
+ * As the focus requests typically precede audio playback, this information is used on
+ * certain platforms to declare the subsequent playback use case. It is therefore good
+ * practice to use in this method the same {@code AudioAttributes} as used for
+ * playback, see for example {@link MediaPlayer#setAudioAttributes(AudioAttributes)} in
+ * {@code MediaPlayer} or {@link AudioTrack.Builder#setAudioAttributes(AudioAttributes)}
+ * in {@code AudioTrack}.
+ * @param attributes the {@link AudioAttributes} for the focus request.
+ * @return this {@code Builder} instance.
+ * @throws IllegalArgumentException thrown when using null for the attributes.
+ */
+ public @NonNull Builder setAudioAttributes(@NonNull AudioAttributes attributes) {
+ if (attributes == null) {
+ throw new IllegalArgumentException("Illegal null AudioAttributes");
+ }
+ mAttr = attributes;
+ return this;
+ }
+
+ /**
+ * Declare the intended behavior of the application with regards to audio ducking.
+ * See more details in the {@link AudioFocusRequest} class documentation.
+ * @param pauseOnDuck use {@code true} if the application intends to pause audio playback
+ * when losing focus with {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}.
+ * If {@code true}, note that you must also set a focus listener to receive such an
+ * event, with
+ * {@link #setOnAudioFocusChangeListener(OnAudioFocusChangeListener, Handler)}.
+ * @return this {@code Builder} instance.
+ */
+ public @NonNull Builder setWillPauseWhenDucked(boolean pauseOnDuck) {
+ mPausesOnDuck = pauseOnDuck;
+ return this;
+ }
+
+ /**
+ * Marks this focus request as compatible with delayed focus.
+ * See more details about delayed focus in the {@link AudioFocusRequest} class
+ * documentation.
+ * @param acceptsDelayedFocusGain use {@code true} if the application supports delayed
+ * focus. If {@code true}, note that you must also set a focus listener to be notified
+ * of delayed focus gain, with
+ * {@link #setOnAudioFocusChangeListener(OnAudioFocusChangeListener, Handler)}.
+ * @return this {@code Builder} instance
+ */
+ public @NonNull Builder setAcceptsDelayedFocusGain(boolean acceptsDelayedFocusGain) {
+ mDelayedFocus = acceptsDelayedFocusGain;
+ return this;
+ }
+
+ /**
+ * Builds a new {@code AudioFocusRequest} instance combining all the information gathered
+ * by this {@code Builder}'s configuration methods.
+ * @return the {@code AudioFocusRequest} instance qualified by all the properties set
+ * on this {@code Builder}.
+ * @throws IllegalArgumentException thrown when focus request is set to accept delayed
+ * focus, or to pause on duck, but no focus change listener was set.
+ */
+ public AudioFocusRequest build() {
+ if ((mDelayedFocus || mPausesOnDuck) && (mFocusListener == null)) {
+ throw new IllegalArgumentException(
+ "Can't use delayed focus or pause on duck without a listener");
+ }
+ final int flags = 0
+ | (mDelayedFocus ? AudioManager.AUDIOFOCUS_FLAG_DELAY_OK : 0)
+ | (mPausesOnDuck ? AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS : 0);
+ return new AudioFocusRequest(mFocusListener, mListenerHandler,
+ mAttr, mFocusGain, flags);
+ }
+ }
+}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 95d354b..dc69a69 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2209,11 +2209,11 @@
*/
public static final int AUDIOFOCUS_REQUEST_GRANTED = 1;
/**
- * @hide
* A focus change request whose granting is delayed: the request was successful, but the
* requester will only be granted audio focus once the condition that prevented immediate
* granting has ended.
- * See {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)}
+ * See {@link #requestAudioFocus(AudioFocusRequest)} and
+ * {@link AudioFocusRequest.Builder#setAcceptsDelayedFocusGain(boolean)}
*/
public static final int AUDIOFOCUS_REQUEST_DELAYED = 2;
@@ -2293,6 +2293,44 @@
| AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS | AUDIOFOCUS_FLAG_LOCK;
/**
+ * Request audio focus.
+ * See the {@link AudioFocusRequest} for information about the options available to configure
+ * your request, and notification of focus gain and loss.
+ * @param focusRequest a {@link AudioFocusRequest} instance used to configure how focus is
+ * requested.
+ * @return {@link #AUDIOFOCUS_REQUEST_FAILED}, {@link #AUDIOFOCUS_REQUEST_GRANTED}
+ * or {@link #AUDIOFOCUS_REQUEST_DELAYED}.
+ * <br>Note that the return value is never {@link #AUDIOFOCUS_REQUEST_DELAYED} when focus
+ * is requested without building the {@link AudioFocusRequest} with
+ * {@link AudioFocusRequest.Builder#setAcceptsDelayedFocusGain(boolean)} set to
+ * {@code true}.
+ * @throws IllegalArgumentException if passed a null argument
+ */
+ public int requestAudioFocus(@NonNull AudioFocusRequest focusRequest) {
+ if (focusRequest == null) {
+ throw new IllegalArgumentException("Illegal null AudioFocusRequest");
+ }
+ return requestAudioFocus(focusRequest.getOnAudioFocusChangeListener(),
+ focusRequest.getAudioAttributes(),
+ focusRequest.getFocusGain(), focusRequest.getFlags(), null /* no AudioPolicy*/);
+ }
+
+ /**
+ * Abandon audio focus. Causes the previous focus owner, if any, to receive focus.
+ * @param focusRequest the {@link AudioFocusRequest} that was used when requesting focus
+ * with {@link #requestAudioFocus(AudioFocusRequest)}.
+ * @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
+ * @throws IllegalArgumentException if passed a null argument
+ */
+ public int abandonAudioFocusRequest(@NonNull AudioFocusRequest focusRequest) {
+ if (focusRequest == null) {
+ throw new IllegalArgumentException("Illegal null AudioFocusRequest");
+ }
+ return abandonAudioFocus(focusRequest.getOnAudioFocusChangeListener(),
+ focusRequest.getAudioAttributes());
+ }
+
+ /**
* @hide
* Request audio focus.
* Send a request to obtain the audio focus. This method differs from
@@ -2372,8 +2410,7 @@
if (requestAttributes == null) {
throw new IllegalArgumentException("Illegal null AudioAttributes argument");
}
- if ((durationHint < AUDIOFOCUS_GAIN) ||
- (durationHint > AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)) {
+ if (!AudioFocusRequest.isValidFocusGain(durationHint)) {
throw new IllegalArgumentException("Invalid duration hint");
}
if (flags != (flags & AUDIOFOCUS_FLAGS_SYSTEM)) {
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index ddd8a65..7f5d3a0 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -79,6 +79,7 @@
*/
public class AudioTrack extends PlayerBase
implements AudioRouting
+ , VolumeAutomation
{
//---------------------------------------------------------
// Constants
@@ -1753,6 +1754,12 @@
return native_getVolumeShaperState(id);
}
+ @Override
+ public @NonNull VolumeShaper createVolumeShaper(
+ @NonNull VolumeShaper.Configuration configuration) {
+ return new VolumeShaper(configuration, this);
+ }
+
/**
* Sets the playback sample rate for this track. This sets the sampling rate at which
* the audio data will be consumed and played back
diff --git a/media/java/android/media/ICas.aidl b/media/java/android/media/ICas.aidl
deleted file mode 100644
index 6b2ce4a..0000000
--- a/media/java/android/media/ICas.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.media.MediaCas;
-
-/** @hide */
-interface ICas {
- void setPrivateData(in byte[] pvtData);
- byte[] openSession(int program_number);
- byte[] openSessionForStream(int program_number, int elementary_PID);
- void closeSession(in byte[] sessionId);
- void setSessionPrivateData(in byte[] sessionId, in byte[] pvtData);
- void processEcm(in byte[] sessionId, in MediaCas.ParcelableCasData ecm);
- void processEmm(in MediaCas.ParcelableCasData emm);
- void sendEvent(int event, int arg, in @nullable byte[] eventData);
- void provision(String provisionString);
- void refreshEntitlements(int refreshType, in @nullable byte[] refreshData);
- void release();
-}
\ No newline at end of file
diff --git a/media/java/android/media/ICasListener.aidl b/media/java/android/media/ICasListener.aidl
deleted file mode 100644
index 01a5abc..0000000
--- a/media/java/android/media/ICasListener.aidl
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/** @hide */
-interface ICasListener {
- void onEvent(int event, int arg, in @nullable byte[] data);
-}
\ No newline at end of file
diff --git a/media/java/android/media/IMediaCasService.aidl b/media/java/android/media/IMediaCasService.aidl
deleted file mode 100644
index 44f6825..0000000
--- a/media/java/android/media/IMediaCasService.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.media.IDescrambler;
-import android.media.ICas;
-import android.media.ICasListener;
-import android.media.MediaCas;
-
-/** @hide */
-interface IMediaCasService {
- MediaCas.ParcelableCasPluginDescriptor[] enumeratePlugins();
- boolean isSystemIdSupported(int CA_system_id);
- ICas createPlugin(int CA_system_id, ICasListener listener);
- boolean isDescramblerSupported(int CA_system_id);
- IDescrambler createDescrambler(int CA_system_id);
-}
-
diff --git a/media/java/android/media/MediaDescrambler.aidl b/media/java/android/media/MediaDescrambler.aidl
deleted file mode 100644
index e789244..0000000
--- a/media/java/android/media/MediaDescrambler.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/** @hide */
-parcelable MediaDescrambler.DescrambleInfo cpp_header "media/MediaCasDefs.h";
\ No newline at end of file
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 4791cf0..e77c00b 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -53,6 +53,7 @@
* time-interval between key frames.
* Float support added in {@link android.os.Build.VERSION_CODES#N_MR1}</td></tr>
* <tr><td>{@link #KEY_INTRA_REFRESH_PERIOD}</td><td>Integer</td><td><b>encoder-only</b>, optional</td></tr>
+ * <tr><td>{@link #KEY_LATENCY}</td><td>Integer</td><td><b>encoder-only</b>, optional</td></tr>
* <tr><td>{@link #KEY_MAX_WIDTH}</td><td>Integer</td><td><b>decoder-only</b>, optional, max-resolution width</td></tr>
* <tr><td>{@link #KEY_MAX_HEIGHT}</td><td>Integer</td><td><b>decoder-only</b>, optional, max-resolution height</td></tr>
* <tr><td>{@link #KEY_REPEAT_PREVIOUS_FRAME_AFTER}</td><td>Long</td><td><b>encoder in surface-mode
@@ -577,6 +578,18 @@
public static final String KEY_LEVEL = "level";
/**
+ * An optional key describing the desired encoder latency in frames. This is an optional
+ * parameter that applies only to video encoders. If encoder supports it, it should ouput
+ * at least one output frame after being queued the specified number of frames. This key
+ * is ignored if the video encoder does not support the latency feature. Use the output
+ * format to verify that this feature was enabled and the actual value used by the encoder.
+ * <p>
+ * If the key is not specified, the default latency will be implenmentation specific.
+ * The associated value is an integer.
+ */
+ public static final String KEY_LATENCY = "latency";
+
+ /**
* A key describing the desired clockwise rotation on an output surface.
* This key is only used when the codec is configured using an output surface.
* The associated value is an integer, representing degrees. Supported values
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index aacce91..832b297 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -68,44 +68,46 @@
<h4>Metadata Track</h4>
<p>
- Metadata is usefule in carrying extra information that correlated with video or audio to
- facilate offline processing, e.g. gyro signals from the sensor. Meatadata track is only
- supported in MP4 format. When adding a metadata track, track's mime format must start with
- prefix "application/", e.g. "applicaton/gyro". Metadata's format/layout will be defined by
- the application. The generated MP4 file uses TextMetaDataSampleEntry defined in section 12.3.3.2
- of the ISOBMFF to signal the metadata's mime format. When using {@link android.media.MediaExtractor}
- to extract the file with metadata track, the mime format of the metadata will be extracted into
- {@link android.media.MediaFormat}.
+ Per-frame metadata is useful in carrying extra information that correlated with video or audio to
+ facilitate offline processing, e.g. gyro signals from the sensor could help video stabilization when
+ doing offline processing. Metaadata track is only supported in MP4 container. When adding a new
+ metadata track, track's mime format must start with prefix "application/", e.g. "applicaton/gyro".
+ Metadata's format/layout will be defined by the application. Writing metadata is nearly the same as
+ writing video/audio data except that the data will not be from mediacodec. Application just needs
+ to pass the bytebuffer that contains the metadata and also the associated timestamp to the
+ {@link #writeSampleData} api. The timestamp must be in the same time base as video and audio. The
+ generated MP4 file uses TextMetaDataSampleEntry defined in section 12.3.3.2 of the ISOBMFF to signal
+ the metadata's mime format. When using{@link android.media.MediaExtractor} to extract the file with
+ metadata track, the mime format of the metadata will be extracted into {@link android.media.MediaFormat}.
<pre class=prettyprint>
MediaMuxer muxer = new MediaMuxer("temp.mp4", OutputFormat.MUXER_OUTPUT_MPEG_4);
- // More often, the MediaFormat will be retrieved from MediaCodec.getOutputFormat()
- // or MediaExtractor.getTrackFormat().
+ // SetUp Video/Audio Tracks.
MediaFormat audioFormat = new MediaFormat(...);
MediaFormat videoFormat = new MediaFormat(...);
+ int audioTrackIndex = muxer.addTrack(audioFormat);
+ int videoTrackIndex = muxer.addTrack(videoFormat);
// Setup Metadata Track
MediaFormat metadataFormat = new MediaFormat(...);
metadataFormat.setString(KEY_MIME, "application/gyro");
-
- int audioTrackIndex = muxer.addTrack(audioFormat);
- int videoTrackIndex = muxer.addTrack(videoFormat);
int metadataTrackIndex = muxer.addTrack(metadataFormat);
- ByteBuffer inputBuffer = ByteBuffer.allocate(bufferSize);
- boolean finished = false;
- BufferInfo bufferInfo = new BufferInfo();
muxer.start();
- while(!finished) {
- // getInputBuffer() will fill the inputBuffer with one frame of encoded
- // sample from either MediaCodec or MediaExtractor, set isAudioSample to
- // true when the sample is audio data, set up all the fields of bufferInfo,
- // and return true if there are no more samples.
- finished = getInputBuffer(inputBuffer, sampleType, bufferInfo);
- if (!finished) {
- int currentTrackIndex = getTrackIndex(sampleType);
- muxer.writeSampleData(currentTrackIndex, inputBuffer, bufferInfo);
- }
+ while(..) {
+ // Allocate bytebuffer and write gyro data(x,y,z) into it.
+ ByteBuffer metaData = ByteBuffer.allocate(bufferSize);
+ metaData.putFloat(x);
+ metaData.putFloat(y);
+ metaData.putFloat(z);
+ BufferInfo metaInfo = new BufferInfo();
+ // Associate this metadata with the video frame by setting
+ // the same timestamp as the video frame.
+ metaInfo.presentationTimeUs = currentVideoTrackTimeUs;
+ metaInfo.offset = 0;
+ metaInfo.flags = 0;
+ metaInfo.size = bufferSize;
+ muxer.writeSampleData(metadataTrackIndex, metaData, metaInfo);
};
muxer.stop();
muxer.release();
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 5008a5f..1ebbe85 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -579,6 +579,7 @@
*/
public class MediaPlayer extends PlayerBase
implements SubtitleController.Listener
+ , VolumeAutomation
{
/**
Constant to retrieve only the new metadata since the last
@@ -1373,6 +1374,12 @@
return native_getVolumeShaperState(id);
}
+ @Override
+ public @NonNull VolumeShaper createVolumeShaper(
+ @NonNull VolumeShaper.Configuration configuration) {
+ return new VolumeShaper(configuration, this);
+ }
+
private native int native_applyVolumeShaper(
@NonNull VolumeShaper.Configuration configuration,
@NonNull VolumeShaper.Operation operation);
diff --git a/media/java/android/media/VolumeAutomation.java b/media/java/android/media/VolumeAutomation.java
new file mode 100644
index 0000000..dff8801
--- /dev/null
+++ b/media/java/android/media/VolumeAutomation.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.annotation.NonNull;
+import android.media.VolumeShaper.Configuration;
+
+/**
+ * {@code VolumeAutomation} defines an interface for automatic volume control
+ * of {@link AudioTrack} and {@link MediaPlayer} objects.
+ */
+public interface VolumeAutomation {
+ /**
+ * Returns a {@link VolumeShaper} object that can be used modify the volume envelope
+ * of the player or track.
+ *
+ * @param configuration the {@link VolumeShaper.Configuration configuration}
+ * that specifies the curve and duration to use.
+ * @return a {@code VolumeShaper} object
+ * @throws IllegalArgumentException if the configuration is not allowed by the player.
+ * @throws IllegalStateException if too many VolumeShapers are requested or the state of
+ * the player does not permit its creation (e.g. player is released).
+ */
+ public @NonNull VolumeShaper createVolumeShaper(
+ @NonNull VolumeShaper.Configuration configuration);
+}
diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java
index 4a2c4d8..cb27d10 100644
--- a/media/java/android/media/VolumeShaper.java
+++ b/media/java/android/media/VolumeShaper.java
@@ -23,78 +23,25 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.lang.AutoCloseable;
import java.lang.ref.WeakReference;
import java.util.Objects;
/**
- * TODO: remove @hide
* The {@code VolumeShaper} class is used to automatically control audio volume during media
- * playback, allowing for simple implementation of transition effects and ducking.
+ * playback, allowing simple implementation of transition effects and ducking.
*
* The {@link VolumeShaper} appears as an additional scaling on the audio output,
- * and can be used independently of track or stream volume controls.
+ * and adjusts independently of track or stream volume controls.
*/
-public final class VolumeShaper {
+public final class VolumeShaper implements AutoCloseable {
/* member variables */
private int mId;
private final WeakReference<PlayerBase> mWeakPlayerBase;
- private final WeakReference<PlayerProxy> mWeakPlayerProxy;
- private PlayerProxy mPlayerProxy;
-
- /**
- * Constructs a {@code VolumeShaper} from a {@link VolumeShaper.Configuration} and an
- * {@link AudioTrack}.
- *
- * @param configuration
- * @param audioTrack
- */
- public VolumeShaper(@NonNull Configuration configuration, @NonNull AudioTrack audioTrack) {
- this(configuration, (PlayerBase)audioTrack);
- }
-
- /**
- * Constructs a {@code VolumeShaper} from a {@link VolumeShaper.Configuration} and a
- * {@link MediaPlayer}.
- *
- * @param configuration
- * @param mediaPlayer
- */
- public VolumeShaper(@NonNull Configuration configuration, @NonNull MediaPlayer mediaPlayer) {
- this(configuration, (PlayerBase)mediaPlayer);
- }
/* package */ VolumeShaper(
@NonNull Configuration configuration, @NonNull PlayerBase playerBase) {
mWeakPlayerBase = new WeakReference<PlayerBase>(playerBase);
- mPlayerProxy = null;
- mWeakPlayerProxy = null;
- mId = applyPlayer(configuration, new Operation.Builder().defer().build());
- }
-
- /**
- * @hide
- * Constructs a {@code VolumeShaper} from a {@link VolumeShaper.Configuration} and a
- * {@code PlayerProxy} object. The PlayerProxy object requires that the configuration
- * be set with a system VolumeShaper id (this is a reserved value).
- *
- * @param configuration
- * @param playerProxy
- */
- public VolumeShaper(
- @NonNull Configuration configuration,
- @NonNull PlayerProxy playerProxy,
- boolean keepReference) {
- if (configuration.getId() < 0) {
- throw new IllegalArgumentException("playerProxy configuration id must be specified");
- }
- if (keepReference) {
- mPlayerProxy = playerProxy;
- mWeakPlayerProxy = null;
- } else {
- mWeakPlayerProxy = new WeakReference<PlayerProxy>(playerProxy);
- mPlayerProxy = null;
- }
- mWeakPlayerBase = null;
mId = applyPlayer(configuration, new Operation.Builder().defer().build());
}
@@ -104,7 +51,7 @@
/**
* Applies the {@link VolumeShaper.Operation} to the {@code VolumeShaper}.
- * @param operation
+ * @param operation the {@code operation} to apply.
*/
public void apply(@NonNull Operation operation) {
/* void */ applyPlayer(new VolumeShaper.Configuration(mId), operation);
@@ -112,17 +59,16 @@
/**
* Replaces the current {@code VolumeShaper}
- * configuration with a new configuration.
+ * {@code configuration} with a new {@code configuration}.
*
- * This can be used to dynamically change the {@code VolumeShaper}
- * configuration by joining several
- * {@code VolumeShaper} configurations together.
- * This is useful if the user changes the volume while the
- * {@code VolumeShaper} is in effect.
+ * This allows the user to change the volume shape
+ * while the existing {@code VolumeShaper} is in effect.
*
- * @param configuration
- * @param operation
- * @param join
+ * @param configuration the new {@code configuration} to use.
+ * @param operation the operation to apply to the {@code VolumeShaper}
+ * @param join if true, match the start volume of the
+ * new {@code configuration} to the current volume of the existing
+ * {@code VolumeShaper}, to avoid discontinuity.
*/
public void replace(
@NonNull Configuration configuration, @NonNull Operation operation, boolean join) {
@@ -141,10 +87,11 @@
}
/**
- * Releases the {@code VolumeShaper}. Any volume scale due to the
+ * Releases the {@code VolumeShaper} object; any volume scale due to the
* {@code VolumeShaper} is removed.
*/
- public void release() {
+ @Override
+ public void close() {
try {
/* void */ applyPlayer(
new VolumeShaper.Configuration(mId),
@@ -155,15 +102,11 @@
if (mWeakPlayerBase != null) {
mWeakPlayerBase.clear();
}
- if (mWeakPlayerProxy != null) {
- mWeakPlayerProxy.clear();
- }
- mPlayerProxy = null;
}
@Override
protected void finalize() {
- release(); // ensure we remove the native volume shaper
+ close(); // ensure we remove the native volume shaper
}
/**
@@ -177,20 +120,7 @@
@NonNull VolumeShaper.Configuration configuration,
@NonNull VolumeShaper.Operation operation) {
final int id;
- if (mPlayerProxy != null || mWeakPlayerProxy != null) {
- // The PlayerProxy accepts only one way transactions so
- // the Configuration must have an id set to one of the system
- // ids (a positive value less than 16).
- PlayerProxy player = mWeakPlayerProxy != null ? mWeakPlayerProxy.get() : mPlayerProxy;
- if (player == null) {
- throw new IllegalStateException("player deallocated");
- }
- id = configuration.getId();
- if (id < 0) {
- throw new IllegalArgumentException("proxy requires configuration with id");
- }
- player.applyVolumeShaper(configuration, operation);
- } else if (mWeakPlayerBase != null) {
+ if (mWeakPlayerBase != null) {
PlayerBase player = mWeakPlayerBase.get();
if (player == null) {
throw new IllegalStateException("player deallocated");
@@ -220,9 +150,7 @@
*/
private @NonNull VolumeShaper.State getStatePlayer(int id) {
final VolumeShaper.State state;
- if (mPlayerProxy != null || mWeakPlayerProxy != null) {
- throw new IllegalStateException("getStatePlayer not permitted through proxy");
- } else if (mWeakPlayerBase != null) {
+ if (mWeakPlayerBase != null) {
PlayerBase player = mWeakPlayerBase.get();
if (player == null) {
throw new IllegalStateException("player deallocated");
@@ -238,11 +166,17 @@
}
/**
- * The {@code VolumeShaper.Configuration} class contains curve shape
- * and parameter information for constructing a {@code VolumeShaper}.
- * This curve shape and parameter information is specified
- * on {@code VolumeShaper} creation
- * and may be replaced through {@link VolumeShaper#replace}.
+ * The {@code VolumeShaper.Configuration} class contains curve
+ * and duration information.
+ * It is constructed by the {@link VolumeShaper.Configuration.Builder}.
+ * <p>
+ * A {@code VolumeShaper.Configuration} is used by
+ * {@link VolumeAutomation#createVolumeShaper(Configuration)
+ * VolumeAutomation#createVolumeShaper(Configuration)} to create
+ * a {@code VolumeShaper} and
+ * by {@link VolumeShaper#replace(Configuration, Operation, boolean)
+ * VolumeShaper#replace(Configuration, Operation, boolean)}
+ * to replace an existing {@code configuration}.
*/
public static final class Configuration implements Parcelable {
private static final int MAXIMUM_CURVE_POINTS = 16;
@@ -310,9 +244,9 @@
/**
* Cubic interpolated volume curve
- * with local monotonicity preservation.
+ * that preserves local monotonicity.
* So long as the control points are locally monotonic,
- * the curve interpolation will also be locally monotonic.
+ * the curve interpolation between those points are monotonic.
* This is useful for cubic spline interpolated
* volume ramps and ducks.
*/
@@ -328,6 +262,7 @@
public @interface OptionFlag {}
/**
+ * @hide
* Use a dB full scale volume range for the volume curve.
*<p>
* The volume scale is typically from 0.f to 1.f on a linear scale;
@@ -337,6 +272,7 @@
public static final int OPTION_FLAG_VOLUME_IN_DBFS = (1 << 0);
/**
+ * @hide
* Use clock time instead of media time.
*<p>
* The default implementation of {@code VolumeShaper} is to apply
@@ -354,7 +290,8 @@
/**
* A one second linear ramp from silence to full volume.
- * Use {@link VolumeShaper.Builder#reflectTimes()} to generate
+ * Use {@link VolumeShaper.Builder#reflectTimes()}
+ * or {@link VolumeShaper.Builder#invertVolumes()} to generate
* the matching linear duck.
*/
public static final Configuration LINEAR_RAMP = new VolumeShaper.Configuration.Builder()
@@ -366,7 +303,8 @@
/**
* A one second cubic ramp from silence to full volume.
- * Use {@link VolumeShaper.Builder#reflectTimes()} to generate
+ * Use {@link VolumeShaper.Builder#reflectTimes()}
+ * or {@link VolumeShaper.Builder#invertVolumes()} to generate
* the matching cubic duck.
*/
public static final Configuration CUBIC_RAMP = new VolumeShaper.Configuration.Builder()
@@ -377,17 +315,19 @@
.build();
/**
- * A one second sine curve for energy preserving cross fades.
+ * A one second sine curve
+ * from silence to full volume for energy preserving cross fades.
* Use {@link VolumeShaper.Builder#reflectTimes()} to generate
* the matching cosine duck.
*/
public static final Configuration SINE_RAMP;
/**
- * A one second sine-squared s-curve ramp.
+ * A one second sine-squared s-curve ramp
+ * from silence to full volume.
* Use {@link VolumeShaper.Builder#reflectTimes()}
* or {@link VolumeShaper.Builder#invertVolumes()} to generate
- * the matching s-curve duck.
+ * the matching sine-squared s-curve duck.
*/
public static final Configuration SCURVE_RAMP;
@@ -510,6 +450,7 @@
};
/**
+ * @hide
* Constructs a volume shaper from an id.
*
* This is an opaque handle for controlling a {@code VolumeShaper} that has
@@ -522,7 +463,7 @@
* @param id
* @throws IllegalArgumentException if id is negative.
*/
- private Configuration(int id) {
+ public Configuration(int id) {
if (id < 0) {
throw new IllegalArgumentException("negative id " + id);
}
@@ -557,6 +498,7 @@
}
/**
+ * @hide
* Returns the {@code VolumeShaper} type.
*/
public @Type int getType() {
@@ -579,6 +521,7 @@
}
/**
+ * @hide
* Returns the option flags
*/
public @OptionFlag int getOptionFlags() {
@@ -590,7 +533,7 @@
}
/**
- * Returns the duration of the effect in milliseconds.
+ * Returns the duration of the volume shape in milliseconds.
*/
public double getDurationMs() {
return mDurationMs;
@@ -712,21 +655,22 @@
private int mType = TYPE_SCALE;
private int mId = -1; // invalid
private int mInterpolatorType = INTERPOLATOR_TYPE_CUBIC;
- private int mOptionFlags = 0;
+ private int mOptionFlags = OPTION_FLAG_CLOCK_TIME;
private double mDurationMs = 1000.;
private float[] mTimes = null;
private float[] mVolumes = null;
/**
- * Constructs a new Builder with the defaults.
+ * Constructs a new {@code Builder} with the defaults.
*/
public Builder() {
}
/**
- * Constructs a new Builder from a given {@code VolumeShaper.Configuration}
+ * Constructs a new {@code Builder} with settings
+ * copied from a given {@code VolumeShaper.Configuration}.
* @param configuration prototypical configuration
- * which will be reused in the new Builder.
+ * which will be reused in the new {@code Builder}.
*/
public Builder(@NonNull Configuration configuration) {
mType = configuration.getType();
@@ -740,8 +684,6 @@
/**
* @hide
- * TODO make SystemApi
- *
* Set the id for system defined shapers.
* @param id
* @return
@@ -757,7 +699,11 @@
* If omitted the interplator type is {@link #INTERPOLATOR_TYPE_CUBIC}.
*
* @param interpolatorType method of interpolation used for the volume curve.
- * @return the same Builder instance.
+ * One of {@link #INTERPOLATOR_TYPE_STEP},
+ * {@link #INTERPOLATOR_TYPE_LINEAR},
+ * {@link #INTERPOLATOR_TYPE_CUBIC},
+ * {@link #INTERPOLATOR_TYPE_CUBIC_MONOTONIC}.
+ * @return the same {@code Builder} instance.
* @throws IllegalArgumentException if {@code interpolatorType} is not valid.
*/
public @NonNull Builder setInterpolatorType(@InterpolatorType int interpolatorType) {
@@ -776,6 +722,7 @@
}
/**
+ * @hide
* Sets the optional flags
*
* If omitted, flags are 0. If {@link #OPTION_FLAG_VOLUME_IN_DBFS} has
@@ -783,7 +730,7 @@
* volume domain has changed.
*
* @param optionFlags new value to replace the old {@code optionFlags}.
- * @return the same Builder instance.
+ * @return the same {@code Builder} instance.
* @throws IllegalArgumentException if flag is not recognized.
*/
public @NonNull Builder setOptionFlags(@OptionFlag int optionFlags) {
@@ -800,8 +747,9 @@
* If omitted, the default duration is 1 second.
*
* @param durationMs
- * @return the same Builder instance.
- * @throws IllegalArgumentException if duration is not positive.
+ * @return the same {@code Builder} instance.
+ * @throws IllegalArgumentException if {@code durationMs}
+ * is not strictly positive.
*/
public @NonNull Builder setDurationMs(double durationMs) {
if (durationMs <= 0.) {
@@ -823,19 +771,23 @@
* and no greater than {@link VolumeShaper.Configuration#getMaximumCurvePoints()}.
* <p>
* The volume curve is normalized as follows:
- * (1) time (x) coordinates should be monotonically increasing, from 0.f to 1.f;
- * (2) volume (y) coordinates must be within 0.f to 1.f for linear and be non-positive
- * for log scaling.
+ * time (x) coordinates should be monotonically increasing, from 0.f to 1.f;
+ * volume (y) coordinates must be within 0.f to 1.f.
* <p>
- * The time scale is set by {@link #setDurationMs} in seconds.
+ * The time scale is set by {@link #setDurationMs}.
* <p>
* @param times an array of float values representing
* the time line of the volume curve.
* @param volumes an array of float values representing
* the amplitude of the volume curve.
- * @return the same Builder instance.
+ * @return the same {@code Builder} instance.
* @throws IllegalArgumentException if {@code times} or {@code volumes} is invalid.
*/
+
+ /* Note: volume (y) coordinates must be non-positive for log scaling,
+ * if {@link VolumeShaper.Configuration#OPTION_FLAG_VOLUME_IN_DBFS} is set.
+ */
+
public @NonNull Builder setCurve(@NonNull float[] times, @NonNull float[] volumes) {
String error = checkCurveForErrors(
times, volumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
@@ -852,7 +804,7 @@
* the shaper changes volume from the end
* to the start.
*
- * @return the same Builder instance.
+ * @return the same {@code Builder} instance.
*/
public @NonNull Builder reflectTimes() {
int i;
@@ -871,7 +823,7 @@
* Inverts the volume curve so that the max volume
* becomes the min volume and vice versa.
*
- * @return the same Builder instance.
+ * @return the same {@code Builder} instance.
*/
public @NonNull Builder invertVolumes() {
if (mVolumes.length >= 2) {
@@ -899,8 +851,9 @@
* Keeps the start volume the same.
* This works best if the volume curve is monotonic.
*
- * @return the same Builder instance.
- * @throws IllegalArgumentException if volume is not valid.
+ * @param volume the target end volume to use.
+ * @return the same {@code Builder} instance.
+ * @throws IllegalArgumentException if {@code volume} is not valid.
*/
public @NonNull Builder scaleToEndVolume(float volume) {
final boolean log = (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0;
@@ -930,8 +883,9 @@
* Keeps the end volume the same.
* This works best if the volume curve is monotonic.
*
- * @return the same Builder instance.
- * @throws IllegalArgumentException if volume is not valid.
+ * @param volume the target start volume to use.
+ * @return the same {@code Builder} instance.
+ * @throws IllegalArgumentException if {@code volume} is not valid.
*/
public @NonNull Builder scaleToStartVolume(float volume) {
final boolean log = (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0;
@@ -978,6 +932,8 @@
public static final class Operation implements Parcelable {
/**
* Forward playback from current volume time position.
+ * At the end of the {@code VolumeShaper} curve,
+ * the last volume value persists.
*/
public static final Operation PLAY =
new VolumeShaper.Operation.Builder()
@@ -985,6 +941,8 @@
/**
* Reverse playback from current volume time position.
+ * When the position reaches the start of the {@code VolumeShaper} curve,
+ * the first volume value persists.
*/
public static final Operation REVERSE =
new VolumeShaper.Operation.Builder()
@@ -1039,6 +997,13 @@
*/
private static final int FLAG_DEFER = 1 << 3;
+ /**
+ * Use the id specified in the configuration, creating
+ * VolumeShaper as needed; the configuration should be
+ * TYPE_SCALE.
+ */
+ private static final int FLAG_CREATE_IF_NEEDED = 1 << 4;
+
private static final int FLAG_PUBLIC_ALL = FLAG_REVERSE | FLAG_TERMINATE;
private final int mFlags;
@@ -1126,15 +1091,13 @@
}
/**
- * Replaces the previous {@code VolumeShaper}.
+ * Replaces the previous {@code VolumeShaper} specified by id.
* It has no other effect if the {@code VolumeShaper} is
- * already expired. If the replaceId is the same as the id associated with
- * the {@code VolumeShaper} in a {@code setVolumeShaper()} call,
- * an error is returned.
- * @param handle is a previous volumeShaper {@code VolumeShaper}.
- * @param join the start to match the current volume of the previous
- * shaper.
- * @return the same Builder instance.
+ * already expired.
+ * @param id the id of the previous {@code VolumeShaper}.
+ * @param join if true, match the volume of the previous
+ * shaper to the start volume of the new {@code VolumeShaper}.
+ * @return the same {@code Builder} instance.
*/
public @NonNull Builder replace(int id, boolean join) {
mReplaceId = id;
@@ -1148,7 +1111,7 @@
/**
* Defers all operations.
- * @return the same Builder instance.
+ * @return the same {@code Builder} instance.
*/
public @NonNull Builder defer() {
mFlags |= FLAG_DEFER;
@@ -1158,7 +1121,7 @@
/**
* Terminates the VolumeShaper.
* Do not call directly, use {@link VolumeShaper#release()}.
- * @return the same Builder instance.
+ * @return the same {@code Builder} instance.
*/
public @NonNull Builder terminate() {
mFlags |= FLAG_TERMINATE;
@@ -1167,7 +1130,7 @@
/**
* Reverses direction.
- * @return the same Builder instance.
+ * @return the same {@code Builder} instance.
*/
public @NonNull Builder reverse() {
mFlags ^= FLAG_REVERSE;
@@ -1175,11 +1138,22 @@
}
/**
+ * Use the id specified in the configuration, creating
+ * VolumeShaper as needed; the configuration should be
+ * TYPE_SCALE.
+ * @return the same {@code Builder} instance.
+ */
+ public @NonNull Builder createIfNeeded() {
+ mFlags |= FLAG_CREATE_IF_NEEDED;
+ return this;
+ }
+
+ /**
* Sets the operation flag. Do not call this directly but one of the
* other builder methods.
*
* @param flags new value for {@code flags}, consisting of ORed flags.
- * @return the same Builder instance.
+ * @return the same {@code Builder} instance.
*/
private @NonNull Builder setFlags(@Flag int flags) {
if ((flags & ~FLAG_PUBLIC_ALL) != 0) {
diff --git a/media/java/android/media/session/ICallback.aidl b/media/java/android/media/session/ICallback.aidl
new file mode 100644
index 0000000..322bffa
--- /dev/null
+++ b/media/java/android/media/session/ICallback.aidl
@@ -0,0 +1,35 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.session;
+
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.media.session.MediaSession;
+import android.view.KeyEvent;
+
+/**
+ * @hide
+ */
+oneway interface ICallback {
+ void onMediaKeyEventDispatchedToMediaSession(in KeyEvent event,
+ in MediaSession.Token sessionToken);
+ void onMediaKeyEventDispatchedToMediaButtonReceiver(in KeyEvent event,
+ in ComponentName mediaButtonReceiver);
+
+ void onAddressedPlayerChangedToMediaSession(in MediaSession.Token sessionToken);
+ void onAddressedPlayerChangedToMediaButtonReceiver(in ComponentName mediaButtonReceiver);
+}
+
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 8a98773..5fcb430 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -18,8 +18,9 @@
import android.content.ComponentName;
import android.media.IRemoteVolumeController;
import android.media.session.IActiveSessionsListener;
-import android.media.session.IOnVolumeKeyLongPressListener;
+import android.media.session.ICallback;
import android.media.session.IOnMediaKeyListener;
+import android.media.session.IOnVolumeKeyLongPressListener;
import android.media.session.ISession;
import android.media.session.ISessionCallback;
import android.os.Bundle;
@@ -45,7 +46,7 @@
// For PhoneWindowManager to precheck media keys
boolean isGlobalPriorityActive();
+ void setCallback(in ICallback callback);
void setOnVolumeKeyLongPressListener(in IOnVolumeKeyLongPressListener listener);
void setOnMediaKeyListener(in IOnMediaKeyListener listener);
}
-
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 80d2a0c..83793ae 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -71,6 +71,7 @@
private Context mContext;
+ private CallbackImpl mCallback;
private OnVolumeKeyLongPressListenerImpl mOnVolumeKeyLongPressListener;
private OnMediaKeyListenerImpl mOnMediaKeyListener;
@@ -411,6 +412,36 @@
}
/**
+ * Set a {@link Callback}.
+ *
+ * <p>System can only have a single callback, and the callback can only be set by
+ * Bluetooth service process.
+ *
+ * @param callback A {@link Callback}. {@code null} to reset.
+ * @param handler The handler on which the callback should be invoked, or {@code null}
+ * if the callback should be invoked on the calling thread's looper.
+ * @hide
+ */
+ public void setCallback(@Nullable Callback callback, @Nullable Handler handler) {
+ synchronized (mLock) {
+ try {
+ if (callback == null) {
+ mCallback = null;
+ mService.setCallback(null);
+ } else {
+ if (handler == null) {
+ handler = new Handler();
+ }
+ mCallback = new CallbackImpl(callback, handler);
+ mService.setCallback(mCallback);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to set media key callback", e);
+ }
+ }
+ }
+
+ /**
* Listens for changes to the list of active sessions. This can be added
* using {@link #addOnActiveSessionsChangedListener}.
*/
@@ -439,12 +470,65 @@
public interface OnMediaKeyListener {
/**
* Called when the media key is pressed.
+ * <p>If the listener consumes the initial down event (i.e. ACTION_DOWN with
+ * repeat count zero), it must also comsume all following key events.
+ * (i.e. ACTION_DOWN with repeat count more than zero, and ACTION_UP).
* <p>If it takes more than 1s to return, the key event will be sent to
* other media sessions.
*/
boolean onMediaKey(KeyEvent event);
}
+ /**
+ * Callbacks for the media session service.
+ *
+ * <p>Called when a media key event is dispatched or the addressed player is changed.
+ * The addressed player is either the media session or the media button receiver that will
+ * receive media key events.
+ * @hide
+ */
+ public static abstract class Callback {
+ /**
+ * Called when a media key event is dispatched to the media session
+ * through the media session service.
+ *
+ * @param event Dispatched media key event.
+ * @param sessionToken The media session's token.
+ */
+ public abstract void onMediaKeyEventDispatched(KeyEvent event,
+ MediaSession.Token sessionToken);
+
+ /**
+ * Called when a media key event is dispatched to the media button receiver
+ * through the media session service.
+ * <p>MediaSessionService may broadcast key events to the media button receiver
+ * when reviving playback after the media session is released.
+ *
+ * @param event Dispatched media key event.
+ * @param mediaButtonReceiver The media button receiver.
+ */
+ public abstract void onMediaKeyEventDispatched(KeyEvent event,
+ ComponentName mediaButtonReceiver);
+
+ /**
+ * Called when the addressed player is changed to a media session.
+ * <p>One of the {@ #onAddressedPlayerChanged} will be also called immediately after
+ * {@link #setCallback} if the addressed player exists.
+ *
+ * @param sessionToken The media session's token.
+ */
+ public abstract void onAddressedPlayerChanged(MediaSession.Token sessionToken);
+
+ /**
+ * Called when the addressed player is changed to the media button receiver.
+ * <p>One of the {@ #onAddressedPlayerChanged} will be also called immediately after
+ * {@link #setCallback} if the addressed player exists.
+ *
+ * @param mediaButtonReceiver The media button receiver.
+ */
+ public abstract void onAddressedPlayerChanged(ComponentName mediaButtonReceiver);
+ }
+
private static final class SessionsChangedWrapper {
private Context mContext;
private OnActiveSessionsChangedListener mListener;
@@ -534,9 +618,64 @@
public void run() {
boolean handled = mListener.onMediaKey(event);
Log.d(TAG, "The media key listener is returned " + handled);
- result.send(
- handled ? RESULT_MEDIA_KEY_HANDLED : RESULT_MEDIA_KEY_NOT_HANDLED,
- null);
+ if (result != null) {
+ result.send(
+ handled ? RESULT_MEDIA_KEY_HANDLED : RESULT_MEDIA_KEY_NOT_HANDLED,
+ null);
+ }
+ }
+ });
+ }
+ }
+
+ private static final class CallbackImpl extends ICallback.Stub {
+ private final Callback mCallback;
+ private final Handler mHandler;
+
+ public CallbackImpl(@NonNull Callback callback, @NonNull Handler handler) {
+ mCallback = callback;
+ mHandler = handler;
+ }
+
+ @Override
+ public void onMediaKeyEventDispatchedToMediaSession(KeyEvent event,
+ MediaSession.Token sessionToken) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onMediaKeyEventDispatched(event, sessionToken);
+ }
+ });
+ }
+
+ @Override
+ public void onMediaKeyEventDispatchedToMediaButtonReceiver(KeyEvent event,
+ ComponentName mediaButtonReceiver) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onMediaKeyEventDispatched(event, mediaButtonReceiver);
+ }
+ });
+ }
+
+ @Override
+ public void onAddressedPlayerChangedToMediaSession(MediaSession.Token sessionToken) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onAddressedPlayerChanged(sessionToken);
+ }
+ });
+ }
+
+ @Override
+ public void onAddressedPlayerChangedToMediaButtonReceiver(
+ ComponentName mediaButtonReceiver) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onAddressedPlayerChanged(mediaButtonReceiver);
}
});
}
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 6d8296a..1b53d72 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -25,6 +25,7 @@
import android.content.ContentUris;
import android.content.Intent;
import android.net.Uri;
+import android.os.Bundle;
import android.os.IBinder;
import android.provider.BaseColumns;
import android.text.TextUtils;
@@ -72,6 +73,98 @@
private static final String PATH_PASSTHROUGH = "passthrough";
/**
+ * The method name to get existing columns in the given table of the specified content provider.
+ *
+ * <p>The method caller must provide the following parameter:
+ * <ul>
+ * <li>{@code arg}: The content URI of the target table as a {@link String}.</li>
+ * </ul>
+
+ * <p>On success, the returned {@link android.os.Bundle} will include existing column names
+ * with the key {@link #EXTRA_EXISTING_COLUMN_NAMES}. Otherwise, the return value will be {@code null}.
+ *
+ * @see ContentResolver#call(Uri, String, String, Bundle)
+ * @see #EXTRA_EXISTING_COLUMN_NAMES
+ * @hide
+ */
+ @SystemApi
+ public static final String METHOD_GET_COLUMNS = "get_columns";
+
+ /**
+ * The method name to add a new column in the given table of the specified content provider.
+ *
+ * <p>The method caller must provide the following parameter:
+ * <ul>
+ * <li>{@code arg}: The content URI of the target table as a {@link String}.</li>
+ * <li>{@code extra}: Name, data type, and default value of the new column in a Bundle:
+ * <ul>
+ * <li>{@link #EXTRA_COLUMN_NAME} the column name as a {@link String}.</li>
+ * <li>{@link #EXTRA_DATA_TYPE} the data type as a {@link String}.</li>
+ * <li>{@link #EXTRA_DEFAULT_VALUE} the default value as a {@link String}.
+ * (optional)</li>
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * <p>On success, the returned {@link android.os.Bundle} will include current colum names after
+ * the addition operation with the key {@link #EXTRA_EXISTING_COLUMN_NAMES}. Otherwise, the
+ * return value will be {@code null}.
+ *
+ * @see ContentResolver#call(Uri, String, String, Bundle)
+ * @see #EXTRA_COLUMN_NAME
+ * @see #EXTRA_DATA_TYPE
+ * @see #EXTRA_DEFAULT_VALUE
+ * @see #EXTRA_EXISTING_COLUMN_NAMES
+ * @hide
+ */
+ @SystemApi
+ public static final String METHOD_ADD_COLUMN = "add_column";
+
+ /**
+ * The key for a returned {@link Bundle} value containing existing column names in the given
+ * table as an {@link ArrayList} of {@link String}.
+ *
+ * @see #METHOD_GET_COLUMNS
+ * @see #METHOD_ADD_COLUMN
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_EXISTING_COLUMN_NAMES =
+ "android.media.tv.extra.EXISTING_COLUMN_NAMES";
+
+ /**
+ * The key for a {@link Bundle} parameter containing the new column name to be added in the
+ * given table as a non-empty {@link CharSequence}.
+ *
+ * @see #METHOD_ADD_COLUMN
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_COLUMN_NAME = "android.media.tv.extra.COLUMN_NAME";
+
+ /**
+ * The key for a {@link Bundle} parameter containing the data type of the new column to be added
+ * in the given table as a non-empty {@link CharSequence}, which should be one of the following
+ * values: {@code "TEXT"}, {@code "INTEGER"}, {@code "REAL"}, or {@code "BLOB"}.
+ *
+ * @see #METHOD_ADD_COLUMN
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_DATA_TYPE = "android.media.tv.extra.DATA_TYPE";
+
+ /**
+ * The key for a {@link Bundle} parameter containing the default value of the new column to be
+ * added in the given table as a {@link CharSequence}, which represents a valid default value
+ * according to the data type provided with {@link #EXTRA_DATA_TYPE}.
+ *
+ * @see #METHOD_ADD_COLUMN
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_DEFAULT_VALUE = "android.media.tv.extra.DEFAULT_VALUE";
+
+ /**
* An optional query, update or delete URI parameter that allows the caller to specify TV input
* ID to filter channels.
* @hide
diff --git a/native/android/Android.mk b/native/android/Android.mk
index 1c1ff82..57f996c 100644
--- a/native/android/Android.mk
+++ b/native/android/Android.mk
@@ -19,6 +19,7 @@
net.c \
obb.cpp \
sensor.cpp \
+ sharedmem.cpp \
storage_manager.cpp \
trace.cpp \
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index f9e8fda..e2623d4 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -186,6 +186,9 @@
ASensor_getType;
ASensor_getVendor;
ASensor_isWakeUpSensor; # introduced=21
+ ASharedMemory_create; # introduced=26
+ ASharedMemory_getSize; # introduced=26
+ ASharedMemory_setProt; # introduced=26
AStorageManager_delete;
AStorageManager_getMountedObbPath;
AStorageManager_isObbMounted;
diff --git a/native/android/sharedmem.cpp b/native/android/sharedmem.cpp
new file mode 100644
index 0000000..9d029df
--- /dev/null
+++ b/native/android/sharedmem.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/sharedmem.h>
+#include <cutils/ashmem.h>
+#include <utils/Errors.h>
+
+int ASharedMemory_create(const char *name, size_t size) {
+ if (size == 0) {
+ return android::BAD_VALUE;
+ }
+ return ashmem_create_region(name, size);
+}
+
+size_t ASharedMemory_getSize(int fd) {
+ return ashmem_valid(fd) ? ashmem_get_size_region(fd) : 0;
+}
+
+int ASharedMemory_setProt(int fd, int prot) {
+ return ashmem_set_prot_region(fd, prot);
+}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 22a5b7f..3cc9f65e 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -56,6 +56,7 @@
import android.webkit.MimeTypeMap;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.content.FileSystemProvider;
import com.android.internal.util.IndentingPrintWriter;
import java.io.File;
@@ -63,15 +64,15 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
-public class ExternalStorageProvider extends DocumentsProvider {
+public class ExternalStorageProvider extends FileSystemProvider {
private static final String TAG = "ExternalStorage";
private static final boolean DEBUG = false;
- private static final boolean LOG_INOTIFY = false;
public static final String AUTHORITY = "com.android.externalstorage.documents";
@@ -105,20 +106,17 @@
private static final String ROOT_ID_HOME = "home";
private StorageManager mStorageManager;
- private Handler mHandler;
private final Object mRootsLock = new Object();
@GuardedBy("mRootsLock")
private ArrayMap<String, RootInfo> mRoots = new ArrayMap<>();
- @GuardedBy("mObservers")
- private ArrayMap<File, DirectoryObserver> mObservers = new ArrayMap<>();
-
@Override
public boolean onCreate() {
+ super.onCreate(DEFAULT_DOCUMENT_PROJECTION);
+
mStorageManager = (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE);
- mHandler = new Handler();
updateVolumes();
return true;
@@ -274,11 +272,8 @@
return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
}
- private static String[] resolveDocumentProjection(String[] projection) {
- return projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION;
- }
-
- private String getDocIdForFile(File file) throws FileNotFoundException {
+ @Override
+ protected String getDocIdForFile(File file) throws FileNotFoundException {
return getDocIdForFileMaybeCreate(file, false);
}
@@ -344,11 +339,8 @@
return mostSpecificRoot;
}
- private File getFileForDocId(String docId) throws FileNotFoundException {
- return getFileForDocId(docId, false);
- }
-
- private File getFileForDocId(String docId, boolean visible) throws FileNotFoundException {
+ @Override
+ protected File getFileForDocId(String docId, boolean visible) throws FileNotFoundException {
RootInfo root = getRootFromDocId(docId);
return buildFile(root, docId, visible);
}
@@ -393,48 +385,9 @@
return target;
}
- private void includeFile(MatrixCursor result, String docId, File file)
- throws FileNotFoundException {
- if (docId == null) {
- docId = getDocIdForFile(file);
- } else {
- file = getFileForDocId(docId);
- }
-
- int flags = 0;
-
- if (file.canWrite()) {
- if (file.isDirectory()) {
- flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
- flags |= Document.FLAG_SUPPORTS_DELETE;
- flags |= Document.FLAG_SUPPORTS_RENAME;
- flags |= Document.FLAG_SUPPORTS_MOVE;
- } else {
- flags |= Document.FLAG_SUPPORTS_WRITE;
- flags |= Document.FLAG_SUPPORTS_DELETE;
- flags |= Document.FLAG_SUPPORTS_RENAME;
- flags |= Document.FLAG_SUPPORTS_MOVE;
- }
- }
-
- final String mimeType = getTypeForFile(file);
- final String displayName = file.getName();
- if (mimeType.startsWith("image/")) {
- flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
- }
-
- final RowBuilder row = result.newRow();
- row.add(Document.COLUMN_DOCUMENT_ID, docId);
- row.add(Document.COLUMN_DISPLAY_NAME, displayName);
- row.add(Document.COLUMN_SIZE, file.length());
- row.add(Document.COLUMN_MIME_TYPE, mimeType);
- row.add(Document.COLUMN_FLAGS, flags);
-
- // Only publish dates reasonably after epoch
- long lastModified = file.lastModified();
- if (lastModified > 31536000000L) {
- row.add(Document.COLUMN_LAST_MODIFIED, lastModified);
- }
+ @Override
+ protected Uri buildNotificationUri(String docId) {
+ return DocumentsContract.buildChildDocumentsUri(AUTHORITY, docId);
}
@Override
@@ -455,22 +408,8 @@
}
@Override
- public boolean isChildDocument(String parentDocId, String docId) {
- try {
- final File parent = getFileForDocId(parentDocId).getCanonicalFile();
- final File doc = getFileForDocId(docId).getCanonicalFile();
- return FileUtils.contains(parent, doc);
- } catch (IOException e) {
- throw new IllegalArgumentException(
- "Failed to determine if " + docId + " is child of " + parentDocId + ": " + e);
- }
- }
-
- @Override
public Path findDocumentPath(String childDocId, @Nullable String parentDocId)
throws FileNotFoundException {
- LinkedList<String> path = new LinkedList<>();
-
final Pair<RootInfo, File> resolvedDocId = resolveDocId(childDocId, false);
final RootInfo root = resolvedDocId.first;
File child = resolvedDocId.second;
@@ -479,49 +418,7 @@
? root.path
: getFileForDocId(parentDocId);
- if (!child.exists()) {
- throw new FileNotFoundException(childDocId + " is not found.");
- }
-
- if (!child.getAbsolutePath().startsWith(parent.getAbsolutePath())) {
- throw new FileNotFoundException(childDocId + " is not found under " + parentDocId);
- }
-
- while (child != null && child.getAbsolutePath().startsWith(parent.getAbsolutePath())) {
- path.addFirst(getDocIdForFile(child));
-
- child = child.getParentFile();
- }
-
- return new Path(parentDocId == null ? root.rootId : null, path);
- }
-
- @Override
- public String createDocument(String docId, String mimeType, String displayName)
- throws FileNotFoundException {
- displayName = FileUtils.buildValidFatFilename(displayName);
-
- final File parent = getFileForDocId(docId);
- if (!parent.isDirectory()) {
- throw new IllegalArgumentException("Parent document isn't a directory");
- }
-
- final File file = FileUtils.buildUniqueFile(parent, mimeType, displayName);
- if (Document.MIME_TYPE_DIR.equals(mimeType)) {
- if (!file.mkdir()) {
- throw new IllegalStateException("Failed to mkdir " + file);
- }
- } else {
- try {
- if (!file.createNewFile()) {
- throw new IllegalStateException("Failed to touch " + file);
- }
- } catch (IOException e) {
- throw new IllegalStateException("Failed to touch " + file + ": " + e);
- }
- }
-
- return getDocIdForFile(file);
+ return new Path(parentDocId == null ? root.rootId : null, findDocumentPath(parent, child));
}
private Uri getDocumentUri(String path, List<UriPermission> accessUriPermissions)
@@ -587,120 +484,14 @@
}
@Override
- public String renameDocument(String docId, String displayName) throws FileNotFoundException {
- // Since this provider treats renames as generating a completely new
- // docId, we're okay with letting the MIME type change.
- displayName = FileUtils.buildValidFatFilename(displayName);
-
- final File before = getFileForDocId(docId);
- final File after = FileUtils.buildUniqueFile(before.getParentFile(), displayName);
- if (!before.renameTo(after)) {
- throw new IllegalStateException("Failed to rename to " + after);
- }
- final String afterDocId = getDocIdForFile(after);
- if (!TextUtils.equals(docId, afterDocId)) {
- return afterDocId;
- } else {
- return null;
- }
- }
-
- @Override
- public void deleteDocument(String docId) throws FileNotFoundException {
- final File file = getFileForDocId(docId);
- final File visibleFile = getFileForDocId(docId, true);
-
- final boolean isDirectory = file.isDirectory();
- if (isDirectory) {
- FileUtils.deleteContents(file);
- }
- if (!file.delete()) {
- throw new IllegalStateException("Failed to delete " + file);
- }
-
- if (visibleFile != null) {
- final ContentResolver resolver = getContext().getContentResolver();
- final Uri externalUri = MediaStore.Files.getContentUri("external");
-
- // Remove media store entries for any files inside this directory, using
- // path prefix match. Logic borrowed from MtpDatabase.
- if (isDirectory) {
- final String path = visibleFile.getAbsolutePath() + "/";
- resolver.delete(externalUri,
- "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)",
- new String[] { path + "%", Integer.toString(path.length()), path });
- }
-
- // Remove media store entry for this exact file.
- final String path = visibleFile.getAbsolutePath();
- resolver.delete(externalUri,
- "_data LIKE ?1 AND lower(_data)=lower(?2)",
- new String[] { path, path });
- }
- }
-
- @Override
- public String moveDocument(String sourceDocumentId, String sourceParentDocumentId,
- String targetParentDocumentId)
- throws FileNotFoundException {
- final File before = getFileForDocId(sourceDocumentId);
- final File after = new File(getFileForDocId(targetParentDocumentId), before.getName());
-
- if (after.exists()) {
- throw new IllegalStateException("Already exists " + after);
- }
- if (!before.renameTo(after)) {
- throw new IllegalStateException("Failed to move to " + after);
- }
- return getDocIdForFile(after);
- }
-
- @Override
- public Cursor queryDocument(String documentId, String[] projection)
- throws FileNotFoundException {
- final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
- includeFile(result, documentId, null);
- return result;
- }
-
- @Override
- public Cursor queryChildDocuments(
- String parentDocumentId, String[] projection, String sortOrder)
- throws FileNotFoundException {
- final File parent = getFileForDocId(parentDocumentId);
- final MatrixCursor result = new DirectoryCursor(
- resolveDocumentProjection(projection), parentDocumentId, parent);
- for (File file : parent.listFiles()) {
- includeFile(result, null, file);
- }
- return result;
- }
-
- @Override
public Cursor querySearchDocuments(String rootId, String query, String[] projection)
throws FileNotFoundException {
- final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
-
- query = query.toLowerCase();
final File parent;
synchronized (mRootsLock) {
parent = mRoots.get(rootId).path;
}
- final LinkedList<File> pending = new LinkedList<>();
- pending.add(parent);
- while (!pending.isEmpty() && result.getCount() < 24) {
- final File file = pending.removeFirst();
- if (file.isDirectory()) {
- for (File child : file.listFiles()) {
- pending.add(child);
- }
- }
- if (file.getName().toLowerCase().contains(query)) {
- includeFile(result, null, file);
- }
- }
- return result;
+ return querySearchDocuments(parent, query, projection, Collections.emptySet());
}
@Override
@@ -722,48 +513,6 @@
}
@Override
- public String getDocumentType(String documentId) throws FileNotFoundException {
- final File file = getFileForDocId(documentId);
- return getTypeForFile(file);
- }
-
- @Override
- public ParcelFileDescriptor openDocument(
- String documentId, String mode, CancellationSignal signal)
- throws FileNotFoundException {
- final File file = getFileForDocId(documentId);
- final File visibleFile = getFileForDocId(documentId, true);
-
- final int pfdMode = ParcelFileDescriptor.parseMode(mode);
- if (pfdMode == ParcelFileDescriptor.MODE_READ_ONLY || visibleFile == null) {
- return ParcelFileDescriptor.open(file, pfdMode);
- } else {
- try {
- // When finished writing, kick off media scanner
- return ParcelFileDescriptor.open(file, pfdMode, mHandler, new OnCloseListener() {
- @Override
- public void onClose(IOException e) {
- final Intent intent = new Intent(
- Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
- intent.setData(Uri.fromFile(visibleFile));
- getContext().sendBroadcast(intent);
- }
- });
- } catch (IOException e) {
- throw new FileNotFoundException("Failed to open for writing: " + e);
- }
- }
- }
-
- @Override
- public AssetFileDescriptor openDocumentThumbnail(
- String documentId, Point sizeHint, CancellationSignal signal)
- throws FileNotFoundException {
- final File file = getFileForDocId(documentId);
- return DocumentsContract.openImageThumbnail(file);
- }
-
- @Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
synchronized (mRootsLock) {
@@ -826,107 +575,4 @@
}
return bundle;
}
-
- private static String getTypeForFile(File file) {
- if (file.isDirectory()) {
- return Document.MIME_TYPE_DIR;
- } else {
- return getTypeForName(file.getName());
- }
- }
-
- private static String getTypeForName(String name) {
- final int lastDot = name.lastIndexOf('.');
- if (lastDot >= 0) {
- final String extension = name.substring(lastDot + 1).toLowerCase();
- final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
- if (mime != null) {
- return mime;
- }
- }
-
- return "application/octet-stream";
- }
-
- private void startObserving(File file, Uri notifyUri) {
- synchronized (mObservers) {
- DirectoryObserver observer = mObservers.get(file);
- if (observer == null) {
- observer = new DirectoryObserver(
- file, getContext().getContentResolver(), notifyUri);
- observer.startWatching();
- mObservers.put(file, observer);
- }
- observer.mRefCount++;
-
- if (LOG_INOTIFY) Log.d(TAG, "after start: " + observer);
- }
- }
-
- private void stopObserving(File file) {
- synchronized (mObservers) {
- DirectoryObserver observer = mObservers.get(file);
- if (observer == null) return;
-
- observer.mRefCount--;
- if (observer.mRefCount == 0) {
- mObservers.remove(file);
- observer.stopWatching();
- }
-
- if (LOG_INOTIFY) Log.d(TAG, "after stop: " + observer);
- }
- }
-
- private static class DirectoryObserver extends FileObserver {
- private static final int NOTIFY_EVENTS = ATTRIB | CLOSE_WRITE | MOVED_FROM | MOVED_TO
- | CREATE | DELETE | DELETE_SELF | MOVE_SELF;
-
- private final File mFile;
- private final ContentResolver mResolver;
- private final Uri mNotifyUri;
-
- private int mRefCount = 0;
-
- public DirectoryObserver(File file, ContentResolver resolver, Uri notifyUri) {
- super(file.getAbsolutePath(), NOTIFY_EVENTS);
- mFile = file;
- mResolver = resolver;
- mNotifyUri = notifyUri;
- }
-
- @Override
- public void onEvent(int event, String path) {
- if ((event & NOTIFY_EVENTS) != 0) {
- if (LOG_INOTIFY) Log.d(TAG, "onEvent() " + event + " at " + path);
- mResolver.notifyChange(mNotifyUri, null, false);
- }
- }
-
- @Override
- public String toString() {
- return "DirectoryObserver{file=" + mFile.getAbsolutePath() + ", ref=" + mRefCount + "}";
- }
- }
-
- private class DirectoryCursor extends MatrixCursor {
- private final File mFile;
-
- public DirectoryCursor(String[] columnNames, String docId, File file) {
- super(columnNames);
-
- final Uri notifyUri = DocumentsContract.buildChildDocumentsUri(
- AUTHORITY, docId);
- setNotificationUri(getContext().getContentResolver(), notifyUri);
-
- mFile = file;
- startObserving(mFile, notifyUri);
- }
-
- @Override
- public void close() {
- super.close();
- stopObserving(mFile);
- }
- }
}
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index f36167e..36465a1 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -79,7 +79,7 @@
</plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> प्रिंट हो रहा है"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> रद्द हो रहा है"</string>
- <string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिंटर त्रुटि <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
+ <string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिंटर गड़बड़ी <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"प्रिंटर अवरोधित <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancel" msgid="4373674107267141885">"अभी नहीं"</string>
<string name="restart" msgid="2472034227037808749">"पुन: आरंभ करें"</string>
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index d207c35..9ff22c7 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -538,7 +538,7 @@
<item>100</item>
</array>
<array name="batterymeter_color_values">
- <item>@*android:color/battery_saver_mode_color</item>
+ <item>?android:attr/colorError</item>
<item>@android:color/white</item>
</array>
<array name="batterymeter_bolt_points">
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 961d0e5..f77d466 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -537,6 +537,11 @@
<string name="wait_for_debugger_summary">Debugged application waits for debugger to
attach before executing</string>
+ <!-- UI debug setting: title for Telephonymonitor switch [CHAR LIMIT=50] -->
+ <string name="telephony_monitor_switch">Telephony Monitor</string>
+ <!-- UI debug setting: summary for switch of Telephonymonitor [CHAR LIMIT=500] -->
+ <string name="telephony_monitor_switch_summary">TelephonyMonitor will collect logs when it detects a problem with telephony/modem functionality and prompt notification to user to file a bug</string>
+
<!-- Preference category for input debugging development settings. [CHAR LIMIT=25] -->
<string name="debug_input_category">Input</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index 99d7f1e..49fc2ea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -16,6 +16,11 @@
package com.android.settingslib;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
+import static android.app.admin.DevicePolicyManager.PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.AppGlobals;
import android.app.admin.DevicePolicyManager;
@@ -29,6 +34,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
import android.text.Spanned;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
@@ -108,47 +114,68 @@
}
/**
- * Checks if keyguard features are disabled by policy.
+ * Checks whether keyguard features are disabled by policy.
*
- * @param keyguardFeatures Could be any of keyguard features that can be
+ * @param context {@link Context} for the calling user.
+ *
+ * @param keyguardFeatures Any one of keyguard features that can be
* disabled by {@link android.app.admin.DevicePolicyManager#setKeyguardDisabledFeatures}.
+ *
+ * @param userId User to check enforced admin status for.
+ *
* @return EnforcedAdmin Object containing the enforced admin component and admin user details,
* or {@code null} If the notification features are not disabled. If the restriction is set by
* multiple admins, then the admin component will be set to {@code null} and userId to
* {@link UserHandle#USER_NULL}.
*/
public static EnforcedAdmin checkIfKeyguardFeaturesDisabled(Context context,
- int keyguardFeatures, int userId) {
- final LockSettingCheck check =
- (DevicePolicyManager dpm, ComponentName admin, @UserIdInt int checkUser) ->
- (dpm.getKeyguardDisabledFeatures(admin, checkUser) & keyguardFeatures) != 0;
+ int keyguardFeatures, final @UserIdInt int userId) {
+ final LockSettingCheck check = (dpm, admin, checkUser) -> {
+ int effectiveFeatures = dpm.getKeyguardDisabledFeatures(admin, checkUser);
+ if (checkUser != userId) {
+ effectiveFeatures &= PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
+ }
+ return (effectiveFeatures & keyguardFeatures) != KEYGUARD_DISABLE_FEATURES_NONE;
+ };
+ if (UserManager.get(context).getUserInfo(userId).isManagedProfile()) {
+ DevicePolicyManager dpm =
+ (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ return findEnforcedAdmin(dpm.getActiveAdminsAsUser(userId), dpm, userId, check);
+ }
+ return checkForLockSetting(context, userId, check);
+ }
- final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
- Context.DEVICE_POLICY_SERVICE);
- if (dpm == null) {
+ /**
+ * Filter a set of device admins based on a predicate {@code check}. This is equivalent to
+ * {@code admins.stream().filter(check).map(x → new EnforcedAdmin(admin, userId)} except it's
+ * returning a zero/one/many-type thing.
+ *
+ * @param admins set of candidate device admins identified by {@link ComponentName}.
+ * @param userId user to create the resultant {@link EnforcedAdmin} as.
+ * @param check filter predicate.
+ *
+ * @return {@code null} if none of the {@param admins} match.
+ * An {@link EnforcedAdmin} if exactly one of the admins matches.
+ * Otherwise, {@link EnforcedAdmin#MULTIPLE_ENFORCED_ADMIN} for multiple matches.
+ */
+ @Nullable
+ private static EnforcedAdmin findEnforcedAdmin(@Nullable List<ComponentName> admins,
+ @NonNull DevicePolicyManager dpm, @UserIdInt int userId,
+ @NonNull LockSettingCheck check) {
+ if (admins == null) {
return null;
}
-
- final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
- if (um.getUserInfo(userId).isManagedProfile()) {
- final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId);
- if (admins == null) {
- return null;
- }
- EnforcedAdmin enforcedAdmin = null;
- for (ComponentName admin : admins) {
- if (check.isEnforcing(dpm, admin, userId)) {
- if (enforcedAdmin == null) {
- enforcedAdmin = new EnforcedAdmin(admin, userId);
- } else {
- return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
- }
+ EnforcedAdmin enforcedAdmin = null;
+ for (ComponentName admin : admins) {
+ if (check.isEnforcing(dpm, admin, userId)) {
+ if (enforcedAdmin == null) {
+ enforcedAdmin = new EnforcedAdmin(admin, userId);
+ } else {
+ return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
}
}
- return enforcedAdmin;
- } else {
- return checkForLockSetting(context, userId, check);
}
+ return enforcedAdmin;
}
public static EnforcedAdmin checkIfUninstallBlocked(Context context,
@@ -361,7 +388,7 @@
}
LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
- if (lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
+ if (sProxy.isSeparateProfileChallengeEnabled(lockPatternUtils, userId)) {
// userId is managed profile and has a separate challenge, only consider
// the admins in that user.
final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId);
@@ -428,7 +455,7 @@
if (userInfo.isManagedProfile()) {
// If userInfo.id is a managed profile, we also need to look at
// the policies set on the parent.
- final DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
+ DevicePolicyManager parentDpm = sProxy.getParentProfileInstance(dpm, userInfo);
if (parentDpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
if (enforcedAdmin == null) {
enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
@@ -448,8 +475,9 @@
/**
* Checks whether any of the user's profiles enforce the lock setting. A managed profile is only
- * included if it does not have a separate challenege but the settings for it's parent (i.e. the
- * user being checked) are always included.
+ * included if it does not have a separate challenge.
+ *
+ * The user identified by {@param userId} is always included.
*/
private static EnforcedAdmin checkForLockSetting(
Context context, @UserIdInt int userId, LockSettingCheck check) {
@@ -468,7 +496,7 @@
continue;
}
final boolean isSeparateProfileChallengeEnabled =
- lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
+ sProxy.isSeparateProfileChallengeEnabled(lockPatternUtils, userInfo.id);
for (ComponentName admin : admins) {
if (!isSeparateProfileChallengeEnabled) {
if (check.isEnforcing(dpm, admin, userInfo.id)) {
@@ -487,7 +515,7 @@
if (userInfo.isManagedProfile()) {
// If userInfo.id is a managed profile, we also need to look at
// the policies set on the parent.
- final DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
+ DevicePolicyManager parentDpm = sProxy.getParentProfileInstance(dpm, userInfo);
if (check.isEnforcing(parentDpm, admin, userInfo.id)) {
if (enforcedAdmin == null) {
enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
@@ -733,4 +761,23 @@
other.userId = userId;
}
}
+
+ /**
+ * Static {@link LockPatternUtils} and {@link DevicePolicyManager} wrapper for testing purposes.
+ * {@link LockPatternUtils} is an internal API not supported by robolectric.
+ * {@link DevicePolicyManager} has a {@code getProfileParent} not yet suppored by robolectric.
+ */
+ @VisibleForTesting
+ static Proxy sProxy = new Proxy();
+
+ @VisibleForTesting
+ static class Proxy {
+ public boolean isSeparateProfileChallengeEnabled(LockPatternUtils utils, int userHandle) {
+ return utils.isSeparateProfileChallengeEnabled(userHandle);
+ }
+
+ public DevicePolicyManager getParentProfileInstance(DevicePolicyManager dpm, UserInfo ui) {
+ return dpm.getParentProfileInstance(ui);
+ }
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 7a4514a..7e7b391 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -184,10 +184,7 @@
@ColorInt
public static int getColorError(Context context) {
- TypedArray ta = context.obtainStyledAttributes(new int[]{android.R.attr.textColorError});
- @ColorInt int colorError = ta.getColor(0, 0);
- ta.recycle();
- return colorError;
+ return getColorAttr(context, android.R.attr.colorError);
}
@ColorInt
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
index fd2e7ca..6764a6b 100755
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
@@ -29,7 +29,8 @@
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
-import android.provider.Settings;
+import android.util.TypedValue;
+
import com.android.settingslib.R;
import com.android.settingslib.Utils;
@@ -97,9 +98,13 @@
final int N = levels.length();
mColors = new int[2 * N];
- for (int i = 0; i < N; i++) {
+ for (int i=0; i < N; i++) {
mColors[2 * i] = levels.getInt(i, 0);
- mColors[2 * i + 1] = colors.getColor(i, 0);
+ if (colors.getType(i) == TypedValue.TYPE_ATTRIBUTE) {
+ mColors[2 * i + 1] = Utils.getColorAttr(context, colors.getResourceId(i, 0));
+ } else {
+ mColors[2 * i + 1] = colors.getColor(i, 0);
+ }
}
levels.recycle();
colors.recycle();
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 2dcbf90..6fe581e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -89,15 +89,15 @@
new ConcurrentHashMap<String, ScanResult>(32);
private static final long MAX_SCAN_RESULT_AGE_MS = 15000;
- private static final String KEY_NETWORKINFO = "key_networkinfo";
- private static final String KEY_WIFIINFO = "key_wifiinfo";
- private static final String KEY_SCANRESULT = "key_scanresult";
- private static final String KEY_SSID = "key_ssid";
- private static final String KEY_SECURITY = "key_security";
- private static final String KEY_PSKTYPE = "key_psktype";
- private static final String KEY_SCANRESULTCACHE = "key_scanresultcache";
- private static final String KEY_CONFIG = "key_config";
- private static final AtomicInteger sLastId = new AtomicInteger(0);
+ static final String KEY_NETWORKINFO = "key_networkinfo";
+ static final String KEY_WIFIINFO = "key_wifiinfo";
+ static final String KEY_SCANRESULT = "key_scanresult";
+ static final String KEY_SSID = "key_ssid";
+ static final String KEY_SECURITY = "key_security";
+ static final String KEY_PSKTYPE = "key_psktype";
+ static final String KEY_SCANRESULTCACHE = "key_scanresultcache";
+ static final String KEY_CONFIG = "key_config";
+ static final AtomicInteger sLastId = new AtomicInteger(0);
/**
* These values are matched in string arrays -- changes must be kept in sync
@@ -114,6 +114,8 @@
public static final int SIGNAL_LEVELS = 4;
+ static final int UNREACHABLE_RSSI = Integer.MAX_VALUE;
+
private final Context mContext;
private String ssid;
@@ -125,7 +127,7 @@
private WifiConfiguration mConfig;
- private int mRssi = Integer.MAX_VALUE;
+ private int mRssi = UNREACHABLE_RSSI;
private long mSeen = 0;
private WifiInfo mInfo;
@@ -214,6 +216,21 @@
this.mRankingScore = that.mRankingScore;
}
+ /**
+ * Returns a negative integer, zero, or a positive integer if this AccessPoint is less than,
+ * equal to, or greater than the other AccessPoint.
+ *
+ * Sort order rules for AccessPoints:
+ * 1. Active before inactive
+ * 2. Reachable before unreachable
+ * 3. Saved before unsaved
+ * 4. (Internal only) Network ranking score
+ * 5. Stronger signal before weaker signal
+ * 6. SSID alphabetically
+ *
+ * Note that AccessPoints with a signal are usually also Reachable,
+ * and will thus appear before unreachable saved AccessPoints.
+ */
@Override
public int compareTo(@NonNull AccessPoint other) {
// Active one goes first.
@@ -221,18 +238,16 @@
if (!isActive() && other.isActive()) return 1;
// Reachable one goes before unreachable one.
- if (mRssi != Integer.MAX_VALUE && other.mRssi == Integer.MAX_VALUE) return -1;
- if (mRssi == Integer.MAX_VALUE && other.mRssi != Integer.MAX_VALUE) return 1;
+ if (isReachable() && !other.isReachable()) return -1;
+ if (!isReachable() && other.isReachable()) return 1;
// Configured (saved) one goes before unconfigured one.
- if (networkId != WifiConfiguration.INVALID_NETWORK_ID
- && other.networkId == WifiConfiguration.INVALID_NETWORK_ID) return -1;
- if (networkId == WifiConfiguration.INVALID_NETWORK_ID
- && other.networkId != WifiConfiguration.INVALID_NETWORK_ID) return 1;
+ if (isSaved() && !other.isSaved()) return -1;
+ if (!isSaved() && other.isSaved()) return 1;
// Higher scores go before lower scores
- if (mRankingScore != other.mRankingScore) {
- return (mRankingScore > other.mRankingScore) ? -1 : 1;
+ if (getRankingScore() != other.getRankingScore()) {
+ return (getRankingScore() > other.getRankingScore()) ? -1 : 1;
}
// Sort by signal strength, bucketed by level
@@ -242,7 +257,7 @@
return difference;
}
// Sort by ssid.
- return ssid.compareToIgnoreCase(other.ssid);
+ return getSsidStr().compareToIgnoreCase(other.getSsidStr());
}
@Override
@@ -265,6 +280,9 @@
public String toString() {
StringBuilder builder = new StringBuilder().append("AccessPoint(")
.append(ssid);
+ if (bssid != null) {
+ builder.append(":").append(bssid);
+ }
if (isSaved()) {
builder.append(',').append("saved");
}
@@ -280,6 +298,7 @@
if (security != SECURITY_NONE) {
builder.append(',').append(securityToString(security, pskType));
}
+ builder.append(",level=").append(getLevel());
builder.append(",rankingScore=").append(mRankingScore);
builder.append(",badge=").append(mBadge);
@@ -351,7 +370,7 @@
}
public int getLevel() {
- if (mRssi == Integer.MAX_VALUE) {
+ if (!isReachable()) {
return -1;
}
return WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
@@ -527,7 +546,7 @@
}
} else if (config != null && config.getNetworkSelectionStatus().isNotRecommended()) {
summary.append(mContext.getString(R.string.wifi_disabled_by_recommendation_provider));
- } else if (mRssi == Integer.MAX_VALUE) { // Wifi out of range
+ } else if (!isReachable()) { // Wifi out of range
summary.append(mContext.getString(R.string.wifi_not_in_range));
} else { // In range, not disabled.
if (config != null) { // Is saved network
@@ -870,6 +889,11 @@
return mBadge;
}
+ /** Return true if the current RSSI is reachable, and false otherwise. */
+ boolean isReachable() {
+ return mRssi != UNREACHABLE_RSSI;
+ }
+
public static String getSummary(Context context, String ssid, DetailedState state,
boolean isEphemeral, String passpointProvider) {
if (state == DetailedState.CONNECTED && ssid == null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 11bcdca..8421c2c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -271,7 +271,6 @@
if (mWifiManager.isWifiEnabled()) {
mScanner.resume();
}
- mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
}
/**
@@ -715,9 +714,9 @@
mMainHandler.sendEmptyMessage(MainHandler.MSG_CONNECTED_CHANGED);
- mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
mWorkHandler.obtainMessage(WorkHandler.MSG_UPDATE_NETWORK_INFO, info)
.sendToTarget();
+ mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
}
}
};
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 6481f4d..ec0190c 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -15,9 +15,8 @@
*/
package com.android.settingslib.wifi;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import android.content.Context;
import android.net.ConnectivityManager;
@@ -39,6 +38,7 @@
import org.junit.runner.RunWith;
import java.util.ArrayList;
+import java.util.Collections;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -59,12 +59,12 @@
final AccessPoint ap = new AccessPoint(InstrumentationRegistry.getTargetContext(), bundle);
final CharSequence ssid = ap.getSsid();
- assertTrue(ssid instanceof SpannableString);
+ assertThat(ssid instanceof SpannableString).isTrue();
TtsSpan[] spans = ((SpannableString) ssid).getSpans(0, TEST_SSID.length(), TtsSpan.class);
- assertEquals(1, spans.length);
- assertEquals(TtsSpan.TYPE_TELEPHONE, spans[0].getType());
+ assertThat(spans.length).isEqualTo(1);
+ assertThat(spans[0].getType()).isEqualTo(TtsSpan.TYPE_TELEPHONE);
}
@Test
@@ -80,11 +80,11 @@
originalAccessPoint.update(configuration, wifiInfo, networkInfo);
AccessPoint copy = new AccessPoint(mContext, originalAccessPoint);
- assertEquals(originalAccessPoint.getSsid().toString(), copy.getSsid().toString());
- assertEquals(originalAccessPoint.getBssid(), copy.getBssid());
- assertSame(originalAccessPoint.getConfig(), copy.getConfig());
- assertEquals(originalAccessPoint.getSecurity(), copy.getSecurity());
- assertTrue(originalAccessPoint.compareTo(copy) == 0);
+ assertThat(originalAccessPoint.getSsid().toString()).isEqualTo(copy.getSsid().toString());
+ assertThat(originalAccessPoint.getBssid()).isEqualTo(copy.getBssid());
+ assertThat(originalAccessPoint.getConfig()).isEqualTo(copy.getConfig());
+ assertThat(originalAccessPoint.getSecurity()).isEqualTo(copy.getSecurity());
+ assertThat(originalAccessPoint.compareTo(copy) == 0).isTrue();
}
@Test
@@ -101,11 +101,93 @@
bundle.putParcelableArrayList("key_scanresultcache", scanResults);
AccessPoint original = new AccessPoint(mContext, bundle);
- assertEquals(4, original.getRssi());
+ assertThat(original.getRssi()).isEqualTo(4);
AccessPoint copy = new AccessPoint(mContext, createWifiConfiguration());
- assertEquals(Integer.MIN_VALUE, copy.getRssi());
+ assertThat(copy.getRssi()).isEqualTo(Integer.MIN_VALUE);
copy.copyFrom(original);
- assertEquals(original.getRssi(), copy.getRssi());
+ assertThat(original.getRssi()).isEqualTo(copy.getRssi());
+ }
+
+ @Test
+ public void testCompareTo_GivesActiveBeforeInactive() {
+ AccessPoint activeAp = new TestAccessPointBuilder(mContext).setActive(true).build();
+ AccessPoint inactiveAp = new TestAccessPointBuilder(mContext).setActive(false).build();
+
+ assertSortingWorks(activeAp, inactiveAp);
+ }
+
+ @Test
+ public void testCompareTo_GivesReachableBeforeUnreachable() {
+ AccessPoint nearAp = new TestAccessPointBuilder(mContext).setReachable(true).build();
+ AccessPoint farAp = new TestAccessPointBuilder(mContext).setReachable(false).build();
+
+ assertSortingWorks(nearAp, farAp);
+ }
+
+ @Test
+ public void testCompareTo_GivesSavedBeforeUnsaved() {
+ AccessPoint savedAp = new TestAccessPointBuilder(mContext).setSaved(true).build();
+ AccessPoint notSavedAp = new TestAccessPointBuilder(mContext).setSaved(false).build();
+
+ assertSortingWorks(savedAp, notSavedAp);
+ }
+
+ //TODO: add tests for mRankingScore sort order if ranking is exposed
+
+ @Test
+ public void testCompareTo_GivesHighLevelBeforeLowLevel() {
+ final int highLevel = AccessPoint.SIGNAL_LEVELS - 1;
+ final int lowLevel = 1;
+ assertThat(highLevel).isGreaterThan(lowLevel);
+
+ AccessPoint strongAp = new TestAccessPointBuilder(mContext).setLevel(highLevel).build();
+ AccessPoint weakAp = new TestAccessPointBuilder(mContext).setLevel(lowLevel).build();
+
+ assertSortingWorks(strongAp, weakAp);
+ }
+
+ @Test
+ public void testCompareTo_GivesSsidAlphabetically() {
+
+ final String firstName = "AAAAAA";
+ final String secondName = "zzzzzz";
+
+ AccessPoint firstAp = new TestAccessPointBuilder(mContext).setSsid(firstName).build();
+ AccessPoint secondAp = new TestAccessPointBuilder(mContext).setSsid(secondName).build();
+
+ assertThat(firstAp.getSsidStr().compareToIgnoreCase(secondAp.getSsidStr()) < 0).isTrue();
+ assertSortingWorks(firstAp, secondAp);
+ }
+
+ @Test
+ public void testCompareTo_AllSortingRulesCombined() {
+
+ AccessPoint active = new TestAccessPointBuilder(mContext).setActive(true).build();
+ AccessPoint reachableAndMinLevel = new TestAccessPointBuilder(mContext)
+ .setReachable(true).build();
+ AccessPoint saved = new TestAccessPointBuilder(mContext).setSaved(true).build();
+ AccessPoint highLevelAndReachable = new TestAccessPointBuilder(mContext)
+ .setLevel(AccessPoint.SIGNAL_LEVELS - 1).build();
+ AccessPoint firstName = new TestAccessPointBuilder(mContext).setSsid("a").build();
+ AccessPoint lastname = new TestAccessPointBuilder(mContext).setSsid("z").build();
+
+ ArrayList<AccessPoint> points = new ArrayList<AccessPoint>();
+ points.add(lastname);
+ points.add(firstName);
+ points.add(highLevelAndReachable);
+ points.add(saved);
+ points.add(reachableAndMinLevel);
+ points.add(active);
+
+ Collections.sort(points);
+ assertThat(points.indexOf(active)).isLessThan(points.indexOf(reachableAndMinLevel));
+ assertThat(points.indexOf(reachableAndMinLevel)).isLessThan(points.indexOf(saved));
+ // note: the saved AP will not appear before highLevelAndReachable,
+ // because all APs with a signal level are reachable,
+ // and isReachable() takes higher sorting precedence than isSaved().
+ assertThat(points.indexOf(saved)).isLessThan(points.indexOf(firstName));
+ assertThat(points.indexOf(highLevelAndReachable)).isLessThan(points.indexOf(firstName));
+ assertThat(points.indexOf(firstName)).isLessThan(points.indexOf(lastname));
}
private WifiConfiguration createWifiConfiguration() {
@@ -115,4 +197,85 @@
configuration.networkId = 123;
return configuration;
}
+
+ /**
+ * Assert that the first AccessPoint appears after the second AccessPoint
+ * once sorting has been completed.
+ */
+ private void assertSortingWorks(AccessPoint first, AccessPoint second) {
+
+ ArrayList<AccessPoint> points = new ArrayList<AccessPoint>();
+
+ // add in reverse order so we can tell that sorting actually changed something
+ points.add(second);
+ points.add(first);
+ Collections.sort(points);
+ assertWithMessage(
+ String.format("After sorting: second AccessPoint should have higher array index "
+ + "than the first, but found indicies second '%s' and first '%s'.",
+ points.indexOf(second), points.indexOf(first)))
+ .that(points.indexOf(second)).isGreaterThan(points.indexOf(first));
+ }
+
+ @Test
+ public void testBuilder_setActive() {
+ AccessPoint activeAp = new TestAccessPointBuilder(mContext).setActive(true).build();
+ assertThat(activeAp.isActive()).isTrue();
+
+ AccessPoint inactiveAp = new TestAccessPointBuilder(mContext).setActive(false).build();
+ assertThat(inactiveAp.isActive()).isFalse();
+ }
+
+ @Test
+ public void testBuilder_setReachable() {
+ AccessPoint nearAp = new TestAccessPointBuilder(mContext).setReachable(true).build();
+ assertThat(nearAp.isReachable()).isTrue();
+
+ AccessPoint farAp = new TestAccessPointBuilder(mContext).setReachable(false).build();
+ assertThat(farAp.isReachable()).isFalse();
+ }
+
+ @Test
+ public void testBuilder_setSaved() {
+ AccessPoint savedAp = new TestAccessPointBuilder(mContext).setSaved(true).build();
+ assertThat(savedAp.isSaved()).isTrue();
+
+ AccessPoint newAp = new TestAccessPointBuilder(mContext).setSaved(false).build();
+ assertThat(newAp.isSaved()).isFalse();
+ }
+
+ @Test
+ public void testBuilder_setLevel() {
+ AccessPoint testAp;
+
+ for (int i = 0; i < AccessPoint.SIGNAL_LEVELS; i++) {
+ testAp = new TestAccessPointBuilder(mContext).setLevel(i).build();
+ assertThat(testAp.getLevel()).isEqualTo(i);
+ }
+
+ // numbers larger than the max level should be set to max
+ testAp = new TestAccessPointBuilder(mContext).setLevel(AccessPoint.SIGNAL_LEVELS).build();
+ assertThat(testAp.getLevel()).isEqualTo(AccessPoint.SIGNAL_LEVELS - 1);
+
+ // numbers less than 0 should give level 0
+ testAp = new TestAccessPointBuilder(mContext).setLevel(-100).build();
+ assertThat(testAp.getLevel()).isEqualTo(0);
+ }
+
+ @Test
+ public void testBuilder_settingReachableAfterLevelDoesNotAffectLevel() {
+ int level = 1;
+ assertThat(level).isLessThan(AccessPoint.SIGNAL_LEVELS - 1);
+
+ AccessPoint testAp =
+ new TestAccessPointBuilder(mContext).setLevel(level).setReachable(true).build();
+ assertThat(testAp.getLevel()).isEqualTo(level);
+ }
+
+ @Test
+ public void testBuilder_setSsid() {
+ String name = "AmazingSsid!";
+ AccessPoint namedAp = new TestAccessPointBuilder(mContext).setSsid(name).build();
+ assertThat(namedAp.getSsidStr()).isEqualTo(name);
+ }
}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/TestAccessPointBuilder.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
new file mode 100644
index 0000000..665c439
--- /dev/null
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.wifi;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiConfiguration;
+import android.os.Bundle;
+
+/**
+* Build and return a valid AccessPoint.
+*
+* Only intended for testing the AccessPoint class;
+* AccessPoints were designed to only be populated
+* by the mechanisms of scan results and wifi configurations.
+*/
+public class TestAccessPointBuilder {
+ // match the private values in WifiManager
+ private static final int MIN_RSSI = -100;
+ private static final int MAX_RSSI = -55;
+
+ // set some sensible defaults
+ private int mRssi = AccessPoint.UNREACHABLE_RSSI;
+ private int networkId = WifiConfiguration.INVALID_NETWORK_ID;
+ private String ssid = "TestSsid";
+ private NetworkInfo mNetworkInfo = null;
+
+ Context mContext;
+
+ public TestAccessPointBuilder(Context context) {
+ mContext = context;
+ }
+
+ public AccessPoint build() {
+ Bundle bundle = new Bundle();
+
+ WifiConfiguration wifiConig = new WifiConfiguration();
+ wifiConig.networkId = networkId;
+
+ bundle.putString(AccessPoint.KEY_SSID, ssid);
+ bundle.putParcelable(AccessPoint.KEY_CONFIG, wifiConig);
+ bundle.putParcelable(AccessPoint.KEY_NETWORKINFO, mNetworkInfo);
+ AccessPoint ap = new AccessPoint(mContext, bundle);
+ ap.setRssi(mRssi);
+ return ap;
+ }
+
+ public TestAccessPointBuilder setActive(boolean active) {
+ if (active) {
+ mNetworkInfo = new NetworkInfo(
+ ConnectivityManager.TYPE_DUMMY,
+ ConnectivityManager.TYPE_DUMMY,
+ "TestNetwork",
+ "TestNetwork");
+ } else {
+ mNetworkInfo = null;
+ }
+ return this;
+ }
+
+ /**
+ * Set the signal level.
+ * Side effect: if this AccessPoint was previously unreachable,
+ * setting the level will also make it reachable.
+ */
+ public TestAccessPointBuilder setLevel(int level) {
+ int outputRange = AccessPoint.SIGNAL_LEVELS - 1;
+
+ if (level > outputRange) {
+ level = outputRange;
+ } else if (level < 0) {
+ level = 0;
+ }
+
+ int inputRange = MAX_RSSI - MIN_RSSI;
+
+ // calculate the rssi required to get the level we want.
+ // this is a rearrangement of the formula from WifiManager.calculateSignalLevel()
+ mRssi = (int)((float)(level * inputRange) / (float)outputRange) + MIN_RSSI;
+ return this;
+ }
+
+ /**
+ * Set whether the AccessPoint is reachable.
+ * Side effect: if the signal level was not previously set,
+ * making an AccessPoint reachable will set the signal to the minimum level.
+ */
+ public TestAccessPointBuilder setReachable(boolean reachable) {
+ if (reachable) {
+ // only override the mRssi if it hasn't been set yet
+ if (mRssi == AccessPoint.UNREACHABLE_RSSI) {
+ mRssi = MIN_RSSI;
+ }
+ } else {
+ mRssi = AccessPoint.UNREACHABLE_RSSI;
+ }
+ return this;
+ }
+
+ public TestAccessPointBuilder setSaved(boolean saved){
+ if (saved) {
+ networkId = 1;
+ } else {
+ networkId = WifiConfiguration.INVALID_NETWORK_ID;
+ }
+ return this;
+ }
+
+ public TestAccessPointBuilder setSsid(String newSsid) {
+ ssid = newSsid;
+ return this;
+ }
+}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index 2018c13..e100884 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -15,6 +15,8 @@
*/
package com.android.settingslib.wifi;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -28,6 +30,7 @@
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkBadging;
+import android.net.NetworkInfo;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
import android.net.ScoredNetwork;
@@ -35,6 +38,7 @@
import android.net.WifiKey;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkScoreCache;
import android.net.wifi.WifiSsid;
@@ -68,6 +72,8 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+// TODO(sghuman): Change these to robolectric tests b/35766684.
+
@SmallTest
@RunWith(AndroidJUnit4.class)
public class WifiTrackerTest {
@@ -115,9 +121,10 @@
@Before
public void setUp() {
- mContext = InstrumentationRegistry.getTargetContext();
MockitoAnnotations.initMocks(this);
+ mContext = InstrumentationRegistry.getTargetContext();
+
mWorkerThread = new HandlerThread("TestHandlerWorkerThread");
mWorkerThread.start();
mLooper = mWorkerThread.getLooper();
@@ -221,9 +228,15 @@
SystemClock.elapsedRealtime() * 1000 /* microsecond timestamp */);
}
- private WifiTracker createTrackerAndInjectInitialScanResults() throws InterruptedException {
+ private WifiTracker createTrackerWithImmediateBroadcastsAndInjectInitialScanResults(
+ Intent ... intents)
+ throws InterruptedException {
WifiTracker tracker = createMockedWifiTracker();
+
startTracking(tracker);
+ for (Intent intent : intents) {
+ tracker.mReceiver.onReceive(mContext, intent);
+ }
mAccessPointsChangedLatch = new CountDownLatch(1);
sendScanResultsAndProcess(tracker);
@@ -235,16 +248,16 @@
private WifiTracker createMockedWifiTracker() {
WifiTracker tracker =
new WifiTracker(
- mContext,
- mockWifiListener,
- mLooper,
- true,
- true,
- true,
- mockWifiManager,
- mockConnectivityManager,
- mockNetworkScoreManager,
- mMainLooper
+ mContext,
+ mockWifiListener,
+ mLooper,
+ true,
+ true,
+ true,
+ mockWifiManager,
+ mockConnectivityManager,
+ mockNetworkScoreManager,
+ mMainLooper
);
return tracker;
@@ -294,6 +307,31 @@
scoreCache.updateScores(Arrays.asList(sc1, sc2));
}
+ private WifiTracker createTrackerWithScanResultsAndAccessPoint1Connected()
+ throws InterruptedException {
+ int networkId = 123;
+
+ WifiInfo wifiInfo = new WifiInfo();
+ wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(SSID_1));
+ wifiInfo.setBSSID(BSSID_1);
+ wifiInfo.setNetworkId(networkId);
+ when(mockWifiManager.getConnectionInfo()).thenReturn(wifiInfo);
+
+ WifiConfiguration configuration = new WifiConfiguration();
+ configuration.SSID = SSID_1;
+ configuration.BSSID = BSSID_1;
+ configuration.networkId = networkId;
+ when(mockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(configuration));
+
+ NetworkInfo networkInfo = new NetworkInfo(
+ ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
+ networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "connected", "test");
+
+ Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
+ return createTrackerWithImmediateBroadcastsAndInjectInitialScanResults(intent);
+ }
+
@Test
public void testAccessPointListenerSetWhenLookingUpUsingScanResults() {
ScanResult scanResult = new ScanResult();
@@ -357,12 +395,21 @@
}
@Test
+ public void startTrackingShouldSetConnectedAccessPointAsActive() throws InterruptedException {
+ WifiTracker tracker = createTrackerWithScanResultsAndAccessPoint1Connected();
+
+ List<AccessPoint> aps = tracker.getAccessPoints();
+
+ assertThat(aps).hasSize(2);
+ assertThat(aps.get(0).isActive()).isTrue();
+ }
+
+ @Test
public void startTrackingShouldRequestScoresForCurrentAccessPoints() throws InterruptedException {
// Start the tracker and inject the initial scan results and then stop tracking
- WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+ WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
tracker.stopTracking();
- android.util.Log.d("WifiTrackerTest", "Clearing previously captured requested keys");
mRequestedKeys.clear();
mRequestScoresLatch = new CountDownLatch(1);
@@ -370,7 +417,6 @@
assertTrue("Latch timed out",
mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
- android.util.Log.d("WifiTrackerTest", "requested keys: " + mRequestedKeys);
assertTrue(mRequestedKeys.contains(NETWORK_KEY_1));
assertTrue(mRequestedKeys.contains(NETWORK_KEY_2));
}
@@ -394,7 +440,7 @@
@Test
public void scoreCacheUpdateScoresShouldChangeSortOrder() throws InterruptedException {
- WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+ WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
List<AccessPoint> aps = tracker.getAccessPoints();
assertTrue(aps.size() == 2);
assertEquals(aps.get(0).getSsidStr(), SSID_1);
@@ -416,7 +462,7 @@
Settings.Global.NETWORK_SCORING_UI_ENABLED,
0 /* disabled */);
- WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+ WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
List<AccessPoint> aps = tracker.getAccessPoints();
assertTrue(aps.size() == 2);
assertEquals(aps.get(0).getSsidStr(), SSID_1);
@@ -432,7 +478,7 @@
@Test
public void scoreCacheUpdateScoresShouldInsertBadgeIntoAccessPoint() throws InterruptedException {
- WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+ WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
updateScoresAndWaitForAccessPointsChangedCallback();
List<AccessPoint> aps = tracker.getAccessPoints();
@@ -454,7 +500,7 @@
Settings.Global.NETWORK_SCORING_UI_ENABLED,
0 /* disabled */);
- WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+ WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
updateScoresAndWaitForAccessPointsChangedCallback();
List<AccessPoint> aps = tracker.getAccessPoints();
@@ -473,7 +519,7 @@
// Scores can be requested together or serially depending on how the scan results are
// processed.
mRequestScoresLatch = new CountDownLatch(2);
- WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+ WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
mRequestedKeys.clear();
@@ -503,7 +549,7 @@
@Test
public void scoreCacheAndListenerShouldBeUnregisteredWhenStopTrackingIsCalled() throws Exception
{
- WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+ WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
WifiNetworkScoreCache cache = mScoreCacheCaptor.getValue();
tracker.stopTracking();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
index 2958740..c506358 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
@@ -16,6 +16,17 @@
package com.android.settingslib;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
@@ -25,18 +36,13 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import java.util.Arrays;
-import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
-import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT;
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.when;
-
@RunWith(SettingLibRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class RestrictedLockUtilsTest {
@@ -47,8 +53,11 @@
private DevicePolicyManager mDevicePolicyManager;
@Mock
private UserManager mUserManager;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private RestrictedLockUtils.Proxy mProxy;
private static final int mUserId = 194;
+ private static final int mProfileId = 160;
private static final ComponentName mAdmin1 = new ComponentName("admin1", "admin1class");
private static final ComponentName mAdmin2 = new ComponentName("admin2", "admin2class");
@@ -60,12 +69,13 @@
.thenReturn(mDevicePolicyManager);
when(mContext.getSystemService(Context.USER_SERVICE))
.thenReturn(mUserManager);
+
+ RestrictedLockUtils.sProxy = mProxy;
}
@Test
public void checkIfKeyguardFeaturesDisabled_noEnforcedAdminForManagedProfile() {
- setUpManagedProfile(mUserId);
- setUpActiveAdmins(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
+ setUpManagedProfile(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
final EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
mContext, KEYGUARD_DISABLE_FINGERPRINT, mUserId);
@@ -75,8 +85,7 @@
@Test
public void checkIfKeyguardFeaturesDisabled_oneEnforcedAdminForManagedProfile() {
- setUpManagedProfile(mUserId);
- setUpActiveAdmins(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
+ setUpManagedProfile(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
.thenReturn(KEYGUARD_DISABLE_FINGERPRINT);
@@ -89,8 +98,7 @@
@Test
public void checkIfKeyguardFeaturesDisabled_multipleEnforcedAdminForManagedProfile() {
- setUpManagedProfile(mUserId);
- setUpActiveAdmins(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
+ setUpManagedProfile(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
.thenReturn(KEYGUARD_DISABLE_REMOTE_INPUT);
@@ -103,9 +111,129 @@
assertThat(enforcedAdmin).isEqualTo(EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN);
}
- private UserInfo setUpManagedProfile(int userId) {
- final UserInfo userInfo = new UserInfo(userId, "myuser", UserInfo.FLAG_MANAGED_PROFILE);
+ @Test
+ public void checkIfKeyguardFeaturesAreDisabled_doesMatchAllowedFeature_unifiedManagedProfile() {
+ UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
+ UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
+ when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
+ userInfo, profileInfo}));
+
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
+ .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE);
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin2, mProfileId))
+ .thenReturn(KEYGUARD_DISABLE_FINGERPRINT);
+
+ // Querying the parent should return the policy, since it affects the parent.
+ EnforcedAdmin parent = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_FINGERPRINT, mUserId);
+ assertThat(parent).isEqualTo(new EnforcedAdmin(mAdmin2, mProfileId));
+
+ // Querying the child should return that too.
+ EnforcedAdmin profile = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_FINGERPRINT, mProfileId);
+ assertThat(profile).isEqualTo(new EnforcedAdmin(mAdmin2, mProfileId));
+
+ // Querying for some unrelated feature should return nothing. Nothing!
+ assertThat(RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_REMOTE_INPUT, mUserId)).isNull();
+ assertThat(RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_REMOTE_INPUT, mProfileId)).isNull();
+ }
+
+ @Test
+ public void checkIfKeyguardFeaturesAreDisabled_notMatchOtherFeatures_unifiedManagedProfile() {
+ UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
+ UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
+ when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
+ userInfo, profileInfo}));
+
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
+ .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE);
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin2, mProfileId))
+ .thenReturn(KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
+
+ // Querying the parent should not return the policy, because it's not a policy that should
+ // affect parents even when the lock screen is unified.
+ EnforcedAdmin primary = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS, mUserId);
+ assertThat(primary).isNull();
+
+ // Querying the child should still return the policy.
+ EnforcedAdmin profile = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS, mProfileId);
+ assertThat(profile).isEqualTo(new EnforcedAdmin(mAdmin2, mProfileId));
+ }
+
+ @Test
+ public void checkIfKeyguardFeaturesAreDisabled_onlyMatchesProfile_separateManagedProfile() {
+ UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
+ UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
+ when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
+ userInfo, profileInfo}));
+
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
+ .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE);
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin2, mProfileId))
+ .thenReturn(KEYGUARD_DISABLE_FINGERPRINT);
+
+ // Crucially for this test, isSeparateWorkChallengeEnabled => true.
+ doReturn(true).when(mProxy).isSeparateProfileChallengeEnabled(any(), eq(mProfileId));
+
+ // Querying the parent should not return the policy, even though it's shared by default,
+ // because the parent doesn't share a lock screen with the profile any more.
+ EnforcedAdmin parent = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_FINGERPRINT, mUserId);
+ assertThat(parent).isNull();
+
+ // Querying the child should still return the policy.
+ EnforcedAdmin profile = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_FINGERPRINT, mProfileId);
+ assertThat(profile).isEqualTo(new EnforcedAdmin(mAdmin2, mProfileId));
+ }
+
+ /**
+ * This test works great. The real world implementation is sketchy though.
+ * <p>
+ * DevicePolicyManager.getParentProfileInstance(UserInfo) does not do what it looks like it does
+ * (which would be to get an instance for the parent of the user that's passed in to it.)
+ * <p>
+ * Instead it just always returns a parent instance for the current user.
+ * <p>
+ * Still, the test works.
+ */
+ @Test
+ public void checkIfKeyguardFeaturesAreDisabled_onlyMatchesParent_profileParentPolicy() {
+ UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
+ UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
+ when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
+ userInfo, profileInfo}));
+
+ when(mProxy.getParentProfileInstance(any(DevicePolicyManager.class), any())
+ .getKeyguardDisabledFeatures(mAdmin2, mProfileId))
+ .thenReturn(KEYGUARD_DISABLE_FINGERPRINT);
+
+ // Parent should get the policy.
+ EnforcedAdmin parent = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_FINGERPRINT, mUserId);
+ assertThat(parent).isEqualTo(new EnforcedAdmin(mAdmin2, mProfileId));
+
+ // Profile should not get the policy.
+ EnforcedAdmin profile = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_FINGERPRINT, mProfileId);
+ assertThat(profile).isNull();
+ }
+
+ private UserInfo setUpUser(int userId, ComponentName[] admins) {
+ UserInfo userInfo = new UserInfo(userId, "primary", 0);
when(mUserManager.getUserInfo(userId)).thenReturn(userInfo);
+ setUpActiveAdmins(userId, admins);
+ return userInfo;
+ }
+
+ private UserInfo setUpManagedProfile(int userId, ComponentName[] admins) {
+ UserInfo userInfo = new UserInfo(userId, "profile", UserInfo.FLAG_MANAGED_PROFILE);
+ when(mUserManager.getUserInfo(userId)).thenReturn(userInfo);
+ setUpActiveAdmins(userId, admins);
return userInfo;
}
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 12d0c03..1df626f 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -44,6 +44,7 @@
import libcore.io.Streams;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.ChooserActivity;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.FastPrintWriter;
@@ -943,8 +944,13 @@
}
static void sendShareIntent(Context context, Intent intent) {
- context.startActivity(Intent.createChooser(intent,
- context.getResources().getText(R.string.bugreport_intent_chooser_title)));
+ final Intent chooserIntent = Intent.createChooser(intent,
+ context.getResources().getText(R.string.bugreport_intent_chooser_title));
+
+ // Since we may be launched behind lockscreen, make sure that ChooserActivity doesn't finish
+ // itself in onStop.
+ chooserIntent.putExtra(ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP, true);
+ context.startActivity(chooserIntent);
}
/**
diff --git a/packages/SystemUI/res/drawable/ic_fingerprint_error.xml b/packages/SystemUI/res/drawable/ic_fingerprint_error.xml
index 11e83a1..a7fb1a1 100644
--- a/packages/SystemUI/res/drawable/ic_fingerprint_error.xml
+++ b/packages/SystemUI/res/drawable/ic_fingerprint_error.xml
@@ -19,12 +19,12 @@
android:viewportWidth="32.0"
android:viewportHeight="32.0">
<path
- android:fillColor="@color/system_warning_color"
+ android:fillColor="?android:attr/colorError"
android:pathData="M15.99,2.5C8.53,2.5 2.5,8.54 2.5,16.0s6.03,13.5 13.49,13.5S29.5,23.46 29.5,16.0S23.45,2.5 15.99,2.5zM16.0,26.8c-5.97,0.0 -10.8,-4.83 -10.8,-10.8S10.03,5.2 16.0,5.2S26.8,10.03 26.8,16.0S21.97,26.8 16.0,26.8z"/>
<path
- android:fillColor="@color/system_warning_color"
+ android:fillColor="?android:attr/colorError"
android:pathData="M14.65,20.05l2.7,0.0l0.0,2.7l-2.7,0.0z"/>
<path
- android:fillColor="@color/system_warning_color"
+ android:fillColor="?android:attr/colorError"
android:pathData="M14.65,9.25l2.7,0.0l0.0,8.1l-2.7,0.0z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_network_logging.xml b/packages/SystemUI/res/drawable/ic_qs_network_logging.xml
index 87b5a14..7bdf50c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_network_logging.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_network_logging.xml
@@ -20,8 +20,7 @@
android:width="12.0dp"
android:height="12.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="#4DFFFFFF" >
+ android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M2,24v-4h12v4H2z M2,16v-4h20v4H2z M5,7 12,0 19,7 14,7 14,15 10,15 10,7z"/>
diff --git a/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml
index e207cb3..3af2f7f 100644
--- a/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml
+++ b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml
@@ -98,11 +98,11 @@
<path
android:name="path_2"
android:pathData="M 1.35900878906,6.76104736328 c 0.0,0.0 -2.69998168945,0.0 -2.69998168945,0.0 c 0.0,0.0 0.0,-2.69995117188 0.0,-2.69995117188 c 0.0,0.0 2.69998168945,0.0 2.69998168945,0.0 c 0.0,0.0 0.0,2.69995117188 0.0,2.69995117188 Z"
- android:fillColor="@*android:color/system_error" />
+ android:fillColor="?android:attr/colorError" />
<path
android:name="path_1"
android:pathData="M 1.35363769531,1.36633300781 c 0.0,0.0 -2.69998168945,0.0 -2.69998168945,0.0 c 0.0,0.0 0.0,-8.09997558594 0.0,-8.09997558594 c 0.0,0.0 2.69998168945,0.0 2.69998168945,0.0 c 0.0,0.0 0.0,8.09997558594 0.0,8.09997558594 Z"
- android:fillColor="@*android:color/system_error" />
+ android:fillColor="?android:attr/colorError" />
</group>
</group>
<group
@@ -117,7 +117,7 @@
<path
android:name="path_3"
android:pathData="M 0.0101470947266,10.8087768555 c -5.96701049805,0.0 -10.8000183105,-4.8330078125 -10.8000183105,-10.8000488281 c 0.0,-5.96691894531 4.8330078125,-10.7999267578 10.8000183105,-10.7999267578 c 5.96697998047,0.0 10.799987793,4.8330078125 10.799987793,10.7999267578 c 0.0,5.96704101562 -4.8330078125,10.8000488281 -10.799987793,10.8000488281 Z"
- android:strokeColor="@*android:color/system_error"
+ android:strokeColor="?android:attr/colorError"
android:strokeWidth="2"
android:trimPathStart="0"
android:trimPathEnd="1" />
diff --git a/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml b/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml
index 2b4babc..a577afc 100644
--- a/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml
+++ b/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml
@@ -96,7 +96,7 @@
<path
android:name="ridge_5_path_0"
android:pathData="M -25.3591003418,-24.4138946533 c -0.569000244141,0.106399536133 -1.12660217285,0.140594482422 -1.45460510254,0.140594482422 c -1.29689025879,0.0 -2.53239440918,-0.343307495117 -3.62019348145,-1.12400817871 c -1.67700195312,-1.20349121094 -2.76950073242,-3.17008972168 -2.76950073242,-5.39189147949"
- android:strokeColor="@*android:color/system_error"
+ android:strokeColor="?android:attr/colorError"
android:strokeWidth="1.45"
android:strokeLineCap="round"
android:trimPathEnd="0" />
@@ -106,7 +106,7 @@
<path
android:name="ridge_7_path_0"
android:pathData="M -36.1409912109,-21.7843475342 c -1.00540161133,-1.19300842285 -1.57499694824,-1.9181060791 -2.36520385742,-3.50170898438 c -0.827560424805,-1.65869140625 -1.31352233887,-3.49159240723 -1.31352233887,-5.48489379883 c 0.0,-3.66279602051 2.96932983398,-6.63220214844 6.63221740723,-6.63220214844 c 3.6628112793,0.0 6.63220214844,2.96940612793 6.63220214844,6.63220214844"
- android:strokeColor="@*android:color/system_error"
+ android:strokeColor="?android:attr/colorError"
android:strokeWidth="1.45"
android:strokeLineCap="round"
android:trimPathEnd="0" />
@@ -116,7 +116,7 @@
<path
android:name="ridge_6_path_0"
android:pathData="M -42.1907958984,-25.6756896973 c -0.758117675781,-2.14370727539 -0.896545410156,-3.86891174316 -0.896545410156,-5.12921142578 c 0.0,-1.46069335938 0.249176025391,-2.84799194336 0.814682006836,-4.09748840332 c 1.56153869629,-3.45030212402 5.03434753418,-5.85076904297 9.0679473877,-5.85076904297 c 5.49430847168,0.0 9.94830322266,4.4539642334 9.94830322266,9.94825744629 c 0.0,1.83151245117 -1.48460388184,3.31610107422 -3.31610107422,3.31610107422 c -1.83149719238,0.0 -3.31610107422,-1.48469543457 -3.31610107422,-3.31610107422 c 0.0,-1.83139038086 -1.48458862305,-3.31610107422 -3.31610107422,-3.31610107422 c -1.83149719238,0.0 -3.31610107422,1.48471069336 -3.31610107422,3.31610107422 c 0.0,2.57020568848 0.989517211914,4.88710021973 2.60510253906,6.5865020752 c 1.22210693359,1.28550720215 2.43139648438,2.09950256348 4.47590637207,2.69030761719"
- android:strokeColor="@*android:color/system_error"
+ android:strokeColor="?android:attr/colorError"
android:strokeWidth="1.45"
android:strokeLineCap="round"
android:trimPathEnd="0" />
@@ -126,7 +126,7 @@
<path
android:name="ridge_2_path_0"
android:pathData="M -44.0646514893,-38.1672973633 c 1.19026184082,-1.77430725098 2.67503356934,-3.24531555176 4.55902099609,-4.27278137207 c 1.88395690918,-1.0274810791 4.04466247559,-1.61137390137 6.34175109863,-1.61137390137 c 2.28761291504,0.0 4.43991088867,0.579071044922 6.31831359863,1.59861755371 c 1.8784942627,1.01954650879 3.36059570312,2.4796295166 4.55279541016,4.24153137207"
- android:strokeColor="@*android:color/system_error"
+ android:strokeColor="?android:attr/colorError"
android:strokeWidth="1.45"
android:strokeLineCap="round"
android:trimPathStart="1" />
@@ -138,7 +138,7 @@
<path
android:name="ridge_1_path_0"
android:pathData="M 71.7812347412,97.0507202148 c -2.27149963379,-1.31344604492 -4.71360778809,-2.07006835938 -7.56221008301,-2.07006835938 c -2.84869384766,0.0 -5.23320007324,0.779556274414 -7.34411621094,2.07006835938"
- android:strokeColor="@*android:color/system_error"
+ android:strokeColor="?android:attr/colorError"
android:strokeWidth="1.45"
android:strokeLineCap="round"
android:trimPathEnd="0" />
@@ -157,11 +157,11 @@
<path
android:name="path_2"
android:pathData="M -1.3705291748,4.06730651855 c 0.0,0.0 0.036376953125,-0.0102386474609 0.036376953125,-0.0102386474609 c 0.0,0.0 -0.00682067871094,0.0040283203125 -0.00682067871093,0.0040283203125 c 0.0,0.0 -0.0161437988281,0.00479125976562 -0.0161437988281,0.00479125976563 c 0.0,0.0 -0.0134124755859,0.00141906738281 -0.0134124755859,0.00141906738281 Z"
- android:fillColor="@*android:color/system_error" />
+ android:fillColor="?android:attr/colorError" />
<path
android:name="path_1"
android:pathData="M -1.3737487793,-6.77532958984 c 0.0,0.0 0.00604248046875,0.0166625976562 0.00604248046876,0.0166625976562 c 0.0,0.0 0.0213623046875,0.0250244140625 0.0213623046875,0.0250244140625 c 0.0,0.0 -0.00604248046875,-0.0166625976562 -0.00604248046876,-0.0166625976562 c 0.0,0.0 -0.0213623046875,-0.0250244140625 -0.0213623046875,-0.0250244140625 Z"
- android:fillColor="@*android:color/system_error" />
+ android:fillColor="?android:attr/colorError" />
</group>
</group>
<group
@@ -176,7 +176,7 @@
<path
android:name="path_3"
android:pathData="M 0.0101470947266,10.8087768555 c -5.96701049805,0.0 -10.8000183105,-4.8330078125 -10.8000183105,-10.8000488281 c 0.0,-5.96691894531 4.8330078125,-10.7999267578 10.8000183105,-10.7999267578 c 5.96697998047,0.0 10.799987793,4.8330078125 10.799987793,10.7999267578 c 0.0,5.96704101562 -4.8330078125,10.8000488281 -10.799987793,10.8000488281 Z"
- android:strokeColor="@*android:color/system_error"
+ android:strokeColor="?android:attr/colorError"
android:strokeWidth="2"
android:trimPathStart="1" />
</group>
diff --git a/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml b/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml
index b7da30b..bf405fa 100644
--- a/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml
+++ b/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml
@@ -20,10 +20,10 @@
android:viewportHeight="72.0"
android:tint="?android:attr/textColorPrimary">
<group
- android:translateX="52.0"
- android:translateY="42.0" >
+ android:translateX="28.0"
+ android:translateY="10.5" >
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M18.0,8.0l-1.0,0.0L17.0,6.0c0.0,-2.76 -2.24,-5.0 -5.0,-5.0S7.0,3.24 7.0,6.0l0.0,2.0L6.0,8.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,10.0c0.0,1.0 0.9,2.0 2.0,2.0l12.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L20.0,10.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0zm-6.0,9.0c-1.1,0.0 -2.0,-0.9 -2.0,-2.0s0.9,-2.0 2.0,-2.0 2.0,0.9 2.0,2.0 -0.9,2.0 -2.0,2.0zm3.1,-9.0L8.9,8.0L8.9,6.0c0.0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0.0 3.1,1.39 3.1,3.1l0.0,2.0z"/>
+ android:pathData="M36 16l-2 0 0 -4C34 6.48 29.52 2 24 2 18.48 2 14 6.48 14 12l0 4 -2 0c-2.21 0 -4 1.79 -4 4l0 20c0 2.21 1.79 4 4 4l24 0c2.21 0 4 -1.79 4 -4l0 -20c0 -2.21 -1.79 -4 -4 -4zM24 34c-2.21 0 -4 -1.79 -4 -4 0 -2.21 1.79 -4 4 -4 2.21 0 4 1.79 4 4 0 2.21 -1.79 4 -4 4zm6.2 -18l-12.4 0 0 -4c0 -3.42 2.78 -6.2 6.2 -6.2 3.42 0 6.2 2.78 6.2 6.2l0 4z"
+ android:fillColor="#FFFFFF" />
</group>
</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_in.xml b/packages/SystemUI/res/drawable/stat_sys_signal_in.xml
new file mode 100644
index 0000000..7e6e09b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_in.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
+ android:width="17dp"
+ android:height="17dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:name="in"
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M8.7,12.2l-2.0,3.5l-2.0,-3.5z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_inout.xml b/packages/SystemUI/res/drawable/stat_sys_signal_inout.xml
new file mode 100644
index 0000000..b7b6f0f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_inout.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
+ android:width="17dp"
+ android:height="17dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:name="in"
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M8.7,12.2l-2.0,3.5l-2.0,-3.5z" />
+ <path
+ android:name="out"
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M0.5,15.7l2.0,-3.5l2.0,3.5z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_out.xml b/packages/SystemUI/res/drawable/stat_sys_signal_out.xml
new file mode 100644
index 0000000..910c035
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_out.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
+ android:width="17dp"
+ android:height="17dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:name="out"
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M0.5,15.7l2.0,-3.5l2.0,3.5z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_in.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_in.xml
new file mode 100644
index 0000000..666127b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_in.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
+ android:width="18.41dp"
+ android:height="17dp"
+ android:viewportWidth="26.0"
+ android:viewportHeight="24.0">
+ <path
+ android:name="in"
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M8.7,18.3l-2.0,3.5l-2.0,-3.5z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_inout.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_inout.xml
new file mode 100644
index 0000000..eeba030
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_inout.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
+ android:width="18.41dp"
+ android:height="17dp"
+ android:viewportWidth="26.0"
+ android:viewportHeight="24.0">
+ <path
+ android:name="in"
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M8.7,18.3l-2.0,3.5l-2.0,-3.5z" />
+ <path
+ android:name="out"
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M0.5,21.8l2.0,-3.5l2.0,3.5z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_out.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_out.xml
new file mode 100644
index 0000000..d577d1a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_out.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
+ android:width="18.41dp"
+ android:height="17dp"
+ android:viewportWidth="26.0"
+ android:viewportHeight="24.0">
+ <path
+ android:name="out"
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M0.5,21.8l2.0,-3.5l2.0,3.5z" />
+</vector>
diff --git a/packages/SystemUI/res/layout/mobile_signal_group.xml b/packages/SystemUI/res/layout/mobile_signal_group.xml
index 8b10074..d988acc 100644
--- a/packages/SystemUI/res/layout/mobile_signal_group.xml
+++ b/packages/SystemUI/res/layout/mobile_signal_group.xml
@@ -54,4 +54,10 @@
android:src="@drawable/stat_sys_roaming"
android:contentDescription="@string/accessibility_data_connection_roaming"
android:visibility="gone" />
+ <ImageView
+ android:id="@+id/mobile_inout"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:visibility="gone"
+ />
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/qs_detail_item.xml b/packages/SystemUI/res/layout/qs_detail_item.xml
index 6edf135..6544f0d 100644
--- a/packages/SystemUI/res/layout/qs_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_detail_item.xml
@@ -63,7 +63,6 @@
android:focusable="true"
android:scaleType="center"
android:contentDescription="@*android:string/media_route_controller_disconnect"
- android:tint="?android:attr/textColorPrimary"
- android:src="@drawable/ic_qs_cancel" />
+ android:tint="?android:attr/textColorPrimary" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index 222a31d..4d03f0f 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -70,6 +70,11 @@
android:layout_width="wrap_content"
android:alpha="0.0"
/>
+ <ImageView
+ android:id="@+id/wifi_inout"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ />
</FrameLayout>
<View
android:id="@+id/wifi_signal_spacer"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 073a6dc..d63fc0e 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Skermkiekies"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Algemene boodskappe"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Berging"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Kitsprogramme"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Kitsprogramme hoef nie geïnstalleer te word nie."</string>
<string name="app_info" msgid="6856026610594615344">"Programinligting"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index f33b663..4bfebd2 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"ቅጽበታዊ ገጽ እይታዎች"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"አጠቃላይ መልዕክቶች"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"ማከማቻ"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"የቅጽበት መተግበሪያዎች"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"ቅጽበታዊ መተግበሪያዎች መጫን አያስፈልጋቸውም።"</string>
<string name="app_info" msgid="6856026610594615344">"የመተግበሪያ መረጃ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 94810bd..1381cb3 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -704,9 +704,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"لقطات الشاشة"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"رسائل عامة"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"سعة التخزين"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"التطبيقات الفورية"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"لا تتطلب التطبيقات الفورية إجراء التثبيت."</string>
<string name="app_info" msgid="6856026610594615344">"معلومات عن التطبيق"</string>
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index dea9a57..c90e442 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Skrinşotlar"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Ümumi Mesajlar"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Yaddaş"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Ani Tətbiqlər"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Ani tətbiqlər quraşdırma tələb etmir."</string>
<string name="app_info" msgid="6856026610594615344">"Tətbiq məlumatı"</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index eaeabc9..59a925e 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -695,9 +695,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Snimci ekrana"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Opšte poruke"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Memorijski prostor"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant aplikacije"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Instant aplikacije ne zahtevaju instalaciju."</string>
<string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 89191fa..efbf39e 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -700,9 +700,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Здымкі экрана"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Агульныя паведамленні"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Захоўванне"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Імгненныя праграмы"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Імгненныя праграмы не патрабуюць усталёўкі."</string>
<string name="app_info" msgid="6856026610594615344">"Інфармацыя пра праграму"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 3816775..3ebfcc8 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Екранни снимки"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Общи съобщения"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Хранилище"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Мигновени приложения"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"За мигновените приложения не се изисква инсталиране."</string>
<string name="app_info" msgid="6856026610594615344">"Информация за приложението"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 76a882f..476e27c 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"স্ক্রীনশটস"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"সাধারণ বার্তাগুলি"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"সঞ্চয়স্থান"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"ঝটপট অ্যাপ"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"ঝটপট অ্যাপ ইনস্টল করার প্রয়োজন হয় না।"</string>
<string name="app_info" msgid="6856026610594615344">"অ্যাপ্লিকেশানের তথ্য"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 208befe..c318501 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -697,9 +697,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Snimci ekrana"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Općenite poruke"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Pohrana"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant-aplikacije"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Za instant aplikacije nije potrebna instalacija"</string>
<string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index ccb3114..14455b3 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Captures de pantalla"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Missatges generals"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Emmagatzematge"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Aplicacions instantànies"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"No cal instal·lar les aplicacions instantànies."</string>
<string name="app_info" msgid="6856026610594615344">"Informació de l\'aplicació"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 534e7bf..2cb79c9 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -700,9 +700,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Snímky obrazovek"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Všeobecné zprávy"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Úložiště"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Okamžité aplikace"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Okamžité aplikace není třeba instalovat."</string>
<string name="app_info" msgid="6856026610594615344">"Informace o aplikaci"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index f694924..681f747 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Generelle meddelelser"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Lagerplads"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Instant apps kræver ingen installation."</string>
<string name="app_info" msgid="6856026610594615344">"Oplysninger om appen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index dbbb4f9..cb6c4b3 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Nachrichten"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Speicher"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant-Apps"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Bei Instant-Apps ist keine vorherige Installation erforderlich."</string>
<string name="app_info" msgid="6856026610594615344">"App-Informationen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 688084b..0998797 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Στιγμιότυπα οθόνης"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Γενικά μηνύματα"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Αποθηκευτικός χώρος"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant Εφαρμογές"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Οι Instant Εφαρμογές δεν απαιτούν εγκατάσταση."</string>
<string name="app_info" msgid="6856026610594615344">"Πληροφορίες εφαρμογής"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index bcac06f..eba837a 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Instant apps don\'t require installation."</string>
<string name="app_info" msgid="6856026610594615344">"App info"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index bcac06f..eba837a 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Instant apps don\'t require installation."</string>
<string name="app_info" msgid="6856026610594615344">"App info"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index bcac06f..eba837a 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Instant apps don\'t require installation."</string>
<string name="app_info" msgid="6856026610594615344">"App info"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index b0ccb27..c2a41f1 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de pantalla"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Mensajes generales"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamiento"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Apps instantáneas"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Las Apps instantáneas no requieren instalación."</string>
<string name="app_info" msgid="6856026610594615344">"Información de la app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 59fe471..503eb64 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de pantalla"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Mensajes generales"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamiento"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Aplicaciones Instantáneas"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"No es necesario instalar las Aplicaciones Instantáneas."</string>
<string name="app_info" msgid="6856026610594615344">"Información de la aplicación"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 3afebd7..94577f5 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekraanipildid"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Üldised sõnumid"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Salvestusruum"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Installimata avatavad rakendused"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Installimata avatavaid rakendusi pole vaja installida."</string>
<string name="app_info" msgid="6856026610594615344">"Rakenduse teave"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 399d9ec..72d8ecb 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Pantaila-argazkiak"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Mezu orokorrak"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Memoria"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Zuzeneko aplikazioak"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Zuzeneko aplikazioak ez dira instalatu behar."</string>
<string name="app_info" msgid="6856026610594615344">"Aplikazioari buruzko informazioa"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index f38bd46..b8e8ed1 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"عکسهای صفحهنمایش"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"پیامهای عمومی"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"فضای ذخیرهسازی"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"برنامههای فوری"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"برنامههای فوری نیاز به نصب ندارند."</string>
<string name="app_info" msgid="6856026610594615344">"اطلاعات برنامه"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index b29a0f5..2480ac8 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Kuvakaappaukset"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Yleiset viestit"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Tallennustila"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Pikasovelluksia ei tarvitse asentaa."</string>
<string name="app_info" msgid="6856026610594615344">"Sovelluksen tiedot"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 21f7498..121b137 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Saisies d\'écran"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Messages généraux"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Stockage"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Applications instantanées"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Les applications instantanées ne nécessitent pas d\'installation."</string>
<string name="app_info" msgid="6856026610594615344">"Détails de l\'application"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index c65e0ea..6d677ae 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Captures d\'écran"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Nouveaux messages"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Espace de stockage"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Applis instantanées"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Les applis instantanées ne nécessitent pas d\'installation."</string>
<string name="app_info" msgid="6856026610594615344">"Infos sur l\'appli"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 3579ebe..e5df1d3 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de pantalla"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Mensaxes xerais"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamento"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Aplicacións instantáneas"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"As aplicacións instantáneas non precisan instalación."</string>
<string name="app_info" msgid="6856026610594615344">"Información da aplicación"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index acc3890..381476f 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"સ્ક્રીનશૉટ"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"સામાન્ય સંદેશા"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"સ્ટોરેજ"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"ઝટપટ ઍપ્લિકેશનો"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"ઝટપટ ઍપ્લિકેશનો માટે ઇન્સ્ટૉલેશનની જરૂર નથી."</string>
<string name="app_info" msgid="6856026610594615344">"ઍપ્લિકેશન માહિતી"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index a318ea3..27a5918 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"स्क्रीनशॉट"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"सामान्य संदेश"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"जगह"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"झटपट ऐप्स"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"झटपट ऐप्स के लिए इंस्टॉलेशन ज़रूरी नहीं है."</string>
<string name="app_info" msgid="6856026610594615344">"ऐप की जानकारी"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 2ce11af..7957f2c 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -695,9 +695,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Snimke zaslona"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Općenite poruke"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Pohrana"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant aplikacije"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Instant aplikacije nije potrebno instalirati."</string>
<string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 288b25f..629867b 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Képernyőképek"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Általános üzenetek"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Tárhely"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Azonnali alkalmazások"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Az azonnali alkalmazásokat nem kell telepíteni."</string>
<string name="app_info" msgid="6856026610594615344">"Alkalmazásinformáció"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 3b8dac7..f090714 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Էկրանի պատկերներ"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Ընդհանուր հաղորդագրություններ"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Հիշողություն"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Ակնթարթորեն գործարկվող հավելվածներ"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Ակնթարթորեն գործարկվող հավելվածները տեղադրում չեն պահանջում։"</string>
<string name="app_info" msgid="6856026610594615344">"Հավելվածի տվյալներ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 8efc3a9..12acc55 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshot"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Pesan Umum"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Penyimpanan"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Aplikasi Instan"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Aplikasi instan tidak perlu diinstal."</string>
<string name="app_info" msgid="6856026610594615344">"Info aplikasi"</string>
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index c1fa058..a355771 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Skjámyndir"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Almenn skilaboð"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Geymslurými"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Skyndiforrit"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Skyndiforrit þurfa ekki uppsetningu."</string>
<string name="app_info" msgid="6856026610594615344">"Forritsupplýsingar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 481d80c..be648e7 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshot"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Messaggi generali"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Spazio di archiviazione"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"App istantanee"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Le app istantanee non richiedono l\'installazione."</string>
<string name="app_info" msgid="6856026610594615344">"Informazioni app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index f22dec5..d20d590 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -698,9 +698,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"צילומי מסך"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"הודעות כלליות"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"אחסון"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"אפליקציות אינסטנט"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"אפליקציות אינסטנט לא דורשות התקנה."</string>
<string name="app_info" msgid="6856026610594615344">"פרטי אפליקציה"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index d4c381e..00405ac 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"スクリーンショット"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"一般メッセージ"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"ストレージ"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Instant Apps はインストールせずに利用できます。"</string>
<string name="app_info" msgid="6856026610594615344">"アプリ情報"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 674f308..b5bc2408 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"ეკრანის ანაბეჭდები"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"ზოგადი შეტყობინებები"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"მეხსიერება"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"მყისიერი აპები"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"მყისიერი აპები ინსტალაციას არ საჭიროებს."</string>
<string name="app_info" msgid="6856026610594615344">"აპის შესახებ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index dba10da..3e5fe2d 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоттар"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Жалпы хабарлар"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Жад"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Лездік қолданбаларды орнатудың қажеті жоқ."</string>
<string name="app_info" msgid="6856026610594615344">"Қолданба ақпараты"</string>
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index f91c80a..4856e3c 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"រូបថតអេក្រង់"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"សារទូទៅ"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"ទំហំផ្ទុក"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"កម្មវិធីប្រើភ្លាមៗ"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"កម្មវិធីប្រើភ្លាមៗមិនតម្រូវឲ្យមានការដំឡើងទេ។"</string>
<string name="app_info" msgid="6856026610594615344">"ព័ត៌មានកម្មវិធី"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index b94c0bf..65b89b8 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"ಸ್ಕ್ರೀನ್ಶಾಟ್ಗಳು"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"ಸಾಮಾನ್ಯ ಸಂದೇಶಗಳು"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"ಸಂಗ್ರಹಣೆ"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"ತತ್ಕ್ಷಣ ಆಪ್ಗಳು"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"ತತ್ಕ್ಷಣ ಆಪ್ಗಳಿಗೆ ಸ್ಥಾಪನೆಯ ಅಗತ್ಯವಿಲ್ಲ."</string>
<string name="app_info" msgid="6856026610594615344">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index d46c0af..9c277b0 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"스크린샷"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"일반 메시지"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"저장소"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"빠른 실행 앱"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"빠른 실행 앱은 설치가 필요하지 않습니다."</string>
<string name="app_info" msgid="6856026610594615344">"앱 정보"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index ec61db1..9080df8 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоттор"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Жалпы билдирүүлөр"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Сактагыч"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Ыкчам ачылуучу колдонмолор"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Ыкчам ачылуучу колдонмолорду орнотуу талап кылынбайт."</string>
<string name="app_info" msgid="6856026610594615344">"Колдонмо тууралуу"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 87f008b..3ccbe92 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"ຮູບຖ່າຍໜ້າຈໍ"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"ຂໍ້ຄວາມທົ່ວໄປ"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"ບ່ອນເກັບຂໍ້ມູນ"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"ອິນສະແຕນແອັບ"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"ອິນສະແຕນແອັບບໍ່ຈຳເປັນຕ້ອງມີການຕິດຕັ້ງ."</string>
<string name="app_info" msgid="6856026610594615344">"ຂໍ້ມູນແອັບ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index f2df152..fa4ab0d 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -698,9 +698,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekrano kopijos"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Bendrieji pranešimai"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Saugykla"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Akimirksniu įkeliamos programėlės"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Akimirksniu įkeliamų programėlių nereikia įdiegti."</string>
<string name="app_info" msgid="6856026610594615344">"Programos informacija"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index e5970d4..cb7c413 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -695,9 +695,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekrānuzņēmumi"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Vispārīgi ziņojumi"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Krātuve"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Tūlītējās lietotnes"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Tūlītējām lietotnēm nav nepieciešama instalēšana."</string>
<string name="app_info" msgid="6856026610594615344">"Lietotnes informācija"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index dc5f44d..cdadb0a 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Слики од екранот"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Општи пораки"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Меморија"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Инстант апликации"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Инстант апликациите нема потреба да се инсталираат."</string>
<string name="app_info" msgid="6856026610594615344">"Информации за апликација"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 4e3da1b..38769cf 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"സ്ക്രീൻഷോട്ടുകൾ"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"പൊതുവായ സന്ദേശങ്ങൾ"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"സ്റ്റോറേജ്"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"ഇൻസ്റ്റന്റ് ആപ്പ്"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"ഇൻസ്റ്റന്റ് ആപ്പിന് ഇൻസ്റ്റലേഷൻ ആവശ്യമില്ല."</string>
<string name="app_info" msgid="6856026610594615344">"ആപ്പ് വിവരം"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 1ec28b2..206a9cc 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Дэлгэцийн зураг дарах"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Энгийн зурвас"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Хадгалах сан"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Шуурхай апп"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Шуурхай аппыг суулгах шаардлагагүй."</string>
<string name="app_info" msgid="6856026610594615344">"Апп-н мэдээлэл"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index cce2635..266d0c9 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"स्क्रीनशॉट"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"सर्वसाधारण संदेश"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"संचय"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"इन्सटंट अॅप्स"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"इन्सटंट अॅप्सना स्थापनेची आवश्यकता नसते."</string>
<string name="app_info" msgid="6856026610594615344">"अॅप माहिती"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index afc9541..441b4c1 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Tangkapan skrin"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Mesej Am"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Storan"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Apl Segera"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Apl segera tidak memerlukan pemasangan."</string>
<string name="app_info" msgid="6856026610594615344">"Maklumat apl"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 26cc72c..9b9359e 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"မျက်နှာပြင်ဓာတ်ပုံများ"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"အထွေထွေ မက်ဆေ့ဂျ်များ"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"သိုလှောင်မှုများ"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"ချက်ခြင်းသုံးအက်ပ်များကို ထည့်သွင်းစရာမလိုပါ။"</string>
<string name="app_info" msgid="6856026610594615344">"အက်ပ်အချက်အလက်"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index ccee80e..1744729 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Skjermdumper"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Generelle meldinger"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Lagring"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Du trenger ikke å installere instant-apper."</string>
<string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index cc63dfb..a634b91 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"स्क्रिनशटहरू"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"सामान्य सन्देशहरू"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"भण्डारण"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"तात्कालिक अनुप्रयोगहरू"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"तात्कालिक अनुप्रयोगहरूलाई स्थापना गर्नु पर्दैन|"</string>
<string name="app_info" msgid="6856026610594615344">"अनुप्रयोगका बारे जानकारी"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 3fdf5a4..b5b741c 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Algemene berichten"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Opslag"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant-apps"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Instant-apps hoeven niet te worden geïnstalleerd."</string>
<string name="app_info" msgid="6856026610594615344">"App-info"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index bcdfb4c..abd0a70 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"ਆਮ ਸੁਨੇਹੇ"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"ਸਟੋਰੇਜ"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"ਤਤਕਾਲ ਐਪਾਂ"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"ਤਤਕਾਲ ਐਪਾਂ ਨੂੰ ਸਥਾਪਨਾ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ।"</string>
<string name="app_info" msgid="6856026610594615344">"ਐਪ ਜਾਣਕਾਰੀ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index d2bf88e..09159ab 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -698,9 +698,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Zrzuty ekranu"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Wiadomości"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Miejsce"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Aplikacje błyskawiczne"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Aplikacji błyskawicznych nie trzeba instalować."</string>
<string name="app_info" msgid="6856026610594615344">"O aplikacji"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 56ec9bc..19c3c28 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de tela"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Mensagens gerais"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Os Instant Apps não requerem instalação."</string>
<string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 4daf104..d221f3a 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de ecrã"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Mensagens gerais"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Aplicações instantâneas"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"As Aplicações instantâneas não requerem instalação."</string>
<string name="app_info" msgid="6856026610594615344">"Informações da aplicação"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 56ec9bc..19c3c28 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de tela"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Mensagens gerais"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Os Instant Apps não requerem instalação."</string>
<string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 2315e3b..2f32f6b 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -697,9 +697,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturi de ecran"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Mesaje generale"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Stocare"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Aplicații instantanee"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Aplicațiile instantanee nu necesită instalare."</string>
<string name="app_info" msgid="6856026610594615344">"Informații despre aplicație"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index ab26879..744e322 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -700,9 +700,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоты"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Сообщения"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Хранилище"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Приложения с мгновенным запуском"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Приложения с мгновенным запуском не требуется устанавливать."</string>
<string name="app_info" msgid="6856026610594615344">"О приложении"</string>
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 5040eb7..1b60299 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"තිර රු"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"පොදු පණිවිඩ"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"ගබඩාව"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"ක්ෂණික යෙදුම්"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"ක්ෂණික යෙදුම් ස්ථාපනය කිරීම අවශ්ය නොවේ."</string>
<string name="app_info" msgid="6856026610594615344">"යෙදුම් තොරතුරු"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 5e163c2..4ff18ba 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -700,9 +700,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Snímky obrazovky"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Všeobecné správy"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Úložisko"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Okamžité aplikácie"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Okamžité aplikácie nevyžadujú inštaláciu."</string>
<string name="app_info" msgid="6856026610594615344">"Info o aplikácii"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index ee33c0b..a689699 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -700,9 +700,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Posnetki zaslona"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Splošna sporočila"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Shramba"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Aplikacije brez nameščanja"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Aplikacij brez nameščanja ni treba namestiti."</string>
<string name="app_info" msgid="6856026610594615344">"Podatki o aplikaciji"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index aab5942..757714fa 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Pamjet e ekranit"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Mesazhe të përgjithshme"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Hapësira ruajtëse"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Aplikacionet e çastit"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Aplikacionet e çastit nuk kërkojnë instalim."</string>
<string name="app_info" msgid="6856026610594615344">"Informacioni mbi aplikacionin"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 0d6aa7b..f02e935 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -695,9 +695,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Снимци екрана"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Опште поруке"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Меморијски простор"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Инстант апликације"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Инстант апликације не захтевају инсталацију."</string>
<string name="app_info" msgid="6856026610594615344">"Информације о апликацији"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index fb8df95..6778c73 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Skärmdumpar"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Allmänna meddelanden"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Lagring"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Snabbappar behöver inte installeras."</string>
<string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 15cc6aa..f97a582 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Picha za skrini"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Ujumbe wa Jumla"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Hifadhi"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Programu Zinazofunguka Papo Hapo"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Huhitaji kusakinisha programu zinazofunguka papo hapo."</string>
<string name="app_info" msgid="6856026610594615344">"Maelezo ya programu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 20ba620..c7166bd 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"ஸ்கிரீன் ஷாட்டுகள்"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"பொதுச் செய்திகள்"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"சேமிப்பிடம்"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"இன்ஸ்டண்ட் பயன்பாடுகள்"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"இன்ஸ்டண்ட் பயன்பாடுகளுக்கு நிறுவல் தேவையில்லை."</string>
<string name="app_info" msgid="6856026610594615344">"பயன்பாட்டுத் தகவல்"</string>
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index e824a35..e55fa84 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"స్క్రీన్షాట్లు"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"సాధారణ సందేశాలు"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"నిల్వ"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"తక్షణ అనువర్తనాలు"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"తక్షణ అనువర్తనాలకు ఇన్స్టాలేషన్ అవసరం లేదు."</string>
<string name="app_info" msgid="6856026610594615344">"అనువర్తన సమాచారం"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 667b106..c501195 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"ภาพหน้าจอ"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"ข้อความทั่วไป"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"พื้นที่เก็บข้อมูล"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant App"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Instant Apps ไม่ต้องใช้การติดตั้ง"</string>
<string name="app_info" msgid="6856026610594615344">"ข้อมูลแอป"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 2f6fdb2..1789606 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Mga Screenshot"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Mga Pangkalahatang Mensahe"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Hindi kailangang i-install ang mga instant na app."</string>
<string name="app_info" msgid="6856026610594615344">"Impormasyon ng app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index b2e7365..7675450 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekran görüntüleri"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Genel Mesajlar"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Depolama alanı"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Hazır Uygulamalar"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Hazır uygulamaların yüklenmesi gerekmez."</string>
<string name="app_info" msgid="6856026610594615344">"Uygulama bilgileri"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 7eb84e4..774a663 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -700,9 +700,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Знімки екрана"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Загальні повідомлення"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Пам’ять"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Додатки з миттєвим запуском"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Додатки з миттєвим запуском не потрібно встановлювати."</string>
<string name="app_info" msgid="6856026610594615344">"Про додаток"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 6a0b92b..ee42e12 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"اسکرین شاٹس"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"عمومی پیغامات"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"اسٹوریج"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"فوری ایپس"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"فوری ایپس کو انسٹالیشن کی ضرورت نہیں ہے۔"</string>
<string name="app_info" msgid="6856026610594615344">"ایپ کی معلومات"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 810902d..28bb21a 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Skrinshotlar"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Umumiy xabarlar"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Xotira"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Darhol ochiladigan ilovalar"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Darhol ochiladigan ilovalarni o‘rnatish shart emas."</string>
<string name="app_info" msgid="6856026610594615344">"Ilova haqida"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index a3ac98e..82b614d 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Ảnh chụp màn hình"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Thông báo chung"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Bộ nhớ"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Ứng dụng tức thì"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Ứng dụng tức thì không yêu cầu cài đặt."</string>
<string name="app_info" msgid="6856026610594615344">"Thông tin ứng dụng"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 30db51a..9c7435a 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"屏幕截图"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"常规消息"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"存储空间"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"免安装应用"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"免安装应用无需安装就能使用。"</string>
<string name="app_info" msgid="6856026610594615344">"应用信息"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index ee1dbb7..26fc99b 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -694,9 +694,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"螢幕擷取畫面"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"一般訊息"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"儲存空間"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"即時應用程式"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"即時應用程式無需安裝即可使用。"</string>
<string name="app_info" msgid="6856026610594615344">"應用程式資料"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 35468dd..fc756f4 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"螢幕擷取畫面"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"一般訊息"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"儲存空間"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"免安裝應用程式"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"免安裝應用程式不必安裝就能使用。"</string>
<string name="app_info" msgid="6856026610594615344">"應用程式資訊"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 6007ea2..38580ec 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -692,9 +692,7 @@
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Izithombe-skrini"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Imilayezo ejwayelekile"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Isitoreji"</string>
- <!-- no translation found for instant_apps (6647570248119804907) -->
- <skip />
- <!-- no translation found for instant_apps_message (8116608994995104836) -->
- <skip />
+ <string name="instant_apps" msgid="6647570248119804907">"Izinhlelo zokusebenza ezisheshayo"</string>
+ <string name="instant_apps_message" msgid="8116608994995104836">"Izinhlelo zokusebenza ezisheshayo azidingi ukufakwa."</string>
<string name="app_info" msgid="6856026610594615344">"Ulwazi lohlelo lokusebenza"</string>
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 407cddf..f461bb3 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -27,7 +27,6 @@
<color name="notification_list_shadow_top">#80000000</color>
<drawable name="heads_up_notification_bg_pressed">#ff33B5E5</drawable>
<color name="qs_batterymeter_frame_color">#FF404040</color>
- <color name="system_warning_color">@*android:color/system_error</color>
<color name="qs_tile_divider">#29ffffff</color><!-- 16% white -->
<color name="qs_subhead">#99FFFFFF</color><!-- 60% white -->
<color name="qs_detail_button">@*android:color/quaternary_device_default_settings</color>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 48b7664..9168256 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -30,7 +30,7 @@
<!-- Recents theme -->
<style name="RecentsTheme.Wallpaper">
- <item name="android:windowBackground">@color/transparent</item>
+ <item name="android:windowBackground">@*android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowShowWallpaper">true</item>
<item name="android:windowDisablePreview">true</item>
@@ -52,7 +52,7 @@
<!-- Theme used for the activity that shows when the system forced an app to be resizable -->
<style name="ForcedResizableTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
<item name="android:windowBackground">@drawable/forced_resizable_background</item>
- <item name="android:statusBarColor">@color/transparent</item>
+ <item name="android:statusBarColor">@*android:color/transparent</item>
<item name="android:windowAnimationStyle">@style/Animation.ForcedResizable</item>
</style>
@@ -70,7 +70,7 @@
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowBackground">@null</item>
<item name="android:colorBackgroundCacheHint">@null</item>
- <item name="android:statusBarColor">@color/transparent</item>
+ <item name="android:statusBarColor">@*android:color/transparent</item>
<item name="android:windowAnimationStyle">@style/Animation.PipPhoneOverlayControl</item>
</style>
@@ -164,7 +164,7 @@
<style name="TextAppearance.QS.Warning">
<item name="android:textSize">14sp</item>
- <item name="android:textColor">@color/system_warning_color</item>
+ <item name="android:textColor">?android:attr/colorError</item>
</style>
<style name="TextAppearance.QS.DetailButton">
@@ -366,7 +366,7 @@
</style>
<style name="TextAppearance.NotificationGuts.SecondaryWarning">
- <item name="android:textColor">@color/system_warning_color</item>
+ <item name="android:textColor">?android:attr/colorError</item>
<item name="android:textSize">12sp</item>
</style>
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index f1e7d53..ac7ab9d 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -47,6 +47,8 @@
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
+import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.ExtensionControllerImpl;
import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.FlashlightControllerImpl;
import com.android.systemui.statusbar.policy.HotspotController;
@@ -233,6 +235,9 @@
mProviders.put(FragmentService.class, () ->
new FragmentService(mContext));
+ mProviders.put(ExtensionController.class, () ->
+ new ExtensionControllerImpl());
+
// Put all dependencies above here so the factory can override them if it wants.
SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 20866c0..8f7a81c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -337,12 +337,11 @@
* Moves the PIPed activity to the fullscreen and closes PIP system UI.
*/
void movePipToFullscreen() {
- mState = STATE_NO_PIP;
mPipTaskId = TASK_ID_NO_PIP;
for (int i = mListeners.size() - 1; i >= 0; --i) {
mListeners.get(i).onMoveToFullscreen();
}
- resizePinnedStack(mState);
+ resizePinnedStack(STATE_NO_PIP);
updatePipVisibility(false);
}
@@ -388,6 +387,7 @@
if (DEBUG) Log.d(TAG, "resizePinnedStack() state=" + state);
boolean wasRecentsShown =
(mState == STATE_PIP_RECENTS || mState == STATE_PIP_RECENTS_FOCUSED);
+ boolean wasStateNoPip = (mState == STATE_NO_PIP);
mState = state;
for (int i = mListeners.size() - 1; i >= 0; --i) {
mListeners.get(i).onPipResizeAboutToStart();
@@ -401,6 +401,11 @@
switch (mState) {
case STATE_NO_PIP:
mCurrentPipBounds = null;
+ // If the state was already STATE_NO_PIP, then do not resize the stack below as it
+ // will not exist
+ if (wasStateNoPip) {
+ return;
+ }
break;
case STATE_PIP_MENU:
mCurrentPipBounds = mMenuModePipBounds;
@@ -418,18 +423,16 @@
mCurrentPipBounds = mPipBounds;
break;
}
- if (mCurrentPipBounds != null) {
- try {
- int animationDurationMs = -1;
- if (wasRecentsShown
- && (mState == STATE_PIP_RECENTS || mState == STATE_PIP_RECENTS_FOCUSED)) {
- animationDurationMs = mRecentsFocusChangedAnimationDurationMs;
- }
- mActivityManager.resizeStack(PINNED_STACK_ID, mCurrentPipBounds,
- true, true, true, animationDurationMs);
- } catch (RemoteException e) {
- Log.e(TAG, "resizeStack failed", e);
+ try {
+ int animationDurationMs = -1;
+ if (wasRecentsShown
+ && (mState == STATE_PIP_RECENTS || mState == STATE_PIP_RECENTS_FOCUSED)) {
+ animationDurationMs = mRecentsFocusChangedAnimationDurationMs;
}
+ mActivityManager.resizeStack(PINNED_STACK_ID, mCurrentPipBounds,
+ true, true, true, animationDurationMs);
+ } catch (RemoteException e) {
+ Log.e(TAG, "resizeStack failed", e);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginManager.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginManager.java
index 8b4bd7b..0c3e40c 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginManager.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginManager.java
@@ -133,14 +133,7 @@
public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls,
boolean allowMultiple) {
- ProvidesInterface info = cls.getDeclaredAnnotation(ProvidesInterface.class);
- if (info == null) {
- throw new RuntimeException(cls + " doesn't provide an interface");
- }
- if (TextUtils.isEmpty(info.action())) {
- throw new RuntimeException(cls + " doesn't provide an action");
- }
- addPluginListener(info.action(), listener, cls, allowMultiple);
+ addPluginListener(getAction(cls), listener, cls, allowMultiple);
}
public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
@@ -285,6 +278,17 @@
return new PluginContextWrapper(mContext.createApplicationContext(info, 0), classLoader);
}
+ public static <P> String getAction(Class<P> cls) {
+ ProvidesInterface info = cls.getDeclaredAnnotation(ProvidesInterface.class);
+ if (info == null) {
+ throw new RuntimeException(cls + " doesn't provide an interface");
+ }
+ if (TextUtils.isEmpty(info.action())) {
+ throw new RuntimeException(cls + " doesn't provide an action");
+ }
+ return info.action();
+ }
+
private class AllPluginClassLoader extends ClassLoader {
public AllPluginClassLoader(ClassLoader classLoader) {
super(classLoader);
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 09ce2ad..daf0622 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -39,6 +39,7 @@
import android.util.Slog;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -175,8 +176,7 @@
.setOnlyAlertOnce(true)
.setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_WARNING))
.setVisibility(Notification.VISIBILITY_PUBLIC)
- .setColor(mContext.getColor(
- com.android.internal.R.color.battery_saver_mode_color));
+ .setColor(Utils.getColorAttr(mContext, android.R.attr.colorError));
if (hasBatterySettings()) {
nb.setContentIntent(pendingBroadcast(ACTION_SHOW_BATTERY_SETTINGS));
}
@@ -245,8 +245,7 @@
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setContentIntent(pendingBroadcast(ACTION_CLICKED_TEMP_WARNING))
.setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_TEMP_WARNING))
- .setColor(mContext.getColor(
- com.android.internal.R.color.battery_saver_mode_color));
+ .setColor(Utils.getColorAttr(mContext, android.R.attr.colorError));
SystemUI.overrideNotificationAppName(mContext, nb);
final Notification n = nb.build();
mNoMan.notifyAsUser(TAG_TEMPERATURE, SystemMessage.NOTE_HIGH_TEMP, n, UserHandle.ALL);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
index dad8bea..65238b1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
@@ -203,16 +203,28 @@
}
}
});
- final ImageView disconnect = (ImageView) view.findViewById(android.R.id.icon2);
- disconnect.setVisibility(item.canDisconnect ? VISIBLE : GONE);
- disconnect.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mCallback != null) {
- mCallback.onDetailItemDisconnect(item);
+
+ final ImageView icon2 = (ImageView) view.findViewById(android.R.id.icon2);
+ if (item.canDisconnect) {
+ icon2.setImageResource(R.drawable.ic_qs_cancel);
+ icon2.setVisibility(VISIBLE);
+ icon2.setClickable(true);
+ icon2.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mCallback != null) {
+ mCallback.onDetailItemDisconnect(item);
+ }
}
- }
- });
+ });
+ } else if (item.icon2 != -1) {
+ icon2.setVisibility(VISIBLE);
+ icon2.setImageResource(item.icon2);
+ icon2.setClickable(false);
+ } else {
+ icon2.setVisibility(GONE);
+ }
+
return view;
}
};
@@ -245,6 +257,7 @@
public CharSequence line2;
public Object tag;
public boolean canDisconnect;
+ public int icon2 = -1;
}
public interface Callback {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index dea56aa1..cdde6ea 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -87,7 +87,7 @@
private void setTileIcon() {
try {
PackageManager pm = mContext.getPackageManager();
- int flags = PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+ int flags = PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.MATCH_DIRECT_BOOT_AWARE;
if (isSystemApp(pm)) {
flags |= PackageManager.MATCH_DISABLED_COMPONENTS;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
index c7b6aea..9cd79f8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -91,7 +91,7 @@
formatBytes(info.usageLevel));
bottom = res.getString(R.string.quick_settings_cellular_detail_data_limit,
formatBytes(info.limitLevel));
- usageColor = mContext.getColor(R.color.system_warning_color);
+ usageColor = Utils.getDefaultColor(mContext, android.R.attr.colorError);
}
if (usageColor == 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 90a9db6..796967c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -372,9 +372,9 @@
item.icon = mWifiController.getIcon(ap);
item.line1 = ap.getSsid();
item.line2 = ap.isActive() ? ap.getSummary() : null;
- item.overlay = ap.getSecurity() != AccessPoint.SECURITY_NONE
- ? mContext.getDrawable(R.drawable.qs_ic_wifi_lock)
- : null;
+ item.icon2 = ap.getSecurity() != AccessPoint.SECURITY_NONE
+ ? R.drawable.qs_ic_wifi_lock
+ : -1;
items[i] = item;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index 02b0113..e0dac09 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -197,6 +197,7 @@
bm.getHeight() - thumbnailData.insets.top - thumbnailData.insets.bottom);
mThumbnailData = thumbnailData;
updateThumbnailMatrix();
+ updateThumbnailPaintFilter();
} else {
mBitmapShader = null;
mDrawPaint.setShader(null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index bc992d8..fb92a67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -42,6 +42,7 @@
import com.android.internal.app.IBatteryStats;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
@@ -365,7 +366,7 @@
if (!updateMonitor.isUnlockingWithFingerprintAllowed()) {
return;
}
- int errorColor = mContext.getResources().getColor(R.color.system_warning_color, null);
+ int errorColor = Utils.getColorError(mContext);
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mStatusBarKeyguardViewManager.showBouncerMessage(helpString, errorColor);
} else if (updateMonitor.isDeviceInteractive()
@@ -388,7 +389,7 @@
|| msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
return;
}
- int errorColor = mContext.getResources().getColor(R.color.system_warning_color, null);
+ int errorColor = Utils.getColorError(mContext);
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
// When swiping up right after receiving a fingerprint error, the bouncer calls
// authenticate leading to the same message being shown again on the bouncer.
@@ -411,8 +412,7 @@
@Override
public void onScreenTurnedOn() {
if (mMessageToShowOnScreenOn != null) {
- int errorColor = mContext.getResources().getColor(R.color.system_warning_color,
- null);
+ int errorColor = Utils.getColorError(mContext);
showTransientIndication(mMessageToShowOnScreenOn, errorColor);
// We want to keep this message around in case the screen was off
mHandler.removeMessages(MSG_HIDE_TRANSIENT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 89041f9..67be99e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -83,6 +83,8 @@
private int mWifiStrengthId = 0;
private int mLastWifiBadgeId = -1;
private int mLastWifiStrengthId = -1;
+ private int mWifiActivityId = 0;
+ private int mLastWifiActivityId = -1;
private boolean mIsAirplaneMode = false;
private int mAirplaneIconId = 0;
private int mLastAirplaneIconId = -1;
@@ -97,6 +99,7 @@
ViewGroup mEthernetGroup, mWifiGroup;
View mNoSimsCombo;
ImageView mVpn, mEthernet, mWifi, mAirplane, mNoSims, mEthernetDark, mWifiDark, mNoSimsDark;
+ ImageView mWifiActivity;
View mWifiAirplaneSpacer;
View mWifiSignalSpacer;
LinearLayout mMobileSignalGroup;
@@ -177,6 +180,7 @@
mWifiGroup = (ViewGroup) findViewById(R.id.wifi_combo);
mWifi = (ImageView) findViewById(R.id.wifi_signal);
mWifiDark = (ImageView) findViewById(R.id.wifi_signal_dark);
+ mWifiActivity = (ImageView) findViewById(R.id.wifi_inout);
mAirplane = (ImageView) findViewById(R.id.airplane);
mNoSims = (ImageView) findViewById(R.id.no_sims);
mNoSimsDark = (ImageView) findViewById(R.id.no_sims_dark);
@@ -267,6 +271,10 @@
mWifiStrengthId = statusIcon.icon;
mWifiBadgeId = statusIcon.iconOverlay;
mWifiDescription = statusIcon.contentDescription;
+ mWifiActivityId = activityIn && activityOut ? R.drawable.stat_sys_wifi_inout
+ : activityIn ? R.drawable.stat_sys_wifi_in
+ : activityOut ? R.drawable.stat_sys_wifi_out
+ : 0;
apply();
}
@@ -286,6 +294,10 @@
state.mMobileTypeDescription = typeContentDescription;
state.mIsMobileTypeIconWide = statusType != 0 && isWide;
state.mRoaming = roaming;
+ state.mMobileActivityId = activityIn && activityOut ? R.drawable.stat_sys_signal_inout
+ : activityIn ? R.drawable.stat_sys_signal_in
+ : activityOut ? R.drawable.stat_sys_signal_out
+ : 0;
apply();
}
@@ -409,6 +421,10 @@
mLastWifiStrengthId = -1;
mLastWifiBadgeId = -1;
}
+ if (mWifiActivity != null) {
+ mWifiActivity.setImageDrawable(null);
+ mLastWifiActivityId = -1;
+ }
for (PhoneState state : mPhoneStates) {
if (state.mMobile != null) {
@@ -425,6 +441,10 @@
state.mMobileType.setImageDrawable(null);
state.mLastMobileTypeId = -1;
}
+ if (state.mMobileActivity != null) {
+ state.mMobileActivity.setImageDrawable(null);
+ state.mLastMobileActivityId = -1;
+ }
}
if (mAirplane != null) {
@@ -484,6 +504,12 @@
mLastWifiStrengthId = mWifiStrengthId;
mLastWifiBadgeId = mWifiBadgeId;
}
+ if (mWifiActivityId != mLastWifiActivityId) {
+ if (mWifiActivityId != 0) {
+ setIconForView(mWifiActivity, mWifiActivityId);
+ }
+ mLastWifiActivityId = mWifiActivityId;
+ }
mWifiGroup.setContentDescription(mWifiDescription);
mWifiGroup.setVisibility(View.VISIBLE);
} else {
@@ -495,6 +521,8 @@
(mWifiVisible ? "VISIBLE" : "GONE"),
mWifiStrengthId));
+ mWifiActivity.setVisibility(mWifiActivityId != 0 ? View.VISIBLE : View.GONE);
+
boolean anyMobileVisible = false;
int firstMobileTypeId = 0;
for (PhoneState state : mPhoneStates) {
@@ -603,6 +631,8 @@
applyDarkIntensity(
DarkIconDispatcher.getDarkIntensity(mTintArea, mWifi, mDarkIntensity),
mWifi, mWifiDark);
+ setTint(mWifiActivity,
+ DarkIconDispatcher.getTint(mTintArea, mWifiActivity, mIconTint));
applyDarkIntensity(
DarkIconDispatcher.getDarkIntensity(mTintArea, mEthernet, mDarkIntensity),
mEthernet, mEthernetDark);
@@ -627,15 +657,17 @@
private class PhoneState {
private final int mSubId;
private boolean mMobileVisible = false;
- private int mMobileStrengthId = 0, mMobileTypeId = 0;
+ private int mMobileStrengthId = 0, mMobileTypeId = 0, mMobileActivityId = 0;
private int mLastMobileStrengthId = -1;
private int mLastMobileTypeId = -1;
+ private int mLastMobileActivityId = -1;
private boolean mIsMobileTypeIconWide;
private String mMobileDescription, mMobileTypeDescription;
private ViewGroup mMobileGroup;
private ImageView mMobile, mMobileDark, mMobileType, mMobileRoaming;
public boolean mRoaming;
+ private ImageView mMobileActivity;
public PhoneState(int subId, Context context) {
ViewGroup root = (ViewGroup) LayoutInflater.from(context)
@@ -650,6 +682,7 @@
mMobileDark = (ImageView) root.findViewById(R.id.mobile_signal_dark);
mMobileType = (ImageView) root.findViewById(R.id.mobile_type);
mMobileRoaming = (ImageView) root.findViewById(R.id.mobile_roaming);
+ mMobileActivity = (ImageView) root.findViewById(R.id.mobile_inout);
}
public boolean apply(boolean isSecondaryIcon) {
@@ -664,6 +697,11 @@
mMobileType.setImageResource(mMobileTypeId);
mLastMobileTypeId = mMobileTypeId;
}
+
+ if (mLastMobileActivityId != mMobileActivityId) {
+ mMobileActivity.setImageResource(mMobileActivityId);
+ mLastMobileActivityId = mMobileActivityId;
+ }
mMobileGroup.setContentDescription(mMobileTypeDescription
+ " " + mMobileDescription);
mMobileGroup.setVisibility(View.VISIBLE);
@@ -686,6 +724,7 @@
mMobileType.setVisibility(mMobileTypeId != 0 ? View.VISIBLE : View.GONE);
mMobileRoaming.setVisibility(mRoaming ? View.VISIBLE : View.GONE);
+ mMobileActivity.setVisibility(mMobileActivityId != 0 ? View.VISIBLE : View.GONE);
return mMobileVisible;
}
@@ -747,6 +786,8 @@
setTint(mMobileType, DarkIconDispatcher.getTint(tintArea, mMobileType, tint));
setTint(mMobileRoaming, DarkIconDispatcher.getTint(tintArea, mMobileRoaming,
tint));
+ setTint(mMobileActivity,
+ DarkIconDispatcher.getTint(tintArea, mMobileActivity, tint));
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index ed71e57..f3c2bc5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -33,6 +33,7 @@
import android.util.Log;
import android.view.View;
+import com.android.settingslib.Utils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -167,7 +168,7 @@
mSemiTransparent = context.getColor(
com.android.internal.R.color.system_bar_background_semi_transparent);
mTransparent = context.getColor(R.color.system_bar_background_transparent);
- mWarning = context.getColor(com.android.internal.R.color.battery_saver_mode_color);
+ mWarning = Utils.getColorAttr(context, android.R.attr.colorError);
}
mGradient = context.getDrawable(gradientResourceId);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 8f63d45..2538bdd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -19,9 +19,10 @@
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON;
import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK;
+import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON;
import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_UNLOCK;
-import static com.android.systemui.tuner.LockscreenFragment.getIntentButton;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -79,9 +80,12 @@
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.policy.AccessibilityController;
+import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.ExtensionController.Extension;
import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.tuner.LockscreenFragment;
+import com.android.systemui.tuner.LockscreenFragment.LockButtonFactory;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -91,8 +95,7 @@
*/
public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
UnlockMethodCache.OnUnlockMethodChangedListener,
- AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener,
- Tunable {
+ AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener {
final static String TAG = "StatusBar/KeyguardBottomAreaView";
@@ -159,12 +162,10 @@
private Drawable mLeftAssistIcon;
private IntentButton mRightButton = new DefaultRightButton();
- private IntentButton mRightDefault = mRightButton;
- private IntentButton mRightPlugin;
+ private Extension<IntentButton> mRightExtension;
private String mRightButtonStr;
private IntentButton mLeftButton = new DefaultLeftButton();
- private IntentButton mLeftDefault = mLeftButton;
- private IntentButton mLeftPlugin;
+ private Extension<IntentButton> mLeftExtension;
private String mLeftButtonStr;
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
private boolean mDozing;
@@ -261,21 +262,28 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mAccessibilityController.addStateChangedCallback(this);
- Dependency.get(PluginManager.class).addPluginListener(RIGHT_BUTTON_PLUGIN,
- mRightListener, IntentButtonProvider.class, false /* Only allow one */);
- Dependency.get(PluginManager.class).addPluginListener(LEFT_BUTTON_PLUGIN,
- mLeftListener, IntentButtonProvider.class, false /* Only allow one */);
- Dependency.get(TunerService.class).addTunable(this, LockscreenFragment.LOCKSCREEN_LEFT_BUTTON,
- LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON);
+ mRightExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class)
+ .withPlugin(IntentButtonProvider.class, RIGHT_BUTTON_PLUGIN,
+ p -> p.getIntentButton())
+ .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_RIGHT_BUTTON))
+ .withDefault(() -> new DefaultRightButton())
+ .withCallback(button -> setRightButton(button))
+ .build();
+ mLeftExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class)
+ .withPlugin(IntentButtonProvider.class, LEFT_BUTTON_PLUGIN,
+ p -> p.getIntentButton())
+ .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_LEFT_BUTTON))
+ .withDefault(() -> new DefaultLeftButton())
+ .withCallback(button -> setLeftButton(button))
+ .build();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mAccessibilityController.removeStateChangedCallback(this);
- Dependency.get(PluginManager.class).removePluginListener(mRightListener);
- Dependency.get(PluginManager.class).removePluginListener(mLeftListener);
- Dependency.get(TunerService.class).removeTunable(this);
+ mRightExtension.destroy();
+ mLeftExtension.destroy();
}
private void initAccessibility() {
@@ -790,63 +798,21 @@
inflateCameraPreview();
}
- @Override
- public void onTuningChanged(String key, String newValue) {
- if (LockscreenFragment.LOCKSCREEN_LEFT_BUTTON.equals(key)) {
- mLeftButtonStr = newValue;
- mLeftIsVoiceAssist = TextUtils.isEmpty(mLeftButtonStr) && mLeftPlugin == null;
- mLeftButton = getIntentButton(mContext, mLeftButtonStr, mLeftPlugin, mLeftDefault);
- updateLeftAffordance();
- } else {
- mRightButtonStr = newValue;
- mRightButton = getIntentButton(mContext, mRightButtonStr, mRightPlugin, mRightDefault);
- updateRightAffordanceIcon();
- updateCameraVisibility();
- inflateCameraPreview();
- }
- }
-
private void setRightButton(IntentButton button) {
- mRightPlugin = button;
- mRightButton = getIntentButton(mContext, mRightButtonStr, mRightPlugin, mRightDefault);
+ mRightButton = button;
updateRightAffordanceIcon();
updateCameraVisibility();
inflateCameraPreview();
}
private void setLeftButton(IntentButton button) {
- mLeftPlugin = button;
- mLeftButton = getIntentButton(mContext, mLeftButtonStr, mLeftPlugin, mLeftDefault);
- mLeftIsVoiceAssist = false;
+ mLeftButton = button;
+ if (!(mLeftButton instanceof DefaultLeftButton)) {
+ mLeftIsVoiceAssist = false;
+ }
updateLeftAffordance();
}
- private final PluginListener<IntentButtonProvider> mRightListener =
- new PluginListener<IntentButtonProvider>() {
- @Override
- public void onPluginConnected(IntentButtonProvider plugin, Context pluginContext) {
- setRightButton(plugin.getIntentButton());
- }
-
- @Override
- public void onPluginDisconnected(IntentButtonProvider plugin) {
- setRightButton(null);
- }
- };
-
- private final PluginListener<IntentButtonProvider> mLeftListener =
- new PluginListener<IntentButtonProvider>() {
- @Override
- public void onPluginConnected(IntentButtonProvider plugin, Context pluginContext) {
- setLeftButton(plugin.getIntentButton());
- }
-
- @Override
- public void onPluginDisconnected(IntentButtonProvider plugin) {
- setLeftButton(null);
- }
- };
-
public void setDozing(boolean dozing, boolean animate) {
mDozing = dozing;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index 0e7b2f3..c070869 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -29,6 +29,7 @@
import android.os.UserManager;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
+import android.telephony.SubscriptionInfo;
import android.util.AttributeSet;
import android.util.SparseBooleanArray;
import android.view.View;
@@ -64,6 +65,8 @@
import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
import com.android.systemui.tuner.TunerService;
+import java.util.List;
+
public class QuickStatusBarHeader extends BaseStatusBarHeader implements
NextAlarmChangeCallback, OnClickListener, OnUserInfoChangedListener, EmergencyListener,
SignalCallback {
@@ -440,10 +443,20 @@
}
}
+ @Override
+ public void setSubs(List<SubscriptionInfo> subs) {
+ mRoamingsBySubId.clear();
+ updateRoaming();
+ }
+
public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
String description, boolean isWide, int subId, boolean roaming) {
mRoamingsBySubId.put(subId, roaming);
+ updateRoaming();
+ }
+
+ private void updateRoaming() {
boolean isRoaming = calculateRoaming();
if (mIsRoaming != isRoaming) {
mIsRoaming = isRoaming;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 213b0aa..a6b145e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -5742,9 +5742,8 @@
if (snoozeOption.criterion != null) {
mNotificationListener.snoozeNotification(sbn.getKey(), snoozeOption.criterion.getId());
} else {
- GregorianCalendar snoozeUntil = new GregorianCalendar();
- snoozeUntil.add(Calendar.MINUTE, snoozeOption.snoozeForMinutes);
- mNotificationListener.snoozeNotification(sbn.getKey(), snoozeUntil.getTimeInMillis());
+ mNotificationListener.snoozeNotification(sbn.getKey(),
+ snoozeOption.snoozeForMinutes * 60 * 1000);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java
new file mode 100644
index 0000000..eaf8925
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.plugins.Plugin;
+
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+/**
+ * Utility class used to select between a plugin, tuner settings, and a default implementation
+ * of an interface.
+ */
+public interface ExtensionController {
+
+ <T> ExtensionBuilder<T> newExtension(Class<T> cls);
+
+ interface Extension<T> {
+ T get();
+ void destroy();
+ }
+
+ interface ExtensionBuilder<T> {
+ ExtensionBuilder<T> withTunerFactory(TunerFactory<T> factory);
+ <P extends T> ExtensionBuilder<T> withPlugin(Class<P> cls);
+ <P extends T> ExtensionBuilder<T> withPlugin(Class<P> cls, String action);
+ <P> ExtensionBuilder<T> withPlugin(Class<P> cls, String action,
+ PluginConverter<T, P> converter);
+ ExtensionBuilder<T> withDefault(Supplier<T> def);
+ ExtensionBuilder<T> withCallback(Consumer<T> callback);
+ Extension build();
+ }
+
+ public interface PluginConverter<T, P> {
+ T getInterfaceFromPlugin(P plugin);
+ }
+
+ public interface TunerFactory<T> {
+ String[] keys();
+ T create(Map<String, String> settings);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
new file mode 100644
index 0000000..fefbaa3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
+
+import android.content.Context;
+import android.util.ArrayMap;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+public class ExtensionControllerImpl implements ExtensionController {
+
+ @Override
+ public <T> ExtensionBuilder<T> newExtension(Class<T> cls) {
+ return new ExtensionBuilder<>();
+ }
+
+ private interface Producer<T> {
+ T get();
+ void destroy();
+ }
+
+ private class ExtensionBuilder<T> implements ExtensionController.ExtensionBuilder<T> {
+
+ private ExtensionImpl<T> mExtension = new ExtensionImpl<>();
+
+ @Override
+ public ExtensionController.ExtensionBuilder<T> withTunerFactory(TunerFactory<T> factory) {
+ mExtension.addTunerFactory(factory, factory.keys());
+ return this;
+ }
+
+ @Override
+ public <P extends T> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls) {
+ return withPlugin(cls, PluginManager.getAction(cls));
+ }
+
+ @Override
+ public <P extends T> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls,
+ String action) {
+ return withPlugin(cls, action, null);
+ }
+
+ @Override
+ public <P> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls,
+ String action, PluginConverter<T, P> converter) {
+ mExtension.addPlugin(action, cls, converter);
+ return this;
+ }
+
+ @Override
+ public ExtensionController.ExtensionBuilder<T> withDefault(Supplier<T> def) {
+ mExtension.addDefault(def);
+ return this;
+ }
+
+ @Override
+ public ExtensionController.ExtensionBuilder<T> withCallback(
+ Consumer<T> callback) {
+ mExtension.mCallbacks.add(callback);
+ return this;
+ }
+
+ @Override
+ public ExtensionController.Extension build() {
+ // Manually sort, plugins first, tuners second, defaults last.
+ Collections.sort(mExtension.mProducers, (o1, o2) -> {
+ if (o1 instanceof ExtensionImpl.PluginItem) {
+ if (o2 instanceof ExtensionImpl.PluginItem) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+ if (o1 instanceof ExtensionImpl.TunerItem) {
+ if (o2 instanceof ExtensionImpl.PluginItem) {
+ return 1;
+ } else if (o2 instanceof ExtensionImpl.TunerItem) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+ return 0;
+ });
+ mExtension.notifyChanged();
+ return mExtension;
+ }
+ }
+
+ private class ExtensionImpl<T> implements ExtensionController.Extension<T> {
+ private final ArrayList<Producer<T>> mProducers = new ArrayList<>();
+ private final ArrayList<Consumer<T>> mCallbacks = new ArrayList<>();
+ private T mItem;
+
+ @Override
+ public T get() {
+ return mItem;
+ }
+
+ @Override
+ public void destroy() {
+ for (int i = 0; i < mProducers.size(); i++) {
+ mProducers.get(i).destroy();
+ }
+ }
+
+ private void notifyChanged() {
+ for (int i = 0; i < mProducers.size(); i++) {
+ final T item = mProducers.get(i).get();
+ if (item != null) {
+ mItem = item;
+ break;
+ }
+ }
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).accept(mItem);
+ }
+ }
+
+ public void addDefault(Supplier<T> def) {
+ mProducers.add(new Default(def));
+ }
+
+ public <P> void addPlugin(String action, Class<P> cls, PluginConverter<T, P> converter) {
+ mProducers.add(new PluginItem(action, cls, converter));
+ }
+
+ public void addTunerFactory(TunerFactory<T> factory, String[] keys) {
+ mProducers.add(new TunerItem(factory, factory.keys()));
+ }
+
+ private class PluginItem<P extends Plugin> implements Producer<T>, PluginListener<P> {
+ private final PluginConverter<T, P> mConverter;
+ private T mItem;
+
+ public PluginItem(String action, Class<P> cls, PluginConverter<T, P> converter) {
+ mConverter = converter;
+ Dependency.get(PluginManager.class).addPluginListener(action, this, cls);
+ }
+
+ @Override
+ public void onPluginConnected(P plugin, Context pluginContext) {
+ if (mConverter != null) {
+ mItem = mConverter.getInterfaceFromPlugin(plugin);
+ } else {
+ mItem = (T) plugin;
+ }
+ notifyChanged();
+ }
+
+ @Override
+ public void onPluginDisconnected(P plugin) {
+ mItem = null;
+ notifyChanged();
+ }
+
+ @Override
+ public T get() {
+ return mItem;
+ }
+
+ @Override
+ public void destroy() {
+ Dependency.get(PluginManager.class).removePluginListener(this);
+ }
+ }
+
+ private class TunerItem<T> implements Producer<T>, Tunable {
+ private final TunerFactory<T> mFactory;
+ private final ArrayMap<String, String> mSettings = new ArrayMap<>();
+ private T mItem;
+
+ public TunerItem(TunerFactory<T> factory, String... setting) {
+ mFactory = factory;
+ Dependency.get(TunerService.class).addTunable(this, setting);
+ }
+
+ @Override
+ public T get() {
+ return mItem;
+ }
+
+ @Override
+ public void destroy() {
+ Dependency.get(TunerService.class).removeTunable(this);
+ }
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ mSettings.put(key, newValue);
+ mItem = mFactory.create(mSettings);
+ notifyChanged();
+ }
+ }
+
+ private class Default<T> implements Producer<T> {
+ private final Supplier<T> mSupplier;
+
+ public Default(Supplier<T> supplier) {
+ mSupplier = supplier;
+ }
+
+ @Override
+ public T get() {
+ return mSupplier.get();
+ }
+
+ @Override
+ public void destroy() {
+
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index a85426c..51d931e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -717,6 +717,7 @@
mDemoMode = true;
mDemoInetCondition = mInetCondition;
mDemoWifiState = mWifiSignalController.getState();
+ mDemoWifiState.ssid = "DemoMode";
} else if (mDemoMode && command.equals(COMMAND_EXIT)) {
if (DEBUG) Log.d(TAG, "Exiting demo mode");
mDemoMode = false;
@@ -762,6 +763,25 @@
: Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1);
mDemoWifiState.connected = mDemoWifiState.level >= 0;
}
+ String activity = args.getString("activity");
+ if (activity != null) {
+ switch (activity) {
+ case "inout":
+ mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_INOUT);
+ break;
+ case "in":
+ mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_IN);
+ break;
+ case "out":
+ mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_OUT);
+ break;
+ default:
+ mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_NONE);
+ break;
+ }
+ } else {
+ mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_NONE);
+ }
mDemoWifiState.enabled = show;
mWifiSignalController.notifyListeners();
}
@@ -831,7 +851,23 @@
}
String activity = args.getString("activity");
if (activity != null) {
- controller.setActivity(Integer.parseInt(activity));
+ controller.getState().dataConnected = true;
+ switch (activity) {
+ case "inout":
+ controller.setActivity(TelephonyManager.DATA_ACTIVITY_INOUT);
+ break;
+ case "in":
+ controller.setActivity(TelephonyManager.DATA_ACTIVITY_IN);
+ break;
+ case "out":
+ controller.setActivity(TelephonyManager.DATA_ACTIVITY_OUT);
+ break;
+ default:
+ controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
+ break;
+ }
+ } else {
+ controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
}
controller.getState().enabled = show;
controller.notifyListeners();
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
index 0a962f1..7c98e13 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
@@ -163,7 +163,7 @@
intent.putExtra("sims", "1");
intent.putExtra("nosim", "false");
intent.putExtra("level", "4");
- intent.putExtra("datatypel", "");
+ intent.putExtra("datatype", "lte");
getContext().sendBroadcast(intent);
// Need to send this after so that the sim controller already exists.
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
index 410d3d2..2df1793 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
@@ -52,11 +52,13 @@
import com.android.systemui.plugins.IntentButtonProvider.IntentButton;
import com.android.systemui.statusbar.ScalingDrawableWrapper;
import com.android.systemui.statusbar.phone.ExpandableIndicator;
+import com.android.systemui.statusbar.policy.ExtensionController.TunerFactory;
import com.android.systemui.tuner.ShortcutParser.Shortcut;
import com.android.systemui.tuner.TunerService.Tunable;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.function.Consumer;
public class LockscreenFragment extends PreferenceFragment {
@@ -313,26 +315,39 @@
}
}
- public static IntentButton getIntentButton(Context context, String buttonStr,
- IntentButton plugin, IntentButton def) {
- // Plugin wins.
- if (plugin != null) return plugin;
- // Then tuner options.
- if (!TextUtils.isEmpty(buttonStr)) {
- if (buttonStr.contains("::")) {
- Shortcut shortcut = getShortcutInfo(context, buttonStr);
- if (shortcut != null) {
- return new ShortcutButton(context, shortcut);
- }
- } else if (buttonStr.contains("/")) {
- ActivityInfo info = getActivityinfo(context, buttonStr);
- if (info != null) {
- return new ActivityButton(context, info);
+ public static class LockButtonFactory implements TunerFactory<IntentButton> {
+
+ private final String mKey;
+ private final Context mContext;
+
+ public LockButtonFactory(Context context, String key) {
+ mContext = context;
+ mKey = key;
+ }
+
+ @Override
+ public String[] keys() {
+ return new String[]{mKey};
+ }
+
+ @Override
+ public IntentButton create(Map<String, String> settings) {
+ String buttonStr = settings.get(mKey);
+ if (!TextUtils.isEmpty(buttonStr)) {
+ if (buttonStr.contains("::")) {
+ Shortcut shortcut = getShortcutInfo(mContext, buttonStr);
+ if (shortcut != null) {
+ return new ShortcutButton(mContext, shortcut);
+ }
+ } else if (buttonStr.contains("/")) {
+ ActivityInfo info = getActivityinfo(mContext, buttonStr);
+ if (info != null) {
+ return new ActivityButton(mContext, info);
+ }
}
}
+ return null;
}
- // Then default.
- return def;
}
private static class ShortcutButton implements IntentButton {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 6c454e1..c0e7e80 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -23,7 +23,6 @@
import android.os.MessageQueue;
import android.support.test.InstrumentationRegistry;
import android.util.ArrayMap;
-import android.util.Log;
import com.android.systemui.Dependency.DependencyKey;
import com.android.systemui.utils.TestableContext;
@@ -32,8 +31,6 @@
import org.junit.After;
import org.junit.Before;
-import java.lang.Thread.UncaughtExceptionHandler;
-
/**
* Base class that does System UI specific setup.
*/
@@ -92,8 +89,10 @@
return null;
}
- public <T> void injectMockDependency(Class<T> cls) {
- injectTestDependency(cls, mock(cls));
+ public <T> T injectMockDependency(Class<T> cls) {
+ final T mock = mock(cls);
+ mDependency.injectTestDependency(cls, mock);
+ return mock;
}
public <T> void injectTestDependency(Class<T> cls, T obj) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
index 72f6ca8..b8be4fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
@@ -25,7 +25,7 @@
import org.junit.runner.RunWith;
@RunWith(SysUIRunner.class)
-@RunWithLooper
+@RunWithLooper(setAsMainLooper = true)
public class NotificationMenuRowTest extends LeakCheckedTest {
@Before
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStatusBarHeaderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStatusBarHeaderTest.java
new file mode 100644
index 0000000..99cecff
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStatusBarHeaderTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.R.layout;
+import com.android.systemui.SysUIRunner;
+import com.android.systemui.utils.TestableLooper;
+import com.android.systemui.utils.TestableLooper.RunWithLooper;
+import com.android.systemui.utils.ViewUtils;
+import com.android.systemui.utils.leaks.LeakCheckedTest;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+
+@RunWith(SysUIRunner.class)
+@RunWithLooper(setAsMainLooper = true)
+public class QuickStatusBarHeaderTest extends LeakCheckedTest {
+
+ @Before
+ public void setup() throws NoSuchFieldException, IllegalAccessException {
+ injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
+ }
+
+ @Test
+ @Ignore("Flaky")
+ public void testRoamingStuck() throws Exception {
+ TestableLooper looper = TestableLooper.get(this);
+ assertEquals(Looper.myLooper(), looper.getLooper());
+ assertEquals(Looper.myLooper(), Looper.getMainLooper());
+ QuickStatusBarHeader header = (QuickStatusBarHeader) LayoutInflater.from(mContext).inflate(
+ layout.quick_status_bar_expanded_header, null);
+ header.setExpanded(true);
+
+ ViewUtils.attachView(header);
+ looper.processMessages(1);
+ TextView emergencyText = (TextView) header.findViewById(
+ R.id.header_emergency_calls_only);
+ int subId = 0;
+ header.setMobileDataIndicators(null, null, 0, 0, false,
+ false, null, null, false, subId, true);
+ looper.processAllMessages();
+ assertEquals(mContext.getString(R.string.accessibility_data_connection_roaming),
+ emergencyText.getText());
+ assertEquals(View.VISIBLE, emergencyText.getVisibility());
+
+ header.setSubs(new ArrayList<>());
+ subId = 1;
+ header.setMobileDataIndicators(null, null, 0, 0, false,
+ false, null, null, false, subId, false);
+ looper.processAllMessages();
+
+ assertNotEquals(View.VISIBLE, emergencyText.getVisibility());
+ assertEquals(Looper.myLooper(), Looper.getMainLooper());
+ ViewUtils.detachView(header);
+ looper.processAllMessages();
+ }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java
new file mode 100644
index 0000000..e3a5ef0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.OverlayPlugin;
+import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.statusbar.policy.ExtensionController.Extension;
+import com.android.systemui.statusbar.policy.ExtensionController.TunerFactory;
+import com.android.systemui.tuner.TunerService;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Map;
+import java.util.function.Consumer;
+
+public class ExtensionControllerTest extends SysuiTestCase {
+
+ private PluginManager mPluginManager;
+ private TunerService mTunerService;
+ private ExtensionController mExtensionController;
+
+ @Before
+ public void setup() {
+ mPluginManager = injectMockDependency(PluginManager.class);
+ mTunerService = injectMockDependency(TunerService.class);
+ mExtensionController = Dependency.get(ExtensionController.class);
+ }
+
+ @Test
+ public void testPlugin() {
+ Extension ext = mExtensionController.newExtension(OverlayPlugin.class)
+ .withPlugin(OverlayPlugin.class)
+ .build();
+ verify(mPluginManager).addPluginListener(eq(OverlayPlugin.ACTION), any(),
+ eq(OverlayPlugin.class));
+
+ ext.destroy();
+ verify(mPluginManager).removePluginListener(any());
+ }
+
+ @Test
+ public void testTuner() {
+ String[] keys = new String[] { "key1", "key2" };
+ TunerFactory<Object> factory = new ExtensionController.TunerFactory() {
+ @Override
+ public String[] keys() {
+ return keys;
+ }
+
+ @Override
+ public Object create(Map settings) {
+ return null;
+ }
+ };
+ Extension ext = mExtensionController.newExtension(Object.class)
+ .withTunerFactory(factory)
+ .build();
+ verify(mTunerService).addTunable(any(), eq(keys[0]), eq(keys[1]));
+
+ ext.destroy();
+ verify(mTunerService).removeTunable(any());
+ }
+
+ @Test
+ public void testDefault() {
+ Object o = new Object();
+ Extension ext = mExtensionController.newExtension(Object.class)
+ .withDefault(() -> o)
+ .build();
+ assertEquals(o, ext.get());
+ }
+
+ @Test
+ public void testCallback() {
+ Consumer<Object> callback = mock(Consumer.class);
+ final Object o = new Object();
+ mExtensionController.newExtension(Object.class)
+ .withDefault(() -> o)
+ .withCallback(callback)
+ .build();
+ verify(callback).accept(eq(o));
+ }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/TestableLooper.java b/packages/SystemUI/tests/src/com/android/systemui/utils/TestableLooper.java
index d275973..8902e0c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/TestableLooper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/TestableLooper.java
@@ -244,9 +244,11 @@
mLooper.setAsMainLooper();
}
- mBase.evaluate();
-
- mLooper.destroy();
+ try {
+ mBase.evaluate();
+ } finally {
+ mLooper.destroy();
+ }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/ViewUtils.java b/packages/SystemUI/tests/src/com/android/systemui/utils/ViewUtils.java
index 07e5f66..678b9f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/ViewUtils.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/ViewUtils.java
@@ -14,9 +14,11 @@
package com.android.systemui.utils;
+import android.content.pm.ApplicationInfo;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Looper;
+import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
@@ -27,18 +29,19 @@
public class ViewUtils {
public static void attachView(View view) {
+ // Make sure hardware acceleration isn't turned on.
+ view.getContext().getApplicationInfo().flags &=
+ ~(ApplicationInfo.FLAG_HARDWARE_ACCELERATED);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
LayoutParams.TYPE_APPLICATION_OVERLAY,
0, PixelFormat.TRANSLUCENT);
- Handler handler = new Handler(Looper.getMainLooper());
- handler.post(() -> InstrumentationRegistry.getContext()
- .getSystemService(WindowManager.class).addView(view, lp));
+ InstrumentationRegistry.getContext()
+ .getSystemService(WindowManager.class).addView(view, lp);
}
public static void detachView(View view) {
- Handler handler = new Handler(Looper.getMainLooper());
- handler.post(() -> InstrumentationRegistry.getContext()
- .getSystemService(WindowManager.class).removeView(view));
+ InstrumentationRegistry.getContext()
+ .getSystemService(WindowManager.class).removeViewImmediate(view);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java
new file mode 100644
index 0000000..c0f5783
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import static org.mockito.Mockito.mock;
+
+import com.android.systemui.statusbar.policy.ExtensionController;
+
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+public class FakeExtensionController implements ExtensionController {
+
+ private final Tracker mTracker;
+
+ public FakeExtensionController(LeakCheckedTest test) {
+ mTracker = test.getTracker("extension");
+ }
+
+ @Override
+ public <T> ExtensionBuilder<T> newExtension(Class<T> cls) {
+ final Object o = new Object();
+ mTracker.getLeakInfo(o).addAllocation(new Throwable());
+ return new FakeExtensionBuilder(o);
+ }
+
+ private class FakeExtensionBuilder<T> implements ExtensionBuilder<T> {
+ private final Object mAllocation;
+
+ public FakeExtensionBuilder(Object o) {
+ mAllocation = o;
+ }
+
+ @Override
+ public ExtensionBuilder<T> withTunerFactory(TunerFactory<T> factory) {
+ return this;
+ }
+
+ @Override
+ public <P extends T> ExtensionBuilder<T> withPlugin(Class<P> cls) {
+ return this;
+ }
+
+ @Override
+ public <P extends T> ExtensionBuilder<T> withPlugin(Class<P> cls, String action) {
+ return this;
+ }
+
+ @Override
+ public <P> ExtensionBuilder<T> withPlugin(Class<P> cls, String action, PluginConverter<T, P> converter) {
+ return this;
+ }
+
+ @Override
+ public ExtensionBuilder<T> withDefault(Supplier<T> def) {
+ return this;
+ }
+
+ @Override
+ public ExtensionBuilder<T> withCallback(Consumer<T> callback) {
+ return this;
+ }
+
+ @Override
+ public Extension build() {
+ return new FakeExtension(mAllocation);
+ }
+ }
+
+ private class FakeExtension<T> implements Extension<T> {
+ private final Object mAllocation;
+
+ public FakeExtension(Object allocation) {
+ mAllocation = allocation;
+ }
+
+ @Override
+ public T get() {
+ // TODO: Support defaults or things.
+ return null;
+ }
+
+ @Override
+ public void destroy() {
+ mTracker.getLeakInfo(mAllocation).clearAllocations();
+ }
+ }
+}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index c7f518c..c1c385a 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3466,6 +3466,12 @@
// OS: O
ENCRYPTION_AND_CREDENTIAL = 846;
+ // ACTION: Settings > About device > Build number
+ ACTION_SETTINGS_BUILD_NUMBER_PREF = 847;
+
+ // FIELD: Whether developer mode has already been enabled when clicking build number preference
+ FIELD_SETTINGS_BUILD_NUMBER_DEVELOPER_MODE_ENABLED = 848;
+
// ---- End O Constants, all O constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 4d2b106..c50623e 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -709,7 +709,7 @@
}
private boolean isUserRunningAndUnlocked(@UserIdInt int userId) {
- return mUserManager.isUserRunning(userId) && StorageManager.isUserKeyUnlocked(userId);
+ return mUserManager.isUserUnlockingOrUnlocked(userId);
}
@Override
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index f7cb010..bfc6e83 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -56,6 +56,7 @@
import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
import android.service.autofill.IAutoFillService;
+import android.service.autofill.SaveInfo;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -719,18 +720,19 @@
}
return;
}
- final ArraySet<AutoFillId> savableIds = mCurrentResponse.getSavableIds();
+ final SaveInfo saveInfo = mCurrentResponse.getSaveInfo();
if (DEBUG) {
- Slog.d(TAG, "showSaveLocked(): savableIds=" + savableIds);
+ Slog.d(TAG, "showSaveLocked(): saveInfo=" + saveInfo);
}
- if (savableIds == null || savableIds.isEmpty()) {
+ if (saveInfo == null || saveInfo.getSavableIds() == null
+ || saveInfo.getSavableIds().isEmpty()) {
return;
}
- final int size = savableIds.size();
+ final int size = saveInfo.getSavableIds().size();
for (int i = 0; i < size; i++) {
- final AutoFillId id = savableIds.valueAt(i);
+ final AutoFillId id = saveInfo.getSavableIds().valueAt(i);
final ViewState state = mViewStates.get(id);
if (state != null && state.mValueUpdated) {
final AutoFillValue filledValue = findValue(mAutoFilledDataset, id);
@@ -741,8 +743,9 @@
Slog.d(TAG, "finishSessionLocked(): found a change on " + id + ": "
+ state.mAutoFillValue);
}
- getUiForShowing().showSaveUi(mInfo.getServiceInfo()
- .loadLabel(mContext.getPackageManager()));
+ getUiForShowing().showSaveUi(
+ mInfo.getServiceInfo().loadLabel(mContext.getPackageManager()),
+ saveInfo);
return;
}
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index cc0baa3..949a80c 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -24,6 +24,7 @@
import android.os.IBinder;
import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
+import android.service.autofill.SaveInfo;
import android.text.TextUtils;
import android.view.autofill.AutoFillId;
import android.widget.Toast;
@@ -172,13 +173,13 @@
/**
* Shows the UI asking the user to save for auto-fill.
*/
- public void showSaveUi(@NonNull CharSequence providerLabel) {
+ public void showSaveUi(@NonNull CharSequence providerLabel, @NonNull SaveInfo info) {
mHandler.post(() -> {
if (!hasCallback()) {
return;
}
hideAllUiThread();
- mSaveUi = new SaveUi(mContext, providerLabel,
+ mSaveUi = new SaveUi(mContext, providerLabel, info,
new SaveUi.OnSaveListener() {
@Override
public void onSave() {
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 b7215d6..afe93c7 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -20,6 +20,7 @@
import android.app.Dialog;
import android.content.Context;
import android.os.Handler;
+import android.service.autofill.SaveInfo;
import android.text.format.DateUtils;
import android.view.Gravity;
import android.view.Window;
@@ -50,15 +51,41 @@
private boolean mDestroyed;
- SaveUi(@NonNull Context context, @NonNull CharSequence providerLabel,
+ SaveUi(@NonNull Context context, @NonNull CharSequence providerLabel, @NonNull SaveInfo info,
@NonNull OnSaveListener listener) {
mListener = listener;
final LayoutInflater inflater = LayoutInflater.from(context);
final View view = inflater.inflate(R.layout.autofill_save, null);
- final TextView title = (TextView) view.findViewById(R.id.autofill_save_title);
- title.setText(context.getString(R.string.autofill_save_title, providerLabel));
+ final TextView titleView = (TextView) view.findViewById(R.id.autofill_save_title);
+ final String type;
+
+ switch(info.getType()) {
+ case SaveInfo.SAVE_DATA_TYPE_PASSWORD:
+ type = context.getString(R.string.autofill_save_type_password);
+ break;
+ case SaveInfo.SAVE_DATA_TYPE_ADDRESS:
+ type = context.getString(R.string.autofill_save_type_address);
+ break;
+ case SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD:
+ type = context.getString(R.string.autofill_save_type_credit_card);
+ break;
+ default:
+ type = null;
+ }
+
+ final String title = (type == null)
+ ? context.getString(R.string.autofill_save_title, providerLabel)
+ : context.getString(R.string.autofill_save_title_with_type, type, providerLabel);
+
+ titleView.setText(title);
+ final CharSequence subTitle = info.getDescription();
+ if (subTitle != null) {
+ final TextView subTitleView = (TextView) view.findViewById(R.id.autofill_save_subtitle);
+ subTitleView.setText(subTitle);
+ subTitleView.setVisibility(View.VISIBLE);
+ }
final View noButton = view.findViewById(R.id.autofill_save_no);
noButton.setOnClickListener((v) -> mListener.onCancel());
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index dc0e3e1..de11f36 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -167,14 +167,10 @@
}
}
- final SparseArray<ArrayList<Callback>> mOpModeWatchers
- = new SparseArray<ArrayList<Callback>>();
- final ArrayMap<String, ArrayList<Callback>> mPackageModeWatchers
- = new ArrayMap<String, ArrayList<Callback>>();
- final ArrayMap<IBinder, Callback> mModeWatchers
- = new ArrayMap<IBinder, Callback>();
- final SparseArray<SparseArray<Restriction>> mAudioRestrictions
- = new SparseArray<SparseArray<Restriction>>();
+ final SparseArray<ArraySet<Callback>> mOpModeWatchers = new SparseArray<>();
+ final ArrayMap<String, ArraySet<Callback>> mPackageModeWatchers = new ArrayMap<>();
+ final ArrayMap<IBinder, Callback> mModeWatchers = new ArrayMap<>();
+ final SparseArray<SparseArray<Restriction>> mAudioRestrictions = new SparseArray<>();
public final class Callback implements DeathRecipient {
final IAppOpsCallback mCallback;
@@ -545,11 +541,11 @@
ArrayMap<Callback, ArraySet<String>> callbackSpecs = null;
synchronized (this) {
- ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
+ ArraySet<Callback> callbacks = mOpModeWatchers.get(code);
if (callbacks != null) {
final int callbackCount = callbacks.size();
for (int i = 0; i < callbackCount; i++) {
- Callback callback = callbacks.get(i);
+ Callback callback = callbacks.valueAt(i);
ArraySet<String> changedPackages = new ArraySet<>();
Collections.addAll(changedPackages, uidPackageNames);
callbackSpecs = new ArrayMap<>();
@@ -565,7 +561,7 @@
}
final int callbackCount = callbacks.size();
for (int i = 0; i < callbackCount; i++) {
- Callback callback = callbacks.get(i);
+ Callback callback = callbacks.valueAt(i);
ArraySet<String> changedPackages = callbackSpecs.get(callback);
if (changedPackages == null) {
changedPackages = new ArraySet<>();
@@ -623,17 +619,17 @@
if (op != null) {
if (op.mode != mode) {
op.mode = mode;
- ArrayList<Callback> cbs = mOpModeWatchers.get(code);
+ ArraySet<Callback> cbs = mOpModeWatchers.get(code);
if (cbs != null) {
if (repCbs == null) {
- repCbs = new ArrayList<Callback>();
+ repCbs = new ArrayList<>();
}
repCbs.addAll(cbs);
}
cbs = mPackageModeWatchers.get(packageName);
if (cbs != null) {
if (repCbs == null) {
- repCbs = new ArrayList<Callback>();
+ repCbs = new ArrayList<>();
}
repCbs.addAll(cbs);
}
@@ -666,7 +662,7 @@
private static HashMap<Callback, ArrayList<ChangeRec>> addCallbacks(
HashMap<Callback, ArrayList<ChangeRec>> callbacks,
- int op, int uid, String packageName, ArrayList<Callback> cbs) {
+ int op, int uid, String packageName, ArraySet<Callback> cbs) {
if (cbs == null) {
return callbacks;
}
@@ -674,8 +670,9 @@
callbacks = new HashMap<>();
}
boolean duplicate = false;
- for (int i=0; i<cbs.size(); i++) {
- Callback cb = cbs.get(i);
+ final int N = cbs.size();
+ for (int i=0; i<N; i++) {
+ Callback cb = cbs.valueAt(i);
ArrayList<ChangeRec> reports = callbacks.get(cb);
if (reports == null) {
reports = new ArrayList<>();
@@ -830,17 +827,17 @@
mModeWatchers.put(callback.asBinder(), cb);
}
if (op != AppOpsManager.OP_NONE) {
- ArrayList<Callback> cbs = mOpModeWatchers.get(op);
+ ArraySet<Callback> cbs = mOpModeWatchers.get(op);
if (cbs == null) {
- cbs = new ArrayList<Callback>();
+ cbs = new ArraySet<>();
mOpModeWatchers.put(op, cbs);
}
cbs.add(cb);
}
if (packageName != null) {
- ArrayList<Callback> cbs = mPackageModeWatchers.get(packageName);
+ ArraySet<Callback> cbs = mPackageModeWatchers.get(packageName);
if (cbs == null) {
- cbs = new ArrayList<Callback>();
+ cbs = new ArraySet<>();
mPackageModeWatchers.put(packageName, cbs);
}
cbs.add(cb);
@@ -858,14 +855,14 @@
if (cb != null) {
cb.unlinkToDeath();
for (int i=mOpModeWatchers.size()-1; i>=0; i--) {
- ArrayList<Callback> cbs = mOpModeWatchers.valueAt(i);
+ ArraySet<Callback> cbs = mOpModeWatchers.valueAt(i);
cbs.remove(cb);
if (cbs.size() <= 0) {
mOpModeWatchers.removeAt(i);
}
}
for (int i=mPackageModeWatchers.size()-1; i>=0; i--) {
- ArrayList<Callback> cbs = mPackageModeWatchers.valueAt(i);
+ ArraySet<Callback> cbs = mPackageModeWatchers.valueAt(i);
cbs.remove(cb);
if (cbs.size() <= 0) {
mPackageModeWatchers.removeAt(i);
@@ -2066,10 +2063,10 @@
for (int i=0; i<mOpModeWatchers.size(); i++) {
pw.print(" Op "); pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i)));
pw.println(":");
- ArrayList<Callback> callbacks = mOpModeWatchers.valueAt(i);
+ ArraySet<Callback> callbacks = mOpModeWatchers.valueAt(i);
for (int j=0; j<callbacks.size(); j++) {
pw.print(" #"); pw.print(j); pw.print(": ");
- pw.println(callbacks.get(j));
+ pw.println(callbacks.valueAt(j));
}
}
}
@@ -2079,10 +2076,10 @@
for (int i=0; i<mPackageModeWatchers.size(); i++) {
pw.print(" Pkg "); pw.print(mPackageModeWatchers.keyAt(i));
pw.println(":");
- ArrayList<Callback> callbacks = mPackageModeWatchers.valueAt(i);
+ ArraySet<Callback> callbacks = mPackageModeWatchers.valueAt(i);
for (int j=0; j<callbacks.size(); j++) {
pw.print(" #"); pw.print(j); pw.print(": ");
- pw.println(callbacks.get(j));
+ pw.println(callbacks.valueAt(j));
}
}
}
@@ -2310,23 +2307,23 @@
}
private void notifyWatchersOfChange(int code) {
- final ArrayList<Callback> clonedCallbacks;
+ final ArraySet<Callback> clonedCallbacks;
synchronized (this) {
- ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
+ ArraySet<Callback> callbacks = mOpModeWatchers.get(code);
if (callbacks == null) {
return;
}
- clonedCallbacks = new ArrayList<>(callbacks);
+ clonedCallbacks = new ArraySet<>(callbacks);
}
// There are components watching for mode changes such as window manager
// and location manager which are in our process. The callbacks in these
- // components may require permissions our remote caller does not have.s
+ // components may require permissions our remote caller does not have.
final long identity = Binder.clearCallingIdentity();
try {
final int callbackCount = clonedCallbacks.size();
for (int i = 0; i < callbackCount; i++) {
- Callback callback = clonedCallbacks.get(i);
+ Callback callback = clonedCallbacks.valueAt(i);
try {
callback.mCallback.opChanged(code, -1, null);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 6248cab..81f137e 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -130,6 +130,8 @@
private int mLastMaxChargingVoltage;
private int mLastChargeCounter;
+ private int mSequence = 1;
+
private int mInvalidCharger;
private int mLastInvalidCharger;
@@ -448,27 +450,29 @@
}
}
- sendIntentLocked();
+ mSequence++;
// Separate broadcast is sent for power connected / not connected
// since the standard intent will not wake any applications and some
// applications may want to have smart behavior based on this.
if (mPlugType != 0 && mLastPlugType == 0) {
+ final Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
+ statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
- Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
- statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
}
else if (mPlugType == 0 && mLastPlugType != 0) {
+ final Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
+ statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
- Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
- statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
@@ -476,26 +480,33 @@
if (shouldSendBatteryLowLocked()) {
mSentLowBatteryBroadcast = true;
+ final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);
+ statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
- Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);
- statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
} else if (mSentLowBatteryBroadcast && mLastBatteryLevel >= mLowBatteryCloseWarningLevel) {
mSentLowBatteryBroadcast = false;
+ final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
+ statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
- Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
- statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
}
+ // We are doing this after sending the above broadcasts, so anything processing
+ // them will get the new sequence number at that point. (See for example how testing
+ // of JobScheduler's BatteryController works.)
+ sendIntentLocked();
+
// Update the battery LED
mLed.updateLightsLocked();
@@ -527,6 +538,7 @@
int icon = getIconLocked(mBatteryProps.batteryLevel);
+ intent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus);
intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryProps.batteryHealth);
intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryProps.batteryPresent);
@@ -666,12 +678,28 @@
pw.println("Battery service (battery) commands:");
pw.println(" help");
pw.println(" Print this help text.");
- pw.println(" set [ac|usb|wireless|status|level|invalid] <value>");
+ pw.println(" set [-f] [ac|usb|wireless|status|level|invalid] <value>");
pw.println(" Force a battery property value, freezing battery state.");
- pw.println(" unplug");
+ pw.println(" -f: force a battery change broadcast be sent, prints new sequence.");
+ pw.println(" unplug [-f]");
pw.println(" Force battery unplugged, freezing battery state.");
- pw.println(" reset");
+ pw.println(" -f: force a battery change broadcast be sent, prints new sequence.");
+ pw.println(" reset [-f]");
pw.println(" Unfreeze battery state, returning to current hardware values.");
+ pw.println(" -f: force a battery change broadcast be sent, prints new sequence.");
+ }
+
+ static final int OPTION_FORCE_UPDATE = 1<<0;
+
+ int parseOptions(Shell shell) {
+ String opt;
+ int opts = 0;
+ while ((opt = shell.getNextOption()) != null) {
+ if ("-f".equals(opt)) {
+ opts |= OPTION_FORCE_UPDATE;
+ }
+ }
+ return opts;
}
int onShellCommand(Shell shell, String cmd) {
@@ -681,6 +709,7 @@
PrintWriter pw = shell.getOutPrintWriter();
switch (cmd) {
case "unplug": {
+ int opts = parseOptions(shell);
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
if (!mUpdatesStopped) {
@@ -692,12 +721,13 @@
long ident = Binder.clearCallingIdentity();
try {
mUpdatesStopped = true;
- processValuesLocked(false);
+ processValuesFromShellLocked(pw, opts);
} finally {
Binder.restoreCallingIdentity(ident);
}
} break;
case "set": {
+ int opts = parseOptions(shell);
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final String key = shell.getNextArg();
@@ -745,7 +775,7 @@
long ident = Binder.clearCallingIdentity();
try {
mUpdatesStopped = true;
- processValuesLocked(false);
+ processValuesFromShellLocked(pw, opts);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -756,6 +786,7 @@
}
} break;
case "reset": {
+ int opts = parseOptions(shell);
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
long ident = Binder.clearCallingIdentity();
@@ -763,7 +794,7 @@
if (mUpdatesStopped) {
mUpdatesStopped = false;
mBatteryProps.set(mLastBatteryProps);
- processValuesLocked(false);
+ processValuesFromShellLocked(pw, opts);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -775,6 +806,13 @@
return 0;
}
+ private void processValuesFromShellLocked(PrintWriter pw, int opts) {
+ processValuesLocked((opts & OPTION_FORCE_UPDATE) != 0);
+ if ((opts & OPTION_FORCE_UPDATE) != 0) {
+ pw.println(mSequence);
+ }
+ }
+
private void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
synchronized (mLock) {
if (args == null || args.length == 0 || "-a".equals(args[0])) {
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index f315553..e8df38b 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -167,7 +167,7 @@
}
public String toString() {
- return android.text.format.DateFormat.format("MM-dd hh:mm:ss ", mTimestamp) +
+ return android.text.format.DateFormat.format("MM-dd HH:mm:ss ", mTimestamp) +
(mEnable ? " Enabled " : " Disabled ") + " by " + mPackageName;
}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index ef7780c..979096e 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -19,6 +19,7 @@
import android.app.ActivityManager;
import android.annotation.NonNull;
import android.content.pm.PackageManagerInternal;
+import android.util.ArrayMap;
import android.util.ArraySet;
import com.android.internal.content.PackageMonitor;
import com.android.internal.location.ProviderProperties;
@@ -104,6 +105,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
@@ -225,6 +227,12 @@
private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
+ private final ArrayMap<IGnssMeasurementsListener, Identity> mGnssMeasurementsListeners =
+ new ArrayMap<>();
+
+ private final ArrayMap<IGnssNavigationMessageListener, Identity>
+ mGnssNavigationMessageListeners = new ArrayMap<>();
+
// current active user on the device - other users are denied location data
private int mCurrentUserId = UserHandle.USER_SYSTEM;
private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_SYSTEM };
@@ -315,17 +323,17 @@
boolean foreground = isImportanceForeground(importance);
HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
synchronized (mLock) {
- for (Map.Entry<String, ArrayList<UpdateRecord>> entry
+ for (Entry<String, ArrayList<UpdateRecord>> entry
: mRecordsByProvider.entrySet()) {
String provider = entry.getKey();
for (UpdateRecord record : entry.getValue()) {
- if (record.mReceiver.mUid == uid
+ if (record.mReceiver.mIdentity.mUid == uid
&& record.mIsForegroundUid != foreground) {
if (D) Log.d(TAG, "request from uid " + uid + " is now "
+ (foreground ? "foreground" : "background)"));
record.mIsForegroundUid = foreground;
- if (!isThrottlingExemptLocked(record.mReceiver)) {
+ if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
affectedProviders.add(provider);
}
}
@@ -334,6 +342,33 @@
for (String provider : affectedProviders) {
applyRequirementsLocked(provider);
}
+
+ for (Entry<IGnssMeasurementsListener, Identity> entry
+ : mGnssMeasurementsListeners.entrySet()) {
+ if (entry.getValue().mUid == uid) {
+ if (D) Log.d(TAG, "gnss measurements listener from uid " + uid
+ + " is now " + (foreground ? "foreground" : "background)"));
+ if (foreground || isThrottlingExemptLocked(entry.getValue())) {
+ mGnssMeasurementsProvider.addListener(entry.getKey());
+ } else {
+ mGnssMeasurementsProvider.removeListener(entry.getKey());
+ }
+ }
+ }
+
+ for (Entry<IGnssNavigationMessageListener, Identity> entry
+ : mGnssNavigationMessageListeners.entrySet()) {
+ if (entry.getValue().mUid == uid) {
+ if (D) Log.d(TAG, "gnss navigation message listener from uid "
+ + uid + " is now "
+ + (foreground ? "foreground" : "background)"));
+ if (foreground || isThrottlingExemptLocked(entry.getValue())) {
+ mGnssNavigationMessageProvider.addListener(entry.getKey());
+ } else {
+ mGnssNavigationMessageProvider.removeListener(entry.getKey());
+ }
+ }
+ }
}
}
@@ -344,7 +379,7 @@
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
updateUserProfiles(mCurrentUserId);
- updateThrottlingWhitelistLocked();
+ updateBackgroundThrottlingWhitelistLocked();
// prepare providers
loadProvidersLocked();
@@ -381,7 +416,7 @@
@Override
public void onChange(boolean selfChange) {
synchronized (mLock) {
- updateThrottlingWhitelistLocked();
+ updateBackgroundThrottlingWhitelistLocked();
updateProvidersLocked();
}
}
@@ -721,14 +756,24 @@
}
}
+ private static final class Identity {
+ final int mUid;
+ final int mPid;
+ final String mPackageName;
+
+ Identity(int uid, int pid, String packageName) {
+ mUid = uid;
+ mPid = pid;
+ mPackageName = packageName;
+ }
+ }
+
/**
* A wrapper class holding either an ILocationListener or a PendingIntent to receive
* location updates.
*/
private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
- final int mUid; // uid of receiver
- final int mPid; // pid of receiver
- final String mPackageName; // package name of receiver
+ final Identity mIdentity;
final int mAllowedResolutionLevel; // resolution level allowed to receiver
final ILocationListener mListener;
@@ -756,9 +801,7 @@
mKey = intent;
}
mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
- mUid = uid;
- mPid = pid;
- mPackageName = packageName;
+ mIdentity = new Identity(uid, pid, packageName);
if (workSource != null && workSource.size() <= 0) {
workSource = null;
}
@@ -770,7 +813,7 @@
// construct/configure wakelock
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
if (workSource == null) {
- workSource = new WorkSource(mUid, mPackageName);
+ workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
}
mWakeLock.setWorkSource(workSource);
}
@@ -865,13 +908,14 @@
int op) {
if (!currentlyMonitoring) {
if (allowMonitoring) {
- return mAppOps.startOpNoThrow(op, mUid, mPackageName)
+ return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
== AppOpsManager.MODE_ALLOWED;
}
} else {
- if (!allowMonitoring || mAppOps.checkOpNoThrow(op, mUid, mPackageName)
+ if (!allowMonitoring
+ || mAppOps.checkOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
!= AppOpsManager.MODE_ALLOWED) {
- mAppOps.finishOp(op, mUid, mPackageName);
+ mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
return false;
}
}
@@ -1628,7 +1672,7 @@
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
if (records != null) {
for (UpdateRecord record : records) {
- if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) {
+ if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
// Sends a notification message to the receiver
if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
if (deadReceivers == null) {
@@ -1673,16 +1717,16 @@
if (records != null) {
for (UpdateRecord record : records) {
- if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) {
+ if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
if (checkLocationAccess(
- record.mReceiver.mPid,
- record.mReceiver.mUid,
- record.mReceiver.mPackageName,
+ record.mReceiver.mIdentity.mPid,
+ record.mReceiver.mIdentity.mUid,
+ record.mReceiver.mIdentity.mPackageName,
record.mReceiver.mAllowedResolutionLevel)) {
LocationRequest locationRequest = record.mRequest;
long interval = locationRequest.getInterval();
- if (!isThrottlingExemptLocked(record.mReceiver)) {
+ if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
if (!record.mIsForegroundUid) {
interval = Math.max(interval, backgroundThrottleInterval);
}
@@ -1709,7 +1753,7 @@
// under that threshold.
long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
for (UpdateRecord record : records) {
- if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) {
+ if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
LocationRequest locationRequest = record.mRequest;
// Don't assign battery blame for update records whose
@@ -1728,8 +1772,8 @@
} else {
// Assign blame to caller.
worksource.add(
- record.mReceiver.mUid,
- record.mReceiver.mPackageName);
+ record.mReceiver.mIdentity.mUid,
+ record.mReceiver.mIdentity.mPackageName);
}
}
}
@@ -1741,7 +1785,15 @@
p.setRequest(providerRequest, worksource);
}
- private void updateThrottlingWhitelistLocked() {
+ @Override
+ public String[] getBackgroundThrottlingWhitelist() {
+ synchronized (mLock) {
+ return mBackgroundThrottlePackageWhitelist.toArray(
+ new String[mBackgroundThrottlePackageWhitelist.size()]);
+ }
+ }
+
+ private void updateBackgroundThrottlingWhitelistLocked() {
String setting = Settings.Global.getString(
mContext.getContentResolver(),
Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
@@ -1756,17 +1808,17 @@
Arrays.asList(setting.split(",")));
}
- private boolean isThrottlingExemptLocked(Receiver receiver) {
- if (receiver.mUid == Process.SYSTEM_UID) {
+ private boolean isThrottlingExemptLocked(Identity identity) {
+ if (identity.mUid == Process.SYSTEM_UID) {
return true;
}
- if (mBackgroundThrottlePackageWhitelist.contains(receiver.mPackageName)) {
+ if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
return true;
}
for (LocationProviderProxy provider : mProxyProviders) {
- if (receiver.mPackageName.equals(provider.getConnectedPackageName())) {
+ if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
return true;
}
}
@@ -1790,7 +1842,7 @@
mRequest = request;
mReceiver = receiver;
mIsForegroundUid = isImportanceForeground(
- mActivityManager.getPackageImportance(mReceiver.mPackageName));
+ mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
if (records == null) {
@@ -1803,14 +1855,14 @@
// Update statistics for historical location requests by package/provider
mRequestStatistics.startRequesting(
- mReceiver.mPackageName, provider, request.getInterval());
+ mReceiver.mIdentity.mPackageName, provider, request.getInterval());
}
/**
* Method to be called when a record will no longer be used.
*/
void disposeLocked(boolean removeReceiver) {
- mRequestStatistics.stopRequesting(mReceiver.mPackageName, mProvider);
+ mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
// remove from mRecordsByProvider
ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
@@ -1834,8 +1886,8 @@
@Override
public String toString() {
- return "UpdateRecord[" + mProvider + " " + mReceiver.mPackageName
- + "(" + mReceiver.mUid + (mIsForegroundUid ? " foreground" : " background")
+ return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
+ + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground" : " background")
+ ")" + " " + mRequest + "]";
}
}
@@ -1994,7 +2046,8 @@
if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
+ " " + name + " " + request + " from " + packageName + "(" + uid + " "
+ (record.mIsForegroundUid ? "foreground" : "background")
- + (isThrottlingExemptLocked(receiver) ? " [whitelisted]" : "") + ")");
+ + (isThrottlingExemptLocked(receiver.mIdentity)
+ ? " [whitelisted]" : "") + ")");
UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
if (oldRecord != null) {
@@ -2227,13 +2280,33 @@
if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
return false;
}
- return mGnssMeasurementsProvider.addListener(listener);
+
+ synchronized (mLock) {
+ Identity callerIdentity
+ = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
+ mGnssMeasurementsListeners.put(listener, callerIdentity);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ if (isThrottlingExemptLocked(callerIdentity)
+ || isImportanceForeground(
+ mActivityManager.getPackageImportance(packageName))) {
+ return mGnssMeasurementsProvider.addListener(listener);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
+ return true;
+ }
}
@Override
public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
if (mGnssMeasurementsProvider != null) {
- mGnssMeasurementsProvider.removeListener(listener);
+ synchronized (mLock) {
+ mGnssMeasurementsListeners.remove(listener);
+ mGnssMeasurementsProvider.removeListener(listener);
+ }
}
}
@@ -2244,13 +2317,33 @@
if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
return false;
}
- return mGnssNavigationMessageProvider.addListener(listener);
+
+ synchronized (mLock) {
+ Identity callerIdentity
+ = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
+ mGnssNavigationMessageListeners.put(listener, callerIdentity);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ if (isThrottlingExemptLocked(callerIdentity)
+ || isImportanceForeground(
+ mActivityManager.getPackageImportance(packageName))) {
+ return mGnssNavigationMessageProvider.addListener(listener);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
+ return true;
+ }
}
@Override
public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
if (mGnssNavigationMessageProvider != null) {
- mGnssNavigationMessageProvider.removeListener(listener);
+ synchronized (mLock) {
+ mGnssNavigationMessageListeners.remove(listener);
+ mGnssNavigationMessageProvider.removeListener(listener);
+ }
}
}
@@ -2529,26 +2622,30 @@
Receiver receiver = r.mReceiver;
boolean receiverDead = false;
- int receiverUserId = UserHandle.getUserId(receiver.mUid);
- if (!isCurrentProfile(receiverUserId) && !isUidALocationProvider(receiver.mUid)) {
+ int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
+ if (!isCurrentProfile(receiverUserId)
+ && !isUidALocationProvider(receiver.mIdentity.mUid)) {
if (D) {
Log.d(TAG, "skipping loc update for background user " + receiverUserId +
" (current user: " + mCurrentUserId + ", app: " +
- receiver.mPackageName + ")");
+ receiver.mIdentity.mPackageName + ")");
}
continue;
}
- if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
+ if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
- receiver.mPackageName);
+ receiver.mIdentity.mPackageName);
continue;
}
- if (!reportLocationAccessNoThrow(receiver.mPid, receiver.mUid, receiver.mPackageName,
+ if (!reportLocationAccessNoThrow(
+ receiver.mIdentity.mPid,
+ receiver.mIdentity.mUid,
+ receiver.mIdentity.mPackageName,
receiver.mAllowedResolutionLevel)) {
if (D) Log.d(TAG, "skipping loc update for no op app: " +
- receiver.mPackageName);
+ receiver.mIdentity.mPackageName);
continue;
}
@@ -2671,7 +2768,7 @@
ArrayList<Receiver> deadReceivers = null;
for (Receiver receiver : mReceivers.values()) {
- if (receiver.mPackageName.equals(packageName)) {
+ if (receiver.mIdentity.mPackageName.equals(packageName)) {
if (deadReceivers == null) {
deadReceivers = new ArrayList<>();
}
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index b33538cb..d54ebaa 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -35,8 +35,7 @@
import android.net.INetworkScoreService;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
-import android.net.NetworkScorerAppManager;
-import android.net.NetworkScorerAppManager.NetworkScorerAppData;
+import android.net.NetworkScorerAppData;
import android.net.RecommendationRequest;
import android.net.RecommendationResult;
import android.net.ScoredNetwork;
@@ -132,10 +131,10 @@
* manages the service connection.
*/
private class NetworkScorerPackageMonitor extends PackageMonitor {
- final List<String> mPackagesToWatch;
+ final String mPackageToWatch;
- private NetworkScorerPackageMonitor(List<String> packagesToWatch) {
- mPackagesToWatch = packagesToWatch;
+ private NetworkScorerPackageMonitor(String packageToWatch) {
+ mPackageToWatch = packageToWatch;
}
@Override
@@ -168,37 +167,27 @@
evaluateBinding(packageName, true /* forceUnbind */);
}
- private void evaluateBinding(String scorerPackageName, boolean forceUnbind) {
- if (!mPackagesToWatch.contains(scorerPackageName)) {
+ private void evaluateBinding(String changedPackageName, boolean forceUnbind) {
+ if (!mPackageToWatch.equals(changedPackageName)) {
// Early exit when we don't care about the package that has changed.
return;
}
if (DBG) {
- Log.d(TAG, "Evaluating binding for: " + scorerPackageName
+ Log.d(TAG, "Evaluating binding for: " + changedPackageName
+ ", forceUnbind=" + forceUnbind);
}
+
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
if (activeScorer == null) {
// Package change has invalidated a scorer, this will also unbind any service
// connection.
if (DBG) Log.d(TAG, "No active scorers available.");
- unbindFromScoringServiceIfNeeded();
- } else if (activeScorer.getRecommendationServicePackageName().equals(scorerPackageName))
- {
- // The active scoring service changed in some way.
- if (DBG) {
- Log.d(TAG, "Possible change to the active scorer: "
- + activeScorer.getRecommendationServicePackageName());
- }
+ refreshBinding();
+ } else { // The scoring service changed in some way.
if (forceUnbind) {
unbindFromScoringServiceIfNeeded();
}
- bindToScoringServiceIfNeeded(activeScorer);
- } else {
- // One of the scoring apps on the device has changed and we may no longer be
- // bound to the correct scoring app. The logic in bindToScoringServiceIfNeeded()
- // will sort that out to leave us bound to the most recent active scorer.
if (DBG) {
Log.d(TAG, "Binding to " + activeScorer.getRecommendationServiceComponent()
+ " if needed.");
@@ -272,60 +261,71 @@
/** Called when the system is ready to run third-party code but before it actually does so. */
void systemReady() {
if (DBG) Log.d(TAG, "systemReady");
- registerPackageMonitorIfNeeded();
registerRecommendationSettingsObserver();
- refreshRecommendationRequestTimeoutMs();
}
/** Called when the system is ready for us to start third-party code. */
void systemRunning() {
if (DBG) Log.d(TAG, "systemRunning");
- bindToScoringServiceIfNeeded();
}
- private void onUserUnlocked(int userId) {
+ @VisibleForTesting
+ void onUserUnlocked(int userId) {
+ if (DBG) Log.d(TAG, "onUserUnlocked(" + userId + ")");
+ refreshBinding();
+ }
+
+ private void refreshBinding() {
+ if (DBG) Log.d(TAG, "refreshBinding()");
+ // Apply the default package name if the Setting isn't set.
+ mNetworkScorerAppManager.revertToDefaultIfNoActive();
registerPackageMonitorIfNeeded();
bindToScoringServiceIfNeeded();
}
private void registerRecommendationSettingsObserver() {
- final List<String> providerPackages =
- mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
- if (!providerPackages.isEmpty()) {
- final Uri enabledUri = Global.getUriFor(Global.NETWORK_RECOMMENDATIONS_ENABLED);
- mContentObserver.observe(enabledUri,
- ServiceHandler.MSG_RECOMMENDATIONS_ENABLED_CHANGED);
- }
+ final Uri packageNameUri = Global.getUriFor(Global.NETWORK_RECOMMENDATIONS_PACKAGE);
+ mContentObserver.observe(packageNameUri,
+ ServiceHandler.MSG_RECOMMENDATIONS_PACKAGE_CHANGED);
final Uri timeoutUri = Global.getUriFor(Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS);
mContentObserver.observe(timeoutUri,
ServiceHandler.MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED);
}
+ /**
+ * Ensures the package manager is registered to monitor the current active scorer.
+ * If a discrepancy is found any previous monitor will be cleaned up
+ * and a new monitor will be created.
+ *
+ * This method is idempotent.
+ */
private void registerPackageMonitorIfNeeded() {
- if (DBG) Log.d(TAG, "registerPackageMonitorIfNeeded");
- final List<String> providerPackages =
- mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
+ if (DBG) Log.d(TAG, "registerPackageMonitorIfNeeded()");
+ final NetworkScorerAppData appData = mNetworkScorerAppManager.getActiveScorer();
synchronized (mPackageMonitorLock) {
// Unregister the current monitor if needed.
- if (mPackageMonitor != null) {
+ if (mPackageMonitor != null && (appData == null
+ || !appData.getRecommendationServicePackageName().equals(
+ mPackageMonitor.mPackageToWatch))) {
if (DBG) {
Log.d(TAG, "Unregistering package monitor for "
- + mPackageMonitor.mPackagesToWatch);
+ + mPackageMonitor.mPackageToWatch);
}
mPackageMonitor.unregister();
mPackageMonitor = null;
}
- // Create and register the monitor if there are packages that could be providers.
- if (!providerPackages.isEmpty()) {
- mPackageMonitor = new NetworkScorerPackageMonitor(providerPackages);
+ // Create and register the monitor if a scorer is active.
+ if (appData != null && mPackageMonitor == null) {
+ mPackageMonitor = new NetworkScorerPackageMonitor(
+ appData.getRecommendationServicePackageName());
// TODO: Need to update when we support per-user scorers. http://b/23422763
mPackageMonitor.register(mContext, null /* thread */, UserHandle.SYSTEM,
false /* externalStorage */);
if (DBG) {
Log.d(TAG, "Registered package monitor for "
- + mPackageMonitor.mPackagesToWatch);
+ + mPackageMonitor.mPackageToWatch);
}
}
}
@@ -337,6 +337,13 @@
bindToScoringServiceIfNeeded(scorerData);
}
+ /**
+ * Ensures the service connection is bound to the current active scorer.
+ * If a discrepancy is found any previous connection will be cleaned up
+ * and a new connection will be created.
+ *
+ * This method is idempotent.
+ */
private void bindToScoringServiceIfNeeded(NetworkScorerAppData appData) {
if (DBG) Log.d(TAG, "bindToScoringServiceIfNeeded(" + appData + ")");
if (appData != null) {
@@ -365,6 +372,8 @@
synchronized (mServiceConnectionLock) {
if (mServiceConnection != null) {
mServiceConnection.disconnect(mContext);
+ if (DBG) Log.d(TAG, "Disconnected from: "
+ + mServiceConnection.mAppData.getRecommendationServiceComponent());
}
mServiceConnection = null;
}
@@ -653,17 +662,13 @@
@Override
public boolean setActiveScorer(String packageName) {
- // TODO: For now, since SCORE_NETWORKS requires an app to be privileged, we allow such apps
- // to directly set the scorer app rather than having to use the consent dialog. The
- // assumption is that anyone bundling a scorer app with the system is trusted by the OEM to
- // do the right thing and not enable this feature without explaining it to the user.
- // In the future, should this API be opened to 3p apps, we will need to lock this down and
- // figure out another way to streamline the UX.
-
- mContext.enforceCallingOrSelfPermission(permission.SCORE_NETWORKS, TAG);
-
- // Scorers (recommendation providers) are selected and no longer set.
- return false;
+ // Only the system can set the active scorer
+ if (isCallerSystemProcess(getCallingUid()) || callerCanRequestScores()) {
+ return mNetworkScorerAppManager.setActiveScorer(packageName);
+ } else {
+ throw new SecurityException(
+ "Caller is neither the system process nor a score requester.");
+ }
}
/**
@@ -700,7 +705,6 @@
return null;
}
-
/**
* Returns metadata about the active scorer or <code>null</code> if there is no active scorer.
*/
@@ -727,7 +731,13 @@
*/
@Override
public List<NetworkScorerAppData> getAllValidScorers() {
- return mNetworkScorerAppManager.getAllValidScorers();
+ // Only the system can access this data.
+ if (isCallerSystemProcess(getCallingUid()) || callerCanRequestScores()) {
+ return mNetworkScorerAppManager.getAllValidScorers();
+ } else {
+ throw new SecurityException(
+ "Caller is neither the system process nor a score requester.");
+ }
}
@Override
@@ -1159,7 +1169,7 @@
@VisibleForTesting
public final class ServiceHandler extends Handler {
public static final int MSG_RECOMMENDATION_REQUEST_TIMEOUT = 1;
- public static final int MSG_RECOMMENDATIONS_ENABLED_CHANGED = 2;
+ public static final int MSG_RECOMMENDATIONS_PACKAGE_CHANGED = 2;
public static final int MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED = 3;
public ServiceHandler(Looper looper) {
@@ -1181,8 +1191,8 @@
sendDefaultRecommendationResponse(request, remoteCallback);
break;
- case MSG_RECOMMENDATIONS_ENABLED_CHANGED:
- bindToScoringServiceIfNeeded();
+ case MSG_RECOMMENDATIONS_PACKAGE_CHANGED:
+ refreshBinding();
break;
case MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED:
diff --git a/services/core/java/com/android/server/NetworkScorerAppManager.java b/services/core/java/com/android/server/NetworkScorerAppManager.java
new file mode 100644
index 0000000..2f4485a
--- /dev/null
+++ b/services/core/java/com/android/server/NetworkScorerAppManager.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server;
+
+import android.Manifest.permission;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.net.NetworkScoreManager;
+import android.net.NetworkScorerAppData;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Internal class for discovering and managing the network scorer/recommendation application.
+ *
+ * @hide
+ */
+@VisibleForTesting
+public class NetworkScorerAppManager {
+ private static final String TAG = "NetworkScorerAppManager";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+ private final Context mContext;
+ private final SettingsFacade mSettingsFacade;
+
+ public NetworkScorerAppManager(Context context) {
+ this(context, new SettingsFacade());
+ }
+
+ @VisibleForTesting
+ public NetworkScorerAppManager(Context context, SettingsFacade settingsFacade) {
+ mContext = context;
+ mSettingsFacade = settingsFacade;
+ }
+
+ /**
+ * Returns the list of available scorer apps. The list will be empty if there are
+ * no valid scorers.
+ */
+ @VisibleForTesting
+ public List<NetworkScorerAppData> getAllValidScorers() {
+ if (VERBOSE) Log.v(TAG, "getAllValidScorers()");
+ final PackageManager pm = mContext.getPackageManager();
+ final Intent serviceIntent = new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS);
+ final List<ResolveInfo> resolveInfos =
+ pm.queryIntentServices(serviceIntent, PackageManager.GET_META_DATA);
+ if (resolveInfos == null || resolveInfos.isEmpty()) {
+ if (DEBUG) Log.d(TAG, "Found 0 Services able to handle " + serviceIntent);
+ return Collections.emptyList();
+ }
+
+ List<NetworkScorerAppData> appDataList = new ArrayList<>();
+ for (int i = 0; i < resolveInfos.size(); i++) {
+ final ServiceInfo serviceInfo = resolveInfos.get(i).serviceInfo;
+ if (hasPermissions(serviceInfo.packageName)) {
+ if (VERBOSE) {
+ Log.v(TAG, serviceInfo.packageName + " is a valid scorer/recommender.");
+ }
+ final ComponentName serviceComponentName =
+ new ComponentName(serviceInfo.packageName, serviceInfo.name);
+ final ComponentName useOpenWifiNetworksActivity =
+ findUseOpenWifiNetworksActivity(serviceInfo);
+ appDataList.add(
+ new NetworkScorerAppData(serviceInfo.applicationInfo.uid,
+ serviceComponentName, useOpenWifiNetworksActivity));
+ } else {
+ if (VERBOSE) Log.v(TAG, serviceInfo.packageName
+ + " is NOT a valid scorer/recommender.");
+ }
+ }
+
+ return appDataList;
+ }
+
+ @Nullable
+ private ComponentName findUseOpenWifiNetworksActivity(ServiceInfo serviceInfo) {
+ if (serviceInfo.metaData == null) {
+ if (DEBUG) {
+ Log.d(TAG, "No metadata found on " + serviceInfo.getComponentName());
+ }
+ return null;
+ }
+ final String useOpenWifiPackage = serviceInfo.metaData
+ .getString(NetworkScoreManager.USE_OPEN_WIFI_PACKAGE_META_DATA);
+ if (TextUtils.isEmpty(useOpenWifiPackage)) {
+ if (DEBUG) {
+ Log.d(TAG, "No use_open_wifi_package metadata found on "
+ + serviceInfo.getComponentName());
+ }
+ return null;
+ }
+ final Intent enableUseOpenWifiIntent = new Intent(NetworkScoreManager.ACTION_CUSTOM_ENABLE)
+ .setPackage(useOpenWifiPackage);
+ final ResolveInfo resolveActivityInfo = mContext.getPackageManager()
+ .resolveActivity(enableUseOpenWifiIntent, 0 /* flags */);
+ if (VERBOSE) {
+ Log.d(TAG, "Resolved " + enableUseOpenWifiIntent + " to " + resolveActivityInfo);
+ }
+
+ if (resolveActivityInfo != null && resolveActivityInfo.activityInfo != null) {
+ return resolveActivityInfo.activityInfo.getComponentName();
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the application to use for scoring networks.
+ *
+ * @return the scorer app info or null if scoring is disabled (including if no scorer was ever
+ * selected) or if the previously-set scorer is no longer a valid scorer app (e.g. because
+ * it was disabled or uninstalled).
+ */
+ @Nullable
+ @VisibleForTesting
+ public NetworkScorerAppData getActiveScorer() {
+ return getScorer(getNetworkRecommendationsPackage());
+ }
+
+ private NetworkScorerAppData getScorer(String packageName) {
+ if (TextUtils.isEmpty(packageName)) {
+ return null;
+ }
+
+ // Otherwise return the recommendation provider (which may be null).
+ List<NetworkScorerAppData> apps = getAllValidScorers();
+ for (int i = 0; i < apps.size(); i++) {
+ NetworkScorerAppData app = apps.get(i);
+ if (app.getRecommendationServicePackageName().equals(packageName)) {
+ return app;
+ }
+ }
+
+ return null;
+ }
+
+ private boolean hasPermissions(String packageName) {
+ final PackageManager pm = mContext.getPackageManager();
+ return pm.checkPermission(permission.SCORE_NETWORKS, packageName)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
+ /**
+ * Set the specified package as the default scorer application.
+ *
+ * <p>The caller must have permission to write to {@link Settings.Global}.
+ *
+ * @param packageName the packageName of the new scorer to use. If null, the scoring app will
+ * revert back to the configured default. Otherwise, the scorer will only
+ * be set if it is a valid scorer application.
+ * @return true if the scorer was changed, or false if the package is not a valid scorer or
+ * a valid network recommendation provider exists.
+ */
+ @VisibleForTesting
+ public boolean setActiveScorer(String packageName) {
+ String oldPackageName = getNetworkRecommendationsPackage();
+ if (TextUtils.equals(oldPackageName, packageName)) {
+ // No change.
+ return true;
+ }
+
+ Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
+
+ if (packageName == null) {
+ // revert to the default setting.
+ setNetworkRecommendationsPackage(getDefaultPackageSetting());
+ return true;
+ } else {
+ // We only make the change if the new package is valid.
+ if (getScorer(packageName) != null) {
+ setNetworkRecommendationsPackage(packageName);
+ return true;
+ } else {
+ Log.w(TAG, "Requested network scorer is not valid: " + packageName);
+ return false;
+ }
+ }
+ }
+
+ /**
+ * If the active scorer is null then revert to the default scorer.
+ */
+ @VisibleForTesting
+ public void revertToDefaultIfNoActive() {
+ if (getActiveScorer() == null) {
+ final String defaultPackage = getDefaultPackageSetting();
+ setNetworkRecommendationsPackage(defaultPackage);
+ Log.i(TAG, "Defaulted the network recommendations app to: " + defaultPackage);
+ }
+ }
+
+ private String getDefaultPackageSetting() {
+ return mContext.getResources().getString(
+ R.string.config_defaultNetworkRecommendationProviderPackage);
+ }
+
+ private String getNetworkRecommendationsPackage() {
+ return mSettingsFacade.getString(mContext, Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE);
+ }
+
+ private void setNetworkRecommendationsPackage(String packageName) {
+ mSettingsFacade.putString(mContext,
+ Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, packageName);
+ }
+
+ /**
+ * Wrapper around Settings to make testing easier.
+ */
+ public static class SettingsFacade {
+ public boolean putString(Context context, String name, String value) {
+ return Settings.Global.putString(context.getContentResolver(), name, value);
+ }
+
+ public String getString(Context context, String name) {
+ return Settings.Global.getString(context.getContentResolver(), name);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java
index ce3166d..421d5a6 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/services/core/java/com/android/server/SystemService.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.os.IBinder;
import android.os.ServiceManager;
+import android.os.UserManager;
/**
* The base class for services running in the system process. Override and implement
@@ -133,9 +134,16 @@
public void onStartUser(int userHandle) {}
/**
- * Called when an existing user is unlocked. This means the
- * credential-encrypted storage for that user is now available, and
- * encryption-aware component filtering is no longer in effect.
+ * Called when an existing user is in the process of being unlocked. This
+ * means the credential-encrypted storage for that user is now available,
+ * and encryption-aware component filtering is no longer in effect.
+ * <p>
+ * While dispatching this event to services, the user is in the
+ * {@code STATE_RUNNING_UNLOCKING} state, and once dispatching is finished
+ * the user will transition into the {@code STATE_RUNNING_UNLOCKED} state.
+ * Code written inside system services should use
+ * {@link UserManager#isUserUnlockingOrUnlocked(int)} to handle both of
+ * these states.
*
* @param userHandle The identifier of the user.
*/
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7524351..67cac98 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3023,15 +3023,24 @@
startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);
} else {
finishRunningVoiceLocked();
- IVoiceInteractionSession session;
- if (mLastResumedActivity != null
- && ((session = mLastResumedActivity.task.voiceSession) != null
- || (session = mLastResumedActivity.voiceSession) != null)) {
- // We had been in a voice interaction session, but now focused has
- // move to something different. Just finish the session, we can't
- // return to it and retain the proper state and synchronization with
- // the voice interaction service.
- finishVoiceTask(session);
+
+ if (mLastResumedActivity != null) {
+ final IVoiceInteractionSession session;
+
+ if (mLastResumedActivity.task != null
+ && mLastResumedActivity.task.voiceSession != null) {
+ session = mLastResumedActivity.task.voiceSession;
+ } else {
+ session = mLastResumedActivity.voiceSession;
+ }
+
+ if (session != null) {
+ // We had been in a voice interaction session, but now focused has
+ // move to something different. Just finish the session, we can't
+ // return to it and retain the proper state and synchronization with
+ // the voice interaction service.
+ finishVoiceTask(session);
+ }
}
}
@@ -10636,7 +10645,7 @@
providers = AppGlobals.getPackageManager()
.queryContentProviders(app.processName, app.uid,
STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS
- | MATCH_DEBUG_TRIAGED_MISSING)
+ | MATCH_DEBUG_TRIAGED_MISSING, /*metadastaKey=*/ null)
.getList();
} catch (RemoteException ex) {
}
@@ -10702,16 +10711,14 @@
try {
cpi = AppGlobals.getPackageManager().resolveContentProvider(authority,
STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS
+ | PackageManager.MATCH_DISABLED_COMPONENTS
| PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
userId);
} catch (RemoteException ignored) {
}
if (cpi == null) {
- // TODO: make this an outright failure in a future platform release;
- // until then anonymous content notifications are unprotected
- //return "Failed to find provider " + authority + " for user " + userId;
- return null;
+ return "Failed to find provider " + authority + " for user " + userId;
}
ProcessRecord r = null;
@@ -18025,15 +18032,18 @@
} else if (rl.uid != callingUid) {
throw new IllegalArgumentException(
"Receiver requested to register for uid " + callingUid
- + " was previously registered for uid " + rl.uid);
+ + " was previously registered for uid " + rl.uid
+ + " callerPackage is " + callerPackage);
} else if (rl.pid != callingPid) {
throw new IllegalArgumentException(
"Receiver requested to register for pid " + callingPid
- + " was previously registered for pid " + rl.pid);
+ + " was previously registered for pid " + rl.pid
+ + " callerPackage is " + callerPackage);
} else if (rl.userId != userId) {
throw new IllegalArgumentException(
"Receiver requested to register for user " + userId
- + " was previously registered for user " + rl.userId);
+ + " was previously registered for user " + rl.userId
+ + " callerPackage is " + callerPackage);
}
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId);
@@ -19723,7 +19733,7 @@
mStackSupervisor.setDisplayOverrideConfiguration(mTempConfig, displayId);
final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
- if (isDensityChange) {
+ if (isDensityChange && displayId == DEFAULT_DISPLAY) {
// Reset the unsupported display size dialog.
mUiHandler.sendEmptyMessage(SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index aef429e..10055c8 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -802,10 +802,7 @@
// Remove the activity from the old task and add it to the new task
prevTask.removeActivity(this);
- // TODO(b/34179495): This should really be set to null in removeActivity() call above,
- // but really bad things that I can't track down right now happen when I do that.
- // So, setting it here now and will change later when there is time for investigation.
- task = null;
+
newTask.addActivityAtIndex(position, this);
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 6f79bc27..ab1559d 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -177,7 +177,6 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -4902,7 +4901,7 @@
setResizingDuringAnimation(task);
}
- mService.mActivityStarter.postStartActivityUncheckedProcessing(task.getTopActivity(),
+ mService.mActivityStarter.postStartActivityProcessing(task.getTopActivity(),
ActivityManager.START_TASK_TO_FRONT,
sourceRecord != null ? sourceRecord.task.getStackId() : INVALID_STACK_ID,
sourceRecord, task.getStack());
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 83d43db..d8c5533 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import static android.app.Activity.RESULT_CANCELED;
+import static android.app.ActivityManager.START_CANCELED;
import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
@@ -88,12 +89,10 @@
import android.app.AppGlobals;
import android.app.IActivityContainer;
import android.app.IApplicationThread;
-import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.ProfilerInfo;
import android.app.WaitResult;
import android.content.ComponentName;
-import android.content.Context;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
@@ -509,33 +508,26 @@
doPendingActivityLaunchesLocked(false);
- try {
- mService.mWindowManager.deferSurfaceLayout();
- err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
- true, options, inTask);
- } finally {
- mService.mWindowManager.continueSurfaceLayout();
- }
- postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
- return err;
+ return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
+ options, inTask);
}
/** Creates a launch intent for the given auxiliary resolution data. */
private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
- Intent originalIntent, String callingPackage,
- String resolvedType, int userId) {
+ Intent originalIntent, String callingPackage,
+ String resolvedType, int userId) {
if (auxiliaryResponse.needsPhaseTwo) {
// request phase two resolution
mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
- auxiliaryResponse, originalIntent, resolvedType, callingPackage, userId);
+ auxiliaryResponse, originalIntent, resolvedType, callingPackage, userId);
}
return EphemeralResolver.buildEphemeralInstallerIntent(originalIntent,
- callingPackage, resolvedType, userId, auxiliaryResponse.packageName,
- auxiliaryResponse.splitName, auxiliaryResponse.versionCode,
- auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
+ callingPackage, resolvedType, userId, auxiliaryResponse.packageName,
+ auxiliaryResponse.splitName, auxiliaryResponse.versionCode,
+ auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
}
- void postStartActivityUncheckedProcessing(
+ void postStartActivityProcessing(
ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
ActivityStack targetStack) {
@@ -937,6 +929,32 @@
}
}
+ private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
+ IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
+ int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
+ int result = START_CANCELED;
+ try {
+ mService.mWindowManager.deferSurfaceLayout();
+ result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
+ startFlags,
+ doResume, options, inTask);
+ } finally {
+ // If we are not able to proceed, disassociate the activity from the task. Leaving an
+ // activity in an incomplete state can lead to issues, such as performing operations
+ // without a window container.
+ if (result != START_SUCCESS && mStartActivity.task != null) {
+ mStartActivity.task.removeActivity(mStartActivity);
+ }
+ mService.mWindowManager.continueSurfaceLayout();
+ }
+
+ postStartActivityProcessing(r, result, mSupervisor.mFocusedStack.mStackId,
+ mSourceRecord, mTargetStack);
+
+ return result;
+ }
+
+ // Note: This method should only be called from {@link startActivity}.
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
@@ -1843,11 +1861,8 @@
final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
try {
- final int result = startActivityUnchecked(
- pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
- postStartActivityUncheckedProcessing(
- pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
- mTargetStack);
+ startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
+ null);
} catch (Exception e) {
Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
pal.sendErrorResult(e.getMessage());
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index f8645d6..b051304 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -1083,6 +1083,13 @@
/** @return true if this was the last activity in the task */
boolean removeActivity(ActivityRecord r) {
+ if (r.task != this) {
+ throw new IllegalArgumentException(
+ "Activity=" + r + " does not belong to task=" + this);
+ }
+
+ r.task = null;
+
if (mActivities.remove(r) && r.fullscreen) {
// Was previously in list.
numFullscreen--;
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index e8ff510..d648dd8 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -51,14 +51,36 @@
private final static boolean DEBUG = false;
private final static int VOLUME_SHAPER_SYSTEM_DUCK_ID = 1;
- private ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>();
+ private final VolumeShaper.Configuration DUCK_VSHAPE =
+ new VolumeShaper.Configuration.Builder()
+ .setId(VOLUME_SHAPER_SYSTEM_DUCK_ID)
+ .setCurve(new float[] { 0.f, 1.f } /* times */,
+ new float[] { 1.f, 0.2f } /* volumes */)
+ .setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
+ .setDurationMs(MediaFocusControl.getFocusRampTimeMs(
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
+ new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION)
+ .build()))
+ .build();
+ private final VolumeShaper.Configuration DUCK_ID =
+ new VolumeShaper.Configuration(VOLUME_SHAPER_SYSTEM_DUCK_ID);
+ private final VolumeShaper.Operation PLAY_CREATE_IF_NEEDED =
+ new VolumeShaper.Operation.Builder(VolumeShaper.Operation.PLAY)
+ .createIfNeeded()
+ .build();
+ private final VolumeShaper.Operation TERMINATE =
+ new VolumeShaper.Operation.Builder()
+ .terminate()
+ .build();
+
+ private final ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>();
// a public client is one that needs an anonymized version of the playback configurations, we
// keep track of whether there is at least one to know when we need to create the list of
// playback configurations that do not contain uid/pid/package name information.
private boolean mHasPublicClients = false;
private final Object mPlayerLock = new Object();
- private HashMap<Integer, AudioPlaybackConfiguration> mPlayers =
+ private final HashMap<Integer, AudioPlaybackConfiguration> mPlayers =
new HashMap<Integer, AudioPlaybackConfiguration>();
PlaybackActivityMonitor() {
@@ -130,12 +152,10 @@
synchronized(mPlayerLock) {
final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
if (checkConfigurationCaller(piid, apc, binderUid)) {
+ apc.getPlayerProxy().applyVolumeShaper(
+ DUCK_ID,
+ TERMINATE);
mPlayers.remove(new Integer(piid));
- final VolumeShaper vs = mDuckVolumeShapers.get(new Integer(piid));
- if (vs != null) {
- vs.release();
- mDuckVolumeShapers.remove(new Integer(piid));
- }
} else {
Log.e(TAG, "Error releasing player " + piid);
}
@@ -252,20 +272,6 @@
private final ArrayList<Integer> mDuckedPlayers = new ArrayList<Integer>();
private final ArrayList<Integer> mMutedPlayers = new ArrayList<Integer>();
- private final VolumeShaper.Configuration DUCK_VSHAPE =
- new VolumeShaper.Configuration.Builder()
- .setId(VOLUME_SHAPER_SYSTEM_DUCK_ID)
- .setCurve(new float[] { 0.f, 1.f } /* times */,
- new float[] { 1.f, 0.2f } /* volumes */)
- .setDurationMs(MediaFocusControl.getFocusRampTimeMs(
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
- new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION)
- .build()))
- .build();
-
- private final HashMap<Integer, VolumeShaper> mDuckVolumeShapers =
- new HashMap<Integer, VolumeShaper>();
-
@Override
public boolean duckPlayers(FocusRequester winner, FocusRequester loser) {
if (DEBUG) {
@@ -302,17 +308,9 @@
} else {
try {
if (DEBUG) { Log.v(TAG, "ducking player " + piid); }
- final VolumeShaper ducker;
- if (mDuckVolumeShapers.containsKey(new Integer(piid))) {
- ducker = mDuckVolumeShapers.get(new Integer(piid));
- } else {
- ducker = new VolumeShaper(
- DUCK_VSHAPE,
- apc.getPlayerProxy(),
- true /* keepReference */);
- mDuckVolumeShapers.put(new Integer(piid), ducker);
- }
- ducker.apply(VolumeShaper.Operation.PLAY); // duck
+ apc.getPlayerProxy().applyVolumeShaper(
+ DUCK_VSHAPE,
+ PLAY_CREATE_IF_NEEDED);
mDuckedPlayers.add(piid);
} catch (Exception e) {
Log.e(TAG, "Error ducking player " + piid, e);
@@ -341,10 +339,9 @@
try {
if (DEBUG) { Log.v(TAG, "unducking player" + piid); }
mDuckedPlayers.remove(new Integer(piid));
- if (mDuckVolumeShapers.containsKey(new Integer(piid))) {
- final VolumeShaper ducker = mDuckVolumeShapers.get(new Integer(piid));
- ducker.apply(VolumeShaper.Operation.REVERSE); // unduck
- }
+ apc.getPlayerProxy().applyVolumeShaper(
+ DUCK_ID,
+ VolumeShaper.Operation.REVERSE);
} catch (Exception e) {
Log.e(TAG, "Error unducking player " + piid, e);
}
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 886c97f..4b34eba56 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -43,6 +43,7 @@
import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.FactoryTest;
import android.os.IBinder;
@@ -287,7 +288,7 @@
*/
@Override
public void registerContentObserver(Uri uri, boolean notifyForDescendants,
- IContentObserver observer, int userHandle) {
+ IContentObserver observer, int userHandle, int targetSdkVersion) {
if (observer == null || uri == null) {
throw new IllegalArgumentException("You must pass a valid uri and observer");
}
@@ -301,8 +302,17 @@
final String msg = LocalServices.getService(ActivityManagerInternal.class)
.checkContentProviderAccess(uri.getAuthority(), userHandle);
if (msg != null) {
- Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg);
- return;
+ if (targetSdkVersion >= Build.VERSION_CODES.O) {
+ throw new SecurityException(msg);
+ } else {
+ if (msg.startsWith("Failed to find provider")) {
+ // Sigh, we need to quietly let apps targeting older API
+ // levels notify on non-existent providers.
+ } else {
+ Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg);
+ return;
+ }
+ }
}
synchronized (mRootNode) {
@@ -316,7 +326,7 @@
public void registerContentObserver(Uri uri, boolean notifyForDescendants,
IContentObserver observer) {
registerContentObserver(uri, notifyForDescendants, observer,
- UserHandle.getCallingUserId());
+ UserHandle.getCallingUserId(), Build.VERSION_CODES.CUR_DEVELOPMENT);
}
@Override
@@ -340,8 +350,8 @@
*/
@Override
public void notifyChange(Uri uri, IContentObserver observer,
- boolean observerWantsSelfNotifications, int flags,
- int userHandle) {
+ boolean observerWantsSelfNotifications, int flags, int userHandle,
+ int targetSdkVersion) {
if (DEBUG) Slog.d(TAG, "Notifying update of " + uri + " for user " + userHandle
+ " from observer " + observer + ", flags " + Integer.toHexString(flags));
@@ -359,8 +369,17 @@
final String msg = LocalServices.getService(ActivityManagerInternal.class)
.checkContentProviderAccess(uri.getAuthority(), userHandle);
if (msg != null) {
- Log.w(TAG, "Ignoring notify for " + uri + " from " + uid + ": " + msg);
- return;
+ if (targetSdkVersion >= Build.VERSION_CODES.O) {
+ throw new SecurityException(msg);
+ } else {
+ if (msg.startsWith("Failed to find provider")) {
+ // Sigh, we need to quietly let apps targeting older API
+ // levels notify on non-existent providers.
+ } else {
+ Log.w(TAG, "Ignoring notify for " + uri + " from " + uid + ": " + msg);
+ return;
+ }
+ }
}
// This makes it so that future permission checks will be in the context of this
@@ -427,7 +446,7 @@
boolean observerWantsSelfNotifications, boolean syncToNetwork) {
notifyChange(uri, observer, observerWantsSelfNotifications,
syncToNetwork ? ContentResolver.NOTIFY_SYNC_TO_NETWORK : 0,
- UserHandle.getCallingUserId());
+ UserHandle.getCallingUserId(), Build.VERSION_CODES.CUR_DEVELOPMENT);
}
/**
diff --git a/services/core/java/com/android/server/job/JobPackageTracker.java b/services/core/java/com/android/server/job/JobPackageTracker.java
index 82e2eb4..0a6d8a4 100644
--- a/services/core/java/com/android/server/job/JobPackageTracker.java
+++ b/services/core/java/com/android/server/job/JobPackageTracker.java
@@ -437,7 +437,7 @@
for (int i=0; i<size; i++) {
final int index = mEventIndices.indexOf(i);
final int uid = mEventUids[index];
- if (filterUid != -1 && filterUid != UserHandle.getAppId(filterUid)) {
+ if (filterUid != -1 && filterUid != UserHandle.getAppId(uid)) {
continue;
}
final int cmd = mEventCmds[index];
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index a748013..c973911 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -131,6 +131,8 @@
final List<JobServiceContext> mActiveServices = new ArrayList<>();
/** List of controllers that will notify this service of updates to jobs. */
List<StateController> mControllers;
+ /** Need direct access to this for testing. */
+ BatteryController mBatteryController;
/**
* Queue of pending jobs. The JobServiceContext class will receive jobs from this list
* when ready to execute them.
@@ -194,6 +196,7 @@
// Key names stored in the settings value.
private static final String KEY_MIN_IDLE_COUNT = "min_idle_count";
private static final String KEY_MIN_CHARGING_COUNT = "min_charging_count";
+ private static final String KEY_MIN_BATTERY_NOT_LOW_COUNT = "min_battery_not_low_count";
private static final String KEY_MIN_CONNECTIVITY_COUNT = "min_connectivity_count";
private static final String KEY_MIN_CONTENT_COUNT = "min_content_count";
private static final String KEY_MIN_READY_JOBS_COUNT = "min_ready_jobs_count";
@@ -207,6 +210,7 @@
private static final int DEFAULT_MIN_IDLE_COUNT = 1;
private static final int DEFAULT_MIN_CHARGING_COUNT = 1;
+ private static final int DEFAULT_MIN_BATTERY_NOT_LOW_COUNT = 1;
private static final int DEFAULT_MIN_CONNECTIVITY_COUNT = 1;
private static final int DEFAULT_MIN_CONTENT_COUNT = 1;
private static final int DEFAULT_MIN_READY_JOBS_COUNT = 1;
@@ -229,6 +233,11 @@
*/
int MIN_CHARGING_COUNT = DEFAULT_MIN_CHARGING_COUNT;
/**
+ * Minimum # of "battery not low" jobs that must be ready in order to force the JMS to
+ * schedule things early.
+ */
+ int MIN_BATTERY_NOT_LOW_COUNT = DEFAULT_MIN_BATTERY_NOT_LOW_COUNT;
+ /**
* Minimum # of connectivity jobs that must be ready in order to force the JMS to schedule
* things early. 1 == Run connectivity jobs as soon as ready.
*/
@@ -312,6 +321,8 @@
DEFAULT_MIN_IDLE_COUNT);
MIN_CHARGING_COUNT = mParser.getInt(KEY_MIN_CHARGING_COUNT,
DEFAULT_MIN_CHARGING_COUNT);
+ MIN_BATTERY_NOT_LOW_COUNT = mParser.getInt(KEY_MIN_BATTERY_NOT_LOW_COUNT,
+ DEFAULT_MIN_BATTERY_NOT_LOW_COUNT);
MIN_CONNECTIVITY_COUNT = mParser.getInt(KEY_MIN_CONNECTIVITY_COUNT,
DEFAULT_MIN_CONNECTIVITY_COUNT);
MIN_CONTENT_COUNT = mParser.getInt(KEY_MIN_CONTENT_COUNT,
@@ -356,6 +367,9 @@
pw.print(" "); pw.print(KEY_MIN_CHARGING_COUNT); pw.print("=");
pw.print(MIN_CHARGING_COUNT); pw.println();
+ pw.print(" "); pw.print(KEY_MIN_BATTERY_NOT_LOW_COUNT); pw.print("=");
+ pw.print(MIN_BATTERY_NOT_LOW_COUNT); pw.println();
+
pw.print(" "); pw.print(KEY_MIN_CONNECTIVITY_COUNT); pw.print("=");
pw.print(MIN_CONNECTIVITY_COUNT); pw.println();
@@ -785,7 +799,8 @@
mControllers.add(ConnectivityController.get(this));
mControllers.add(TimeController.get(this));
mControllers.add(IdleController.get(this));
- mControllers.add(BatteryController.get(this));
+ mBatteryController = BatteryController.get(this);
+ mControllers.add(mBatteryController);
mControllers.add(AppIdleController.get(this));
mControllers.add(ContentObserverController.get(this));
mControllers.add(DeviceIdleJobsController.get(this));
@@ -1186,6 +1201,7 @@
*/
class MaybeReadyJobQueueFunctor implements JobStatusFunctor {
int chargingCount;
+ int batteryNotLowCount;
int idleCount;
int backoffCount;
int connectivityCount;
@@ -1223,6 +1239,9 @@
if (job.hasChargingConstraint()) {
chargingCount++;
}
+ if (job.hasBatteryNotLowConstraint()) {
+ batteryNotLowCount++;
+ }
if (job.hasContentTriggerConstraint()) {
contentCount++;
}
@@ -1241,6 +1260,7 @@
idleCount >= mConstants.MIN_IDLE_COUNT ||
connectivityCount >= mConstants.MIN_CONNECTIVITY_COUNT ||
chargingCount >= mConstants.MIN_CHARGING_COUNT ||
+ batteryNotLowCount >= mConstants.MIN_BATTERY_NOT_LOW_COUNT ||
contentCount >= mConstants.MIN_CONTENT_COUNT ||
(runnableJobs != null
&& runnableJobs.size() >= mConstants.MIN_READY_JOBS_COUNT)) {
@@ -1264,6 +1284,7 @@
idleCount = 0;
backoffCount = 0;
connectivityCount = 0;
+ batteryNotLowCount = 0;
contentCount = 0;
runnableJobs = null;
}
@@ -1764,6 +1785,34 @@
return 0;
}
+ void setMonitorBattery(boolean enabled) {
+ synchronized (mLock) {
+ if (mBatteryController != null) {
+ mBatteryController.getTracker().setMonitorBatteryLocked(enabled);
+ }
+ }
+ }
+
+ int getBatterySeq() {
+ synchronized (mLock) {
+ return mBatteryController != null ? mBatteryController.getTracker().getSeq() : -1;
+ }
+ }
+
+ boolean getBatteryCharging() {
+ synchronized (mLock) {
+ return mBatteryController != null
+ ? mBatteryController.getTracker().isOnStablePower() : false;
+ }
+ }
+
+ boolean getBatteryNotLow() {
+ synchronized (mLock) {
+ return mBatteryController != null
+ ? mBatteryController.getTracker().isBatteryNotLow() : false;
+ }
+ }
+
private String printContextIdToJobMap(JobStatus[] map, String initial) {
StringBuilder s = new StringBuilder(initial + ": ");
for (int i=0; i<map.length; i++) {
diff --git a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
index 2d62c1c..ec23407 100644
--- a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -43,10 +43,19 @@
public int onCommand(String cmd) {
final PrintWriter pw = getOutPrintWriter();
try {
- if ("run".equals(cmd)) {
- return runJob();
- } else {
- return handleDefaultCommands(cmd);
+ switch (cmd != null ? cmd : "") {
+ case "run":
+ return runJob(pw);
+ case "monitor-battery":
+ return runMonitorBattery(pw);
+ case "get-battery-seq":
+ return runGetBatterySeq(pw);
+ case "get-battery-charging":
+ return runGetBatteryCharging(pw);
+ case "get-battery-not-low":
+ return runGetBatteryNotLow(pw);
+ default:
+ return handleDefaultCommands(cmd);
}
} catch (Exception e) {
pw.println("Exception: " + e);
@@ -54,20 +63,23 @@
return -1;
}
- private int runJob() {
- try {
- final int uid = Binder.getCallingUid();
- final int perm = mPM.checkUidPermission(
- "android.permission.CHANGE_APP_IDLE_STATE", uid);
- if (perm != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Uid " + uid
- + " not permitted to force scheduled jobs");
- }
- } catch (RemoteException e) {
- // Can't happen
+ private void checkPermission(String operation) throws Exception {
+ final int uid = Binder.getCallingUid();
+ if (uid == 0) {
+ // Root can do anything.
+ return;
}
+ final int perm = mPM.checkUidPermission(
+ "android.permission.CHANGE_APP_IDLE_STATE", uid);
+ if (perm != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Uid " + uid
+ + " not permitted to " + operation);
+ }
+ }
- final PrintWriter pw = getOutPrintWriter();
+ private int runJob(PrintWriter pw) throws Exception {
+ checkPermission("force scheduled jobs");
+
boolean force = false;
int userId = UserHandle.USER_SYSTEM;
@@ -133,6 +145,42 @@
return ret;
}
+ private int runMonitorBattery(PrintWriter pw) throws Exception {
+ checkPermission("change battery monitoring");
+ String opt = getNextArgRequired();
+ boolean enabled;
+ if ("on".equals(opt)) {
+ enabled = true;
+ } else if ("off".equals(opt)) {
+ enabled = false;
+ } else {
+ getErrPrintWriter().println("Error: unknown option " + opt);
+ return 1;
+ }
+ mInternal.setMonitorBattery(enabled);
+ if (enabled) pw.println("Battery monitoring enabled");
+ else pw.println("Battery monitoring disabled");
+ return 0;
+ }
+
+ private int runGetBatterySeq(PrintWriter pw) {
+ int seq = mInternal.getBatterySeq();
+ pw.println(seq);
+ return 0;
+ }
+
+ private int runGetBatteryCharging(PrintWriter pw) {
+ boolean val = mInternal.getBatteryCharging();
+ pw.println(val);
+ return 0;
+ }
+
+ private int runGetBatteryNotLow(PrintWriter pw) {
+ boolean val = mInternal.getBatteryNotLow();
+ pw.println(val);
+ return 0;
+ }
+
@Override
public void onHelp() {
final PrintWriter pw = getOutPrintWriter();
@@ -140,7 +188,6 @@
pw.println("Job scheduler (jobscheduler) commands:");
pw.println(" help");
pw.println(" Print this help text.");
- pw.println();
pw.println(" run [-f | --force] [-u | --user USER_ID] PACKAGE JOB_ID");
pw.println(" Trigger immediate execution of a specific scheduled job.");
pw.println(" Options:");
@@ -148,6 +195,15 @@
pw.println(" connectivity are not currently met");
pw.println(" -u or --user: specify which user's job is to be run; the default is");
pw.println(" the primary or system user");
+ pw.println(" monitor-battery [on|off]");
+ pw.println(" Control monitoring of all battery changes. Off by default. Turning");
+ pw.println(" on makes get-battery-seq useful.");
+ pw.println(" get-battery-seq");
+ pw.println(" Return the last battery update sequence number that was received.");
+ pw.println(" get-battery-charging");
+ pw.println(" Return whether the battery is currently considered to be charging.");
+ pw.println(" get-battery-not-low");
+ pw.println(" Return whether the battery is currently considered to not be low.");
pw.println();
}
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index dd3f85f..ccfc287 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -381,6 +381,9 @@
if (jobStatus.hasChargingConstraint()) {
out.attribute(null, "charging", Boolean.toString(true));
}
+ if (jobStatus.hasBatteryNotLowConstraint()) {
+ out.attribute(null, "battery-not-low", Boolean.toString(true));
+ }
out.endTag(null, XML_TAG_PARAMS_CONSTRAINTS);
}
diff --git a/services/core/java/com/android/server/job/controllers/BatteryController.java b/services/core/java/com/android/server/job/controllers/BatteryController.java
index f6b8ef4..05527be 100644
--- a/services/core/java/com/android/server/job/controllers/BatteryController.java
+++ b/services/core/java/com/android/server/job/controllers/BatteryController.java
@@ -80,32 +80,38 @@
@Override
public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
- final boolean isOnStablePower = mChargeTracker.isOnStablePower();
- if (taskStatus.hasChargingConstraint()) {
+ if (taskStatus.hasPowerConstraint()) {
mTrackedTasks.add(taskStatus);
- taskStatus.setChargingConstraintSatisfied(isOnStablePower);
+ taskStatus.setChargingConstraintSatisfied(mChargeTracker.isOnStablePower());
+ taskStatus.setBatteryNotLowConstraintSatisfied(mChargeTracker.isBatteryNotLow());
}
}
@Override
public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob, boolean forUpdate) {
- if (taskStatus.hasChargingConstraint()) {
+ if (taskStatus.hasPowerConstraint()) {
mTrackedTasks.remove(taskStatus);
}
}
private void maybeReportNewChargingState() {
final boolean stablePower = mChargeTracker.isOnStablePower();
+ final boolean batteryNotLow = mChargeTracker.isBatteryNotLow();
if (DEBUG) {
Slog.d(TAG, "maybeReportNewChargingState: " + stablePower);
}
boolean reportChange = false;
synchronized (mLock) {
- for (JobStatus ts : mTrackedTasks) {
+ for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
+ final JobStatus ts = mTrackedTasks.get(i);
boolean previous = ts.setChargingConstraintSatisfied(stablePower);
if (previous != stablePower) {
reportChange = true;
}
+ previous = ts.setBatteryNotLowConstraintSatisfied(batteryNotLow);
+ if (previous != batteryNotLow) {
+ reportChange = true;
+ }
}
}
// Let the scheduler know that state has changed. This may or may not result in an
@@ -127,6 +133,10 @@
private boolean mCharging;
/** Keep track of whether the battery is charged enough that we want to do work. */
private boolean mBatteryHealthy;
+ /** Sequence number of last broadcast. */
+ private int mLastBatterySeq = -1;
+
+ private BroadcastReceiver mMonitor;
public ChargingTracker() {
}
@@ -149,10 +159,42 @@
mCharging = batteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
}
- boolean isOnStablePower() {
+ public void setMonitorBatteryLocked(boolean enabled) {
+ if (enabled) {
+ if (mMonitor == null) {
+ mMonitor = new BroadcastReceiver() {
+ @Override public void onReceive(Context context, Intent intent) {
+ ChargingTracker.this.onReceive(context, intent);
+ }
+ };
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ mContext.registerReceiver(mMonitor, filter);
+ }
+ } else {
+ if (mMonitor != null) {
+ mContext.unregisterReceiver(mMonitor);
+ mMonitor = null;
+ }
+ }
+ }
+
+ public boolean isOnStablePower() {
return mCharging && mBatteryHealthy;
}
+ public boolean isBatteryNotLow() {
+ return mBatteryHealthy;
+ }
+
+ public boolean isMonitoring() {
+ return mMonitor != null;
+ }
+
+ public int getSeq() {
+ return mLastBatterySeq;
+ }
+
@Override
public void onReceive(Context context, Intent intent) {
onReceiveInternal(intent);
@@ -191,13 +233,20 @@
mCharging = false;
maybeReportNewChargingState();
}
+ mLastBatterySeq = intent.getIntExtra(BatteryManager.EXTRA_SEQUENCE, mLastBatterySeq);
}
}
@Override
public void dumpControllerStateLocked(PrintWriter pw, int filterUid) {
pw.print("Battery: stable power = ");
- pw.println(mChargeTracker.isOnStablePower());
+ pw.print(mChargeTracker.isOnStablePower());
+ pw.print(", not low = ");
+ pw.println(mChargeTracker.isBatteryNotLow());
+ if (mChargeTracker.isMonitoring()) {
+ pw.print("MONITORING: seq=");
+ pw.println(mChargeTracker.getSeq());
+ }
pw.print("Tracking ");
pw.print(mTrackedTasks.size());
pw.println(":");
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 4b39bf9..9a55fed 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -46,16 +46,17 @@
public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE;
public static final long NO_EARLIEST_RUNTIME = 0L;
- static final int CONSTRAINT_CHARGING = 1<<0;
- static final int CONSTRAINT_TIMING_DELAY = 1<<1;
- static final int CONSTRAINT_DEADLINE = 1<<2;
- static final int CONSTRAINT_IDLE = 1<<3;
- static final int CONSTRAINT_UNMETERED = 1<<4;
- static final int CONSTRAINT_CONNECTIVITY = 1<<5;
- static final int CONSTRAINT_APP_NOT_IDLE = 1<<6;
- static final int CONSTRAINT_CONTENT_TRIGGER = 1<<7;
- static final int CONSTRAINT_DEVICE_NOT_DOZING = 1<<8;
- static final int CONSTRAINT_NOT_ROAMING = 1<<9;
+ static final int CONSTRAINT_CHARGING = JobInfo.CONSTRAINT_FLAG_CHARGING;
+ static final int CONSTRAINT_IDLE = JobInfo.CONSTRAINT_FLAG_DEVICE_IDLE;
+ static final int CONSTRAINT_BATTERY_NOT_LOW = JobInfo.CONSTRAINT_FLAG_BATTERY_NOT_LOW;
+ static final int CONSTRAINT_TIMING_DELAY = 1<<31;
+ static final int CONSTRAINT_DEADLINE = 1<<30;
+ static final int CONSTRAINT_UNMETERED = 1<<29;
+ static final int CONSTRAINT_CONNECTIVITY = 1<<28;
+ static final int CONSTRAINT_APP_NOT_IDLE = 1<<27;
+ static final int CONSTRAINT_CONTENT_TRIGGER = 1<<26;
+ static final int CONSTRAINT_DEVICE_NOT_DOZING = 1<<25;
+ static final int CONSTRAINT_NOT_ROAMING = 1<<24;
// Soft override: ignore constraints like time that don't affect API availability
public static final int OVERRIDE_SOFT = 1;
@@ -163,7 +164,7 @@
this.latestRunTimeElapsedMillis = latestRunTimeElapsedMillis;
this.numFailures = numFailures;
- int requiredConstraints = 0;
+ int requiredConstraints = job.getConstraintFlags();
if (job.getNetworkType() == JobInfo.NETWORK_TYPE_ANY) {
requiredConstraints |= CONSTRAINT_CONNECTIVITY;
}
@@ -173,18 +174,12 @@
if (job.getNetworkType() == JobInfo.NETWORK_TYPE_NOT_ROAMING) {
requiredConstraints |= CONSTRAINT_NOT_ROAMING;
}
- if (job.isRequireCharging()) {
- requiredConstraints |= CONSTRAINT_CHARGING;
- }
if (earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME) {
requiredConstraints |= CONSTRAINT_TIMING_DELAY;
}
if (latestRunTimeElapsedMillis != NO_LATEST_RUNTIME) {
requiredConstraints |= CONSTRAINT_DEADLINE;
}
- if (job.isRequireDeviceIdle()) {
- requiredConstraints |= CONSTRAINT_IDLE;
- }
if (job.getTriggerContentUris() != null) {
requiredConstraints |= CONSTRAINT_CONTENT_TRIGGER;
}
@@ -331,6 +326,14 @@
return (requiredConstraints&CONSTRAINT_CHARGING) != 0;
}
+ public boolean hasBatteryNotLowConstraint() {
+ return (requiredConstraints&CONSTRAINT_BATTERY_NOT_LOW) != 0;
+ }
+
+ public boolean hasPowerConstraint() {
+ return (requiredConstraints&(CONSTRAINT_CHARGING|CONSTRAINT_BATTERY_NOT_LOW)) != 0;
+ }
+
public boolean hasTimingDelayConstraint() {
return (requiredConstraints&CONSTRAINT_TIMING_DELAY) != 0;
}
@@ -379,6 +382,10 @@
return setConstraintSatisfied(CONSTRAINT_CHARGING, state);
}
+ boolean setBatteryNotLowConstraintSatisfied(boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW, state);
+ }
+
boolean setTimingDelayConstraintSatisfied(boolean state) {
return setConstraintSatisfied(CONSTRAINT_TIMING_DELAY, state);
}
@@ -453,13 +460,14 @@
}
static final int CONSTRAINTS_OF_INTEREST =
- CONSTRAINT_CHARGING | CONSTRAINT_TIMING_DELAY |
+ CONSTRAINT_CHARGING | CONSTRAINT_BATTERY_NOT_LOW | CONSTRAINT_TIMING_DELAY |
CONSTRAINT_CONNECTIVITY | CONSTRAINT_UNMETERED | CONSTRAINT_NOT_ROAMING |
CONSTRAINT_IDLE | CONSTRAINT_CONTENT_TRIGGER;
// Soft override covers all non-"functional" constraints
static final int SOFT_OVERRIDE_CONSTRAINTS =
- CONSTRAINT_CHARGING | CONSTRAINT_TIMING_DELAY | CONSTRAINT_IDLE;
+ CONSTRAINT_CHARGING | CONSTRAINT_BATTERY_NOT_LOW
+ | CONSTRAINT_TIMING_DELAY | CONSTRAINT_IDLE;
/**
* @return Whether the constraints set on this job are satisfied.
@@ -495,6 +503,7 @@
+ ",R=(" + formatRunTime(earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME)
+ "," + formatRunTime(latestRunTimeElapsedMillis, NO_LATEST_RUNTIME) + ")"
+ ",N=" + job.getNetworkType() + ",C=" + job.isRequireCharging()
+ + ",BL=" + job.isRequireBatteryNotLow()
+ ",I=" + job.isRequireDeviceIdle()
+ ",U=" + (job.getTriggerContentUris() != null)
+ ",F=" + numFailures + ",P=" + job.isPersisted()
@@ -550,6 +559,9 @@
if ((constraints&CONSTRAINT_CHARGING) != 0) {
pw.print(" CHARGING");
}
+ if ((constraints& CONSTRAINT_BATTERY_NOT_LOW) != 0) {
+ pw.print(" BATTERY_NOT_LOW");
+ }
if ((constraints&CONSTRAINT_TIMING_DELAY) != 0) {
pw.print(" TIMING_DELAY");
}
@@ -607,7 +619,8 @@
pw.println(Integer.toHexString(job.getFlags()));
}
pw.print(prefix); pw.print(" Requires: charging=");
- pw.print(job.isRequireCharging()); pw.print(" deviceIdle=");
+ pw.print(job.isRequireCharging()); pw.print(" batteryNotLow=");
+ pw.print(job.isRequireBatteryNotLow()); pw.print(" deviceIdle=");
pw.println(job.isRequireDeviceIdle());
if (job.getTriggerContentUris() != null) {
pw.print(prefix); pw.println(" Trigger content URIs:");
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 36f3287..6349f21 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -37,6 +37,7 @@
import android.media.IAudioService;
import android.media.IRemoteVolumeController;
import android.media.session.IActiveSessionsListener;
+import android.media.session.ICallback;
import android.media.session.IOnMediaKeyListener;
import android.media.session.IOnVolumeKeyLongPressListener;
import android.media.session.ISession;
@@ -107,6 +108,7 @@
private AudioManagerInternal mAudioManagerInternal;
private ContentResolver mContentResolver;
private SettingsObserver mSettingsObserver;
+ private ICallback mCallback;
// List of user IDs running in the foreground.
// Multiple users can be in the foreground if the work profile is on.
@@ -486,6 +488,7 @@
if (size > 0 && records.get(0).isPlaybackActive(false)) {
rememberMediaButtonReceiverLocked(records.get(0));
}
+ pushAddressedPlayerChangedLocked();
ArrayList<MediaSession.Token> tokens = new ArrayList<MediaSession.Token>();
for (int i = 0; i < size; i++) {
tokens.add(new MediaSession.Token(records.get(i).getControllerBinder()));
@@ -517,6 +520,52 @@
}
}
+ private MediaSessionRecord getMediaButtonSessionLocked() {
+ // If we don't have a media button receiver to fall back on
+ // include non-playing sessions for dispatching.
+ boolean useNotPlayingSessions = true;
+ for (int userId : mCurrentUserIdList) {
+ UserRecord ur = mUserRecords.get(userId);
+ if (ur.mLastMediaButtonReceiver != null
+ || ur.mRestoredMediaButtonReceiver != null) {
+ useNotPlayingSessions = false;
+ break;
+ }
+ }
+ return mPriorityStack.getDefaultMediaButtonSession(
+ mCurrentUserIdList, useNotPlayingSessions);
+ }
+
+ private void pushAddressedPlayerChangedLocked() {
+ if (mCallback == null) {
+ return;
+ }
+ try {
+ MediaSessionRecord mediaButtonSession = getMediaButtonSessionLocked();
+ if (mediaButtonSession != null) {
+ mCallback.onAddressedPlayerChangedToMediaSession(
+ new MediaSession.Token(mediaButtonSession.getControllerBinder()));
+ } else {
+ for (int userId : mCurrentUserIdList) {
+ UserRecord user = mUserRecords.get(userId);
+ if (user.mLastMediaButtonReceiver == null
+ && user.mRestoredMediaButtonReceiver == null) {
+ continue;
+ }
+ ComponentName componentName = user.mLastMediaButtonReceiver != null
+ ? user.mLastMediaButtonReceiver.getIntent().getComponent()
+ : user.mRestoredMediaButtonReceiver;
+ mCallback.onAddressedPlayerChangedToMediaButtonReceiver(componentName);
+ return;
+ }
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to pushAddressedPlayerChangedLocked", e);
+ }
+ }
+
+ // Remember media button receiver and keep it in the persistent storage.
+ // This should be called whenever there's no media session to receive media button event.
private void rememberMediaButtonReceiverLocked(MediaSessionRecord record) {
PendingIntent receiver = record.getMediaButtonReceiver();
UserRecord user = mUserRecords.get(record.getUserId());
@@ -801,19 +850,74 @@
+ "setup is in progress.");
return;
}
- if (isGlobalPriorityActive() && uid != Process.SYSTEM_UID) {
- // Prevent dispatching key event through reflection while the global priority
- // session is active.
- Slog.i(TAG, "Only the system can dispatch media key event "
- + "to the global priority session.");
- return;
- }
synchronized (mLock) {
- if (!isGlobalPriorityActive() && isVoiceKey(keyEvent.getKeyCode())) {
+ boolean isGlobalPriorityActive = mPriorityStack.isGlobalPriorityActive();
+ if (isGlobalPriorityActive && uid != Process.SYSTEM_UID) {
+ // Prevent dispatching key event through reflection while the global
+ // priority session is active.
+ Slog.i(TAG, "Only the system can dispatch media key event "
+ + "to the global priority session.");
+ return;
+ }
+ if (!isGlobalPriorityActive) {
+ // Only consider full user.
+ UserRecord user = mUserRecords.get(mCurrentUserIdList.get(0));
+ if (user.mOnMediaKeyListener != null) {
+ if (DEBUG_KEY_EVENT) {
+ Log.d(TAG, "Send " + keyEvent + " to media key listener");
+ }
+ try {
+ user.mOnMediaKeyListener.onMediaKey(keyEvent,
+ new MediaKeyListenerResultReceiver(keyEvent, needWakeLock));
+ return;
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to send " + keyEvent + " to media key listener");
+ }
+ }
+ }
+ if (!isGlobalPriorityActive && isVoiceKey(keyEvent.getKeyCode())) {
handleVoiceKeyEventLocked(keyEvent, needWakeLock);
} else {
- dispatchMediaKeyEventLocked(keyEvent, needWakeLock, true);
+ dispatchMediaKeyEventLocked(keyEvent, needWakeLock);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void setCallback(ICallback callback) {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (uid != Process.BLUETOOTH_UID) {
+ throw new SecurityException("Only Bluetooth service processes can set"
+ + " Callback");
+ }
+ synchronized (mLock) {
+ Log.d(TAG, "Callback + " + mCallback
+ + " is set by " + getCallingPackageName(uid));
+ mCallback = callback;
+ if (mCallback == null) {
+ return;
+ }
+ try {
+ mCallback.asBinder().linkToDeath(
+ new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ synchronized (mLock) {
+ mCallback = null;
+ }
+ }
+ }, 0);
+ pushAddressedPlayerChangedLocked();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to set callback", e);
+ mCallback = null;
}
}
} finally {
@@ -1080,7 +1184,9 @@
@Override
public boolean isGlobalPriorityActive() {
- return mPriorityStack.isGlobalPriorityActive();
+ synchronized (mLock) {
+ return mPriorityStack.isGlobalPriorityActive();
+ }
}
@Override
@@ -1190,52 +1296,15 @@
if (!mVoiceButtonHandled && !keyEvent.isCanceled()) {
// Resend the down then send this event through
KeyEvent downEvent = KeyEvent.changeAction(keyEvent, KeyEvent.ACTION_DOWN);
- dispatchMediaKeyEventLocked(downEvent, needWakeLock, true);
- dispatchMediaKeyEventLocked(keyEvent, needWakeLock, true);
+ dispatchMediaKeyEventLocked(downEvent, needWakeLock);
+ dispatchMediaKeyEventLocked(keyEvent, needWakeLock);
}
}
}
}
- private void dispatchMediaKeyEventLocked(KeyEvent keyEvent, boolean needWakeLock,
- boolean checkMediaKeyListener) {
- // If we don't have a media button receiver to fall back on
- // include non-playing sessions for dispatching.
- boolean useNotPlayingSessions = true;
- for (int userId : mCurrentUserIdList) {
- UserRecord ur = mUserRecords.get(userId);
- if (ur.mLastMediaButtonReceiver != null
- || ur.mRestoredMediaButtonReceiver != null) {
- useNotPlayingSessions = false;
- break;
- }
- }
- if (DEBUG) {
- Log.d(TAG, "dispatchMediaKeyEvent, useNotPlayingSessions="
- + useNotPlayingSessions);
- }
-
- MediaSessionRecord session = mPriorityStack.getDefaultMediaButtonSession(
- mCurrentUserIdList, useNotPlayingSessions);
-
- if ((session == null
- || !session.hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY))
- && checkMediaKeyListener) {
- // Only consider full user.
- UserRecord user = mUserRecords.get(mCurrentUserIdList.get(0));
- if (user.mOnMediaKeyListener != null) {
- if (DEBUG_KEY_EVENT) {
- Log.d(TAG, "Send " + keyEvent + " to media key listener");
- }
- try {
- user.mOnMediaKeyListener.onMediaKey(keyEvent,
- new MediaKeyListenerResultReceiver(keyEvent, needWakeLock));
- return;
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to send " + keyEvent + " to media key listener");
- }
- }
- }
+ private void dispatchMediaKeyEventLocked(KeyEvent keyEvent, boolean needWakeLock) {
+ MediaSessionRecord session = getMediaButtonSessionLocked();
if (session != null) {
if (DEBUG_KEY_EVENT) {
Log.d(TAG, "Sending " + keyEvent + " to " + session);
@@ -1248,6 +1317,14 @@
needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
mKeyEventReceiver, Process.SYSTEM_UID,
getContext().getPackageName());
+ if (mCallback != null) {
+ try {
+ mCallback.onMediaKeyEventDispatchedToMediaSession(keyEvent,
+ new MediaSession.Token(session.getControllerBinder()));
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to send callback", e);
+ }
+ }
} else {
// Launch the last PendingIntent we had with priority
for (int userId : mCurrentUserIdList) {
@@ -1264,26 +1341,41 @@
mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
try {
if (user.mLastMediaButtonReceiver != null) {
+ PendingIntent receiver = user.mLastMediaButtonReceiver;
if (DEBUG_KEY_EVENT) {
Log.d(TAG, "Sending " + keyEvent
- + " to the last known pendingIntent "
- + user.mLastMediaButtonReceiver);
+ + " to the last known pendingIntent " + receiver);
}
- user.mLastMediaButtonReceiver.send(getContext(),
+ receiver.send(getContext(),
needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
mediaButtonIntent, mKeyEventReceiver, mHandler);
+ if (mCallback != null) {
+ ComponentName componentName =
+ user.mLastMediaButtonReceiver.getIntent().getComponent();
+ if (componentName != null) {
+ mCallback.onMediaKeyEventDispatchedToMediaButtonReceiver(
+ keyEvent, componentName);
+ }
+ }
} else {
+ ComponentName receiver = user.mRestoredMediaButtonReceiver;
if (DEBUG_KEY_EVENT) {
Log.d(TAG, "Sending " + keyEvent + " to the restored intent "
- + user.mRestoredMediaButtonReceiver);
+ + receiver);
}
- mediaButtonIntent.setComponent(user.mRestoredMediaButtonReceiver);
+ mediaButtonIntent.setComponent(receiver);
getContext().sendBroadcastAsUser(mediaButtonIntent,
UserHandle.of(userId));
+ if (mCallback != null) {
+ mCallback.onMediaKeyEventDispatchedToMediaButtonReceiver(
+ keyEvent, receiver);
+ }
}
} catch (CanceledException e) {
Log.i(TAG, "Error sending key event to media button receiver "
+ user.mLastMediaButtonReceiver, e);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to send callback", e);
}
return;
}
@@ -1394,7 +1486,12 @@
mHandled = true;
mHandler.removeCallbacks(this);
synchronized (mLock) {
- dispatchMediaKeyEventLocked(mKeyEvent, mNeedWakeLock, false);
+ if (!mPriorityStack.isGlobalPriorityActive()
+ && isVoiceKey(mKeyEvent.getKeyCode())) {
+ handleVoiceKeyEventLocked(mKeyEvent, mNeedWakeLock);
+ } else {
+ dispatchMediaKeyEventLocked(mKeyEvent, mNeedWakeLock);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/notification/BadgeExtractor.java b/services/core/java/com/android/server/notification/BadgeExtractor.java
index 4795fbf..e6edaf1 100644
--- a/services/core/java/com/android/server/notification/BadgeExtractor.java
+++ b/services/core/java/com/android/server/notification/BadgeExtractor.java
@@ -46,7 +46,9 @@
if (!appCanShowBadge) {
record.setShowBadge(false);
} else {
- record.setShowBadge(record.getChannel().canShowBadge() && appCanShowBadge);
+ record.setShowBadge(mConfig.getNotificationChannel(record.sbn.getPackageName(),
+ record.sbn.getUid(), record.getChannel().getId(), false).canShowBadge()
+ && appCanShowBadge);
}
return null;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8f4ad00..45ff20b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2029,11 +2029,11 @@
*/
@Override
public void snoozeNotificationUntilFromListener(INotificationListener token, String key,
- long snoozeUntil) {
+ long duration) {
long identity = Binder.clearCallingIdentity();
try {
final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
- snoozeNotificationInt(key, snoozeUntil, null, info);
+ snoozeNotificationInt(key, duration, null, info);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -3409,7 +3409,7 @@
@VisibleForTesting
void scheduleTimeoutLocked(NotificationRecord record) {
- if (record.getNotification().getTimeout() > System.currentTimeMillis()) {
+ if (record.getNotification().getTimeout() > 0) {
final PendingIntent pi = PendingIntent.getBroadcast(getContext(),
REQUEST_CODE_TIMEOUT,
new Intent(ACTION_NOTIFICATION_TIMEOUT)
@@ -3418,8 +3418,8 @@
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
.putExtra(EXTRA_KEY, record.getKey()),
PendingIntent.FLAG_UPDATE_CURRENT);
- mAlarmManager.setExactAndAllowWhileIdle(
- AlarmManager.RTC_WAKEUP, record.getNotification().getTimeout(), pi);
+ mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + record.getNotification().getTimeout(), pi);
}
}
@@ -4185,16 +4185,16 @@
}
}
- void snoozeNotificationInt(String key, long until, String snoozeCriterionId,
+ void snoozeNotificationInt(String key, long duration, String snoozeCriterionId,
ManagedServiceInfo listener) {
String listenerName = listener == null ? null : listener.component.toShortString();
- if (until < System.currentTimeMillis() && snoozeCriterionId == null) {
+ if (duration <= 0 && snoozeCriterionId == null) {
return;
}
if (DBG) {
- Slog.d(TAG, String.format("snooze event(%s, %d, %s, %s)", key, until, snoozeCriterionId,
- listenerName));
+ Slog.d(TAG, String.format("snooze event(%s, %d, %s, %s)", key, duration,
+ snoozeCriterionId, listenerName));
}
// Needs to post so that it can cancel notifications not yet enqueued.
mHandler.post(new Runnable() {
@@ -4215,7 +4215,7 @@
snoozeCriterionId);
mSnoozeHelper.snooze(r);
} else {
- mSnoozeHelper.snooze(r, until);
+ mSnoozeHelper.snooze(r, duration);
}
savePolicyFile();
}
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index 0cd8cea..913f636 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -32,6 +32,7 @@
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Binder;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
@@ -125,9 +126,9 @@
/**
* Snoozes a notification and schedules an alarm to repost at that time.
*/
- protected void snooze(NotificationRecord record, long until) {
+ protected void snooze(NotificationRecord record, long duration) {
snooze(record);
- scheduleRepost(record.sbn.getPackageName(), record.getKey(), record.getUserId(), until);
+ scheduleRepost(record.sbn.getPackageName(), record.getKey(), record.getUserId(), duration);
}
/**
@@ -291,13 +292,14 @@
PendingIntent.FLAG_UPDATE_CURRENT);
}
- private void scheduleRepost(String pkg, String key, int userId, long time) {
+ private void scheduleRepost(String pkg, String key, int userId, long duration) {
long identity = Binder.clearCallingIdentity();
try {
final PendingIntent pi = createPendingIntent(pkg, key, userId);
mAm.cancel(pi);
+ long time = SystemClock.elapsedRealtime() + duration;
if (DEBUG) Slog.d(TAG, "Scheduling evaluate for " + new Date(time));
- mAm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, pi);
+ mAm.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, time, pi);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index c11131a..71bfa64 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -442,8 +442,8 @@
@Override
public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
- String packageName, List shortcutIds, ComponentName componentName, int flags,
- UserHandle targetUser) {
+ String packageName, List shortcutIds, ComponentName componentName, Intent intent,
+ int flags, UserHandle targetUser) {
ensureShortcutPermission(callingPackage);
if (!canAccessProfile(callingPackage, targetUser, "Cannot get shortcuts")
|| !isUserEnabled(targetUser)) {
@@ -454,11 +454,17 @@
"To query by shortcut ID, package name must also be set");
}
+ if ((flags & ShortcutQuery.FLAG_MATCH_CHOOSER) == 0
+ && intent != null) {
+ throw new IllegalArgumentException("Supplied an intent in the query, but did "
+ + "not request chooser targets");
+ }
+
// TODO(b/29399275): Eclipse compiler requires explicit List<ShortcutInfo> cast below.
return new ParceledListSlice<>((List<ShortcutInfo>)
mShortcutServiceInternal.getShortcuts(getCallingUserId(),
callingPackage, changedSince, packageName, shortcutIds,
- componentName, flags, targetUser.getIdentifier()));
+ componentName, intent, flags, targetUser.getIdentifier()));
}
@Override
@@ -906,6 +912,7 @@
cookie.packageName,
/* changedSince= */ 0, packageName, /* shortcutIds=*/ null,
/* component= */ null,
+ /* intent= */ null,
ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
| ShortcutQuery.FLAG_GET_ALL_KINDS
, userId);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 53765f2..a7a1683 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -607,6 +607,12 @@
+ "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
}
+ if ((params.installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0
+ || (params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
+ throw new IllegalArgumentException(
+ "New installs into ASEC containers no longer supported");
+ }
+
// Defensively resize giant app icons
if (params.appIcon != null) {
final ActivityManager am = (ActivityManager) mContext.getSystemService(
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index fbf953f..5ebced8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -128,7 +128,6 @@
import android.content.pm.AppsQueryHelper;
import android.content.pm.ChangedPackages;
import android.content.pm.ComponentInfo;
-import android.content.pm.InstantAppInfo;
import android.content.pm.EphemeralRequest;
import android.content.pm.EphemeralResolveInfo;
import android.content.pm.AuxiliaryResolveInfo;
@@ -143,6 +142,7 @@
import android.content.pm.IPackageManager;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
+import android.content.pm.InstantAppInfo;
import android.content.pm.InstrumentationInfo;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.KeySet;
@@ -204,15 +204,16 @@
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.os.storage.IStorageManager;
-import android.os.storage.StorageManagerInternal;
import android.os.storage.StorageEventListener;
import android.os.storage.StorageManager;
+import android.os.storage.StorageManagerInternal;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
import android.security.KeyStore;
import android.security.SystemKeyStore;
+import android.service.pm.PackageServiceDumpProto;
import android.system.ErrnoException;
import android.system.Os;
import android.text.TextUtils;
@@ -235,6 +236,7 @@
import android.util.SparseIntArray;
import android.util.Xml;
import android.util.jar.StrictJarFile;
+import android.util.proto.ProtoOutputStream;
import android.view.Display;
import com.android.internal.R;
@@ -316,8 +318,8 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
-import java.util.HashSet;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -5682,6 +5684,11 @@
false, false, false, userId);
}
+ /**
+ * Returns whether or not instant apps have been disabled remotely.
+ * <p><em>IMPORTANT</em> This should not be called with the package manager lock
+ * held. Otherwise we run the risk of deadlock.
+ */
private boolean isEphemeralDisabled() {
// ephemeral apps have been disabled across the board
if (DISABLE_EPHEMERAL_APPS) {
@@ -5702,10 +5709,6 @@
private boolean isEphemeralAllowed(
Intent intent, List<ResolveInfo> resolvedActivities, int userId,
boolean skipPackageCheck) {
- // Short circuit and return early if possible.
- if (isEphemeralDisabled()) {
- return false;
- }
final int callingUser = UserHandle.getCallingUserId();
if (callingUser != UserHandle.USER_SYSTEM) {
return false;
@@ -6209,6 +6212,7 @@
boolean addEphemeral = false;
List<ResolveInfo> result;
final String pkgName = intent.getPackage();
+ final boolean ephemeralDisabled = isEphemeralDisabled();
synchronized (mPackages) {
if (pkgName == null) {
List<CrossProfileIntentFilter> matchingFilters =
@@ -6226,8 +6230,8 @@
// Check for results in the current profile.
result = filterIfNotSystemUser(mActivities.queryIntent(
intent, resolvedType, flags, userId), userId);
- addEphemeral =
- isEphemeralAllowed(intent, result, userId, false /*skipPackageCheck*/);
+ addEphemeral = !ephemeralDisabled
+ && isEphemeralAllowed(intent, result, userId, false /*skipPackageCheck*/);
// Check for cross profile results.
boolean hasNonNegativePriorityResult = hasNonNegativePriority(result);
@@ -6284,8 +6288,9 @@
} else {
// the caller wants to resolve for a particular package; however, there
// were no installed results, so, try to find an ephemeral result
- addEphemeral = isEphemeralAllowed(
- intent, null /*result*/, userId, true /*skipPackageCheck*/);
+ addEphemeral = !ephemeralDisabled
+ && isEphemeralAllowed(
+ intent, null /*result*/, userId, true /*skipPackageCheck*/);
result = new ArrayList<ResolveInfo>();
}
}
@@ -7467,7 +7472,7 @@
@Override
public @NonNull ParceledListSlice<ProviderInfo> queryContentProviders(String processName,
- int uid, int flags) {
+ int uid, int flags, String metaDataKey) {
final int userId = processName != null ? UserHandle.getUserId(uid)
: UserHandle.getCallingUserId();
if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
@@ -7485,6 +7490,14 @@
|| (p.info.processName.equals(processName)
&& UserHandle.isSameApp(p.info.applicationInfo.uid, uid)))
&& mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) {
+
+ // See PM.queryContentProviders()'s javadoc for why we have the metaData
+ // parameter.
+ if (metaDataKey != null
+ && (p.metaData == null || !p.metaData.containsKey(metaDataKey))) {
+ continue;
+ }
+
if (finalList == null) {
finalList = new ArrayList<ProviderInfo>(3);
}
@@ -11698,7 +11711,8 @@
if (!whitelisted) {
Slog.w(TAG, "Privileged permission " + perm + " for package "
+ pkg.packageName + " - not in privapp-permissions whitelist");
- if (!mSystemReady) {
+ // Only report violations for apps on system image
+ if (!mSystemReady && !pkg.isUpdatedSystemApp()) {
if (mPrivappPermissionsViolations == null) {
mPrivappPermissionsViolations = new ArraySet<>();
}
@@ -13068,6 +13082,12 @@
+ "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
}
+ if ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0
+ || (installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
+ throw new IllegalArgumentException(
+ "New installs into ASEC containers no longer supported");
+ }
+
final File originFile = new File(originPath);
final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);
@@ -16804,11 +16824,20 @@
res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
}
- // Check whether the newly-scanned package wants to define an already-defined perm
int N = pkg.permissions.size();
for (int i = N-1; i >= 0; i--) {
PackageParser.Permission perm = pkg.permissions.get(i);
BasePermission bp = mSettings.mPermissions.get(perm.info.name);
+
+ // Don't allow anyone but the platform to define ephemeral permissions.
+ if ((perm.info.protectionLevel & PermissionInfo.PROTECTION_FLAG_EPHEMERAL) != 0
+ && !PLATFORM_PACKAGE_NAME.equals(pkg.packageName)) {
+ Slog.w(TAG, "Package " + pkg.packageName
+ + " attempting to delcare ephemeral permission "
+ + perm.info.name + "; Removing ephemeral.");
+ perm.info.protectionLevel &= ~PermissionInfo.PROTECTION_FLAG_EPHEMERAL;
+ }
+ // Check whether the newly-scanned package wants to define an already-defined perm
if (bp != null) {
// If the defining package is signed with our cert, it's okay. This
// also includes the "updating the same package" case, of course.
@@ -18702,7 +18731,7 @@
Slog.w(TAG, "Shame on you for calling a hidden API. Shame!");
try {
observer.onGetStatsCompleted(null, false);
- } catch (RemoteException ignored) {
+ } catch (Throwable ignored) {
}
}
@@ -20299,6 +20328,9 @@
checkin = true;
} else if ("-f".equals(opt)) {
dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
+ } else if ("--proto".equals(opt)) {
+ dumpProto(fd);
+ return;
} else {
pw.println("Unknown argument: " + opt + "; use -h for help");
}
@@ -20836,6 +20868,98 @@
}
}
+ private void dumpProto(FileDescriptor fd) {
+ final ProtoOutputStream proto = new ProtoOutputStream(fd);
+
+ synchronized (mPackages) {
+ final long requiredVerifierPackageToken =
+ proto.start(PackageServiceDumpProto.REQUIRED_VERIFIER_PACKAGE);
+ proto.write(PackageServiceDumpProto.PackageShortProto.NAME, mRequiredVerifierPackage);
+ proto.write(
+ PackageServiceDumpProto.PackageShortProto.UID,
+ getPackageUid(
+ mRequiredVerifierPackage,
+ MATCH_DEBUG_TRIAGED_MISSING,
+ UserHandle.USER_SYSTEM));
+ proto.end(requiredVerifierPackageToken);
+
+ if (mIntentFilterVerifierComponent != null) {
+ String verifierPackageName = mIntentFilterVerifierComponent.getPackageName();
+ final long verifierPackageToken =
+ proto.start(PackageServiceDumpProto.VERIFIER_PACKAGE);
+ proto.write(PackageServiceDumpProto.PackageShortProto.NAME, verifierPackageName);
+ proto.write(
+ PackageServiceDumpProto.PackageShortProto.UID,
+ getPackageUid(
+ verifierPackageName,
+ MATCH_DEBUG_TRIAGED_MISSING,
+ UserHandle.USER_SYSTEM));
+ proto.end(verifierPackageToken);
+ }
+
+ dumpSharedLibrariesProto(proto);
+ dumpFeaturesProto(proto);
+ mSettings.dumpPackagesProto(proto);
+ mSettings.dumpSharedUsersProto(proto);
+ dumpMessagesProto(proto);
+ }
+ proto.flush();
+ }
+
+ private void dumpMessagesProto(ProtoOutputStream proto) {
+ BufferedReader in = null;
+ String line = null;
+ try {
+ in = new BufferedReader(new FileReader(getSettingsProblemFile()));
+ while ((line = in.readLine()) != null) {
+ if (line.contains("ignored: updated version")) continue;
+ proto.write(PackageServiceDumpProto.MESSAGES, line);
+ }
+ } catch (IOException ignored) {
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+ }
+
+ private void dumpFeaturesProto(ProtoOutputStream proto) {
+ synchronized (mAvailableFeatures) {
+ final int count = mAvailableFeatures.size();
+ for (int i = 0; i < count; i++) {
+ final FeatureInfo feat = mAvailableFeatures.valueAt(i);
+ final long featureToken = proto.start(PackageServiceDumpProto.FEATURES);
+ proto.write(PackageServiceDumpProto.FeatureProto.NAME, feat.name);
+ proto.write(PackageServiceDumpProto.FeatureProto.VERSION, feat.version);
+ proto.end(featureToken);
+ }
+ }
+ }
+
+ private void dumpSharedLibrariesProto(ProtoOutputStream proto) {
+ final int count = mSharedLibraries.size();
+ for (int i = 0; i < count; i++) {
+ final String libName = mSharedLibraries.keyAt(i);
+ SparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(libName);
+ if (versionedLib == null) {
+ continue;
+ }
+ final int versionCount = versionedLib.size();
+ for (int j = 0; j < versionCount; j++) {
+ final SharedLibraryEntry libEntry = versionedLib.valueAt(j);
+ final long sharedLibraryToken =
+ proto.start(PackageServiceDumpProto.SHARED_LIBRARIES);
+ proto.write(PackageServiceDumpProto.SharedLibraryProto.NAME, libEntry.info.getName());
+ final boolean isJar = (libEntry.path != null);
+ proto.write(PackageServiceDumpProto.SharedLibraryProto.IS_JAR, isJar);
+ if (isJar) {
+ proto.write(PackageServiceDumpProto.SharedLibraryProto.PATH, libEntry.path);
+ } else {
+ proto.write(PackageServiceDumpProto.SharedLibraryProto.APK, libEntry.apk);
+ }
+ proto.end(sharedLibraryToken);
+ }
+ }
+ }
+
private void dumpDexoptStateLPr(PrintWriter pw, String packageName) {
final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
ipw.println();
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 5f348ab..b4bba88 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -19,6 +19,9 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
+import android.content.pm.UserInfo;
+import android.service.pm.PackageProto;
+import android.util.proto.ProtoOutputStream;
import java.io.File;
import java.util.List;
@@ -128,4 +131,32 @@
}
return true;
}
+
+ public void writeToProto(ProtoOutputStream proto, long fieldId, List<UserInfo> users) {
+ final long packageToken = proto.start(fieldId);
+ proto.write(PackageProto.NAME, (realName != null ? realName : name));
+ proto.write(PackageProto.UID, appId);
+ proto.write(PackageProto.VERSION_CODE, versionCode);
+ proto.write(PackageProto.VERSION_STRING, pkg.mVersionName);
+ proto.write(PackageProto.INSTALL_TIME_MS, firstInstallTime);
+ proto.write(PackageProto.UPDATE_TIME_MS, lastUpdateTime);
+ proto.write(PackageProto.INSTALLER_NAME, installerPackageName);
+
+ if (pkg != null) {
+ long splitToken = proto.start(PackageProto.SPLITS);
+ proto.write(PackageProto.SplitProto.NAME, "base");
+ proto.write(PackageProto.SplitProto.REVISION_CODE, pkg.baseRevisionCode);
+ proto.end(splitToken);
+ if (pkg.splitNames != null) {
+ for (int i = 0; i < pkg.splitNames.length; i++) {
+ splitToken = proto.start(PackageProto.SPLITS);
+ proto.write(PackageProto.SplitProto.NAME, pkg.splitNames[i]);
+ proto.write(PackageProto.SplitProto.REVISION_CODE, pkg.splitRevisionCodes[i]);
+ proto.end(splitToken);
+ }
+ }
+ }
+ writeUsersInfoToProto(proto, PackageProto.USERS);
+ proto.end(packageToken);
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 601377d6..b9c43da 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -25,8 +25,10 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageUserState;
import android.os.storage.VolumeInfo;
+import android.service.pm.PackageProto;
import android.util.ArraySet;
import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
@@ -564,4 +566,32 @@
modifyUserState(userId).domainVerificationStatus =
PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
}
+
+ protected void writeUsersInfoToProto(ProtoOutputStream proto, long fieldId) {
+ int count = userState.size();
+ for (int i = 0; i < count; i++) {
+ final long userToken = proto.start(fieldId);
+ final int userId = userState.keyAt(i);
+ final PackageUserState state = userState.valueAt(i);
+ proto.write(PackageProto.UserInfoProto.ID, userId);
+ final int installType;
+ if (state.instantApp) {
+ installType = PackageProto.UserInfoProto.INSTANT_APP_INSTALL;
+ } else if (state.installed) {
+ installType = PackageProto.UserInfoProto.FULL_APP_INSTALL;
+ } else {
+ installType = PackageProto.UserInfoProto.NOT_INSTALLED_FOR_USER;
+ }
+ proto.write(PackageProto.UserInfoProto.INSTALL_TYPE, installType);
+ proto.write(PackageProto.UserInfoProto.IS_HIDDEN, state.hidden);
+ proto.write(PackageProto.UserInfoProto.IS_SUSPENDED, state.suspended);
+ proto.write(PackageProto.UserInfoProto.IS_STOPPED, state.stopped);
+ proto.write(PackageProto.UserInfoProto.IS_LAUNCHED, !state.notLaunched);
+ proto.write(PackageProto.UserInfoProto.ENABLED_STATE, state.enabled);
+ proto.write(
+ PackageProto.UserInfoProto.LAST_DISABLED_APP_CALLER,
+ state.lastDisableAppCaller);
+ proto.end(userToken);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index a057e9b..570b31f 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -65,6 +65,7 @@
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
+import android.service.pm.PackageServiceDumpProto;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -77,6 +78,7 @@
import android.util.SparseIntArray;
import android.util.SparseLongArray;
import android.util.Xml;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
@@ -887,9 +889,9 @@
}
if (p.appId < 0) {
PackageManagerService.reportSettingsProblem(Log.WARN,
- "Package " + p.name + " could not be assigned a valid uid");
+ "Package " + p.name + " could not be assigned a valid UID");
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
- "Creating application package " + p.name + " failed");
+ "Package " + p.name + " could not be assigned a valid UID");
}
}
@@ -4876,6 +4878,16 @@
}
}
+ void dumpPackagesProto(ProtoOutputStream proto) {
+ List<UserInfo> users = getAllUsers(UserManagerService.getInstance());
+
+ final int count = mPackages.size();
+ for (int i = 0; i < count; i++) {
+ final PackageSetting ps = mPackages.valueAt(i);
+ ps.writeToProto(proto, PackageServiceDumpProto.PACKAGES, users);
+ }
+ }
+
void dumpPermissionsLPr(PrintWriter pw, String packageName, ArraySet<String> permissionNames,
DumpState dumpState) {
boolean printedSomething = false;
@@ -4966,6 +4978,17 @@
}
}
+ void dumpSharedUsersProto(ProtoOutputStream proto) {
+ final int count = mSharedUsers.size();
+ for (int i = 0; i < count; i++) {
+ final SharedUserSetting su = mSharedUsers.valueAt(i);
+ final long sharedUserToken = proto.start(PackageServiceDumpProto.SHARED_USERS);
+ proto.write(PackageServiceDumpProto.SharedUserProto.USER_ID, su.userId);
+ proto.write(PackageServiceDumpProto.SharedUserProto.NAME, su.name);
+ proto.end(sharedUserToken);
+ }
+ }
+
void dumpReadMessagesLPr(PrintWriter pw, DumpState dumpState) {
pw.println("Settings parse messages:");
pw.print(mReadMessages.toString());
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 570259b..ac98ab9 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -20,6 +20,7 @@
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
@@ -31,6 +32,7 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.pm.ShortcutService.ShortcutOperation;
@@ -68,6 +70,9 @@
private static final String TAG_EXTRAS = "extras";
private static final String TAG_SHORTCUT = "shortcut";
private static final String TAG_CATEGORIES = "categories";
+ private static final String TAG_CHOOSER_EXTRAS = "chooser-extras";
+ private static final String TAG_CHOOSER_INTENT_FILTERS = "chooser-intent-filters";
+ private static final String TAG_CHOOSER_COMPONENT_NAMES = "chooser-component-names";
private static final String ATTR_NAME = "name";
private static final String ATTR_CALL_COUNT = "call-count";
@@ -91,6 +96,7 @@
private static final String ATTR_ICON_RES_ID = "icon-res";
private static final String ATTR_ICON_RES_NAME = "icon-resname";
private static final String ATTR_BITMAP_PATH = "bitmap-path";
+ private static final String ATTR_COMPONENT_NAMES = "component-names";
private static final String NAME_CATEGORIES = "categories";
@@ -200,7 +206,7 @@
if (shortcut != null) {
mShortcutUser.mService.removeIcon(getPackageUserId(), shortcut);
shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED
- | ShortcutInfo.FLAG_MANIFEST);
+ | ShortcutInfo.FLAG_MANIFEST | ShortcutInfo.FLAG_CHOOSER);
}
return shortcut;
}
@@ -226,7 +232,7 @@
Preconditions.checkArgument(newShortcut.isEnabled(),
"add/setDynamicShortcuts() cannot publish disabled shortcuts");
- newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
+ addCorrectDynamicFlags(newShortcut);
final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
@@ -250,6 +256,17 @@
addShortcutInner(newShortcut);
}
+ // TODO: Sample code & JavaDoc for ShortcutManager needs updating to reflect the fact that
+ // Chooser shortcuts are not always dynamic.
+ public void addCorrectDynamicFlags(@NonNull ShortcutInfo shortcut) {
+ if (shortcut.getIntent() != null) {
+ shortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
+ }
+ if (!ArrayUtils.isEmpty(shortcut.getChooserIntentFilters())) {
+ shortcut.addFlags(ShortcutInfo.FLAG_CHOOSER);
+ }
+ }
+
/**
* Remove all shortcuts that aren't pinned nor dynamic.
*/
@@ -282,11 +299,11 @@
boolean changed = false;
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
- if (si.isDynamic()) {
+ if (si.isDynamic() || si.isChooser()) {
changed = true;
si.setTimestamp(now);
- si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
+ si.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_CHOOSER);
si.setRank(0); // It may still be pinned, so clear the rank.
}
}
@@ -355,7 +372,8 @@
if (oldShortcut.isPinned()) {
oldShortcut.setRank(0);
- oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
+ oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST
+ | ShortcutInfo.FLAG_CHOOSER);
if (disable) {
oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
}
@@ -1116,8 +1134,8 @@
// Don't adjust ranks for manifest shortcuts.
continue;
}
- // At this point, it must be dynamic.
- if (!si.isDynamic()) {
+ // At this point, it must be dynamic or a chooser.
+ if (!si.isDynamicOrChooser()) {
s.wtf("Non-dynamic shortcut found.");
continue;
}
@@ -1294,7 +1312,7 @@
ShortcutService.writeAttr(out, ATTR_FLAGS,
si.getFlags() &
~(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES
- | ShortcutInfo.FLAG_DYNAMIC));
+ | ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_CHOOSER));
} else {
// When writing for backup, ranks shouldn't be saved, since shortcuts won't be restored
// as dynamic.
@@ -1317,15 +1335,36 @@
}
final Intent[] intentsNoExtras = si.getIntentsNoExtras();
final PersistableBundle[] intentsExtras = si.getIntentPersistableExtrases();
- final int numIntents = intentsNoExtras.length;
- for (int i = 0; i < numIntents; i++) {
- out.startTag(null, TAG_INTENT);
- ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
- ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
- out.endTag(null, TAG_INTENT);
+ if (intentsNoExtras != null) {
+ final int numIntents = intentsNoExtras.length;
+ for (int i = 0; i < numIntents; i++) {
+ out.startTag(null, TAG_INTENT);
+ ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
+ ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
+ out.endTag(null, TAG_INTENT);
+ }
+ }
+ ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
+
+ ShortcutService.writeTagExtra(out, TAG_CHOOSER_EXTRAS, si.getChooserExtras());
+
+ final IntentFilter[] intentFilters = si.getChooserIntentFilters();
+ if (intentFilters != null) {
+ for (int i = 0; i < intentFilters.length; i++) {
+ out.startTag(null, TAG_CHOOSER_INTENT_FILTERS);
+ intentFilters[i].writeToXml(out);
+ out.endTag(null, TAG_CHOOSER_INTENT_FILTERS);
+ }
}
- ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
+ final ComponentName[] componentNames = si.getChooserComponentNames();
+ if (componentNames != null) {
+ for (int i = 0; i < componentNames.length; i++) {
+ out.startTag(null, TAG_CHOOSER_COMPONENT_NAMES);
+ ShortcutService.writeAttr(out, ATTR_COMPONENT_NAMES, componentNames[i]);
+ out.endTag(null, TAG_CHOOSER_COMPONENT_NAMES);
+ }
+ }
out.endTag(null, TAG_SHORTCUT);
}
@@ -1398,6 +1437,9 @@
String iconResName;
String bitmapPath;
ArraySet<String> categories = null;
+ PersistableBundle chooserExtras;
+ List<IntentFilter> chooserIntentFilters = new ArrayList<>();
+ List<ComponentName> chooserComponentNames = new ArrayList<>();
id = ShortcutService.parseStringAttribute(parser, ATTR_ID);
activityComponent = ShortcutService.parseComponentNameAttribute(parser,
@@ -1458,6 +1500,18 @@
}
}
continue;
+ case TAG_CHOOSER_EXTRAS:
+ chooserExtras = PersistableBundle.restoreFromXml(parser);
+ continue;
+ case TAG_CHOOSER_COMPONENT_NAMES:
+ chooserComponentNames.add(ShortcutService.parseComponentNameAttribute(parser,
+ ATTR_ACTIVITY));
+ continue;
+ case TAG_CHOOSER_INTENT_FILTERS:
+ IntentFilter toAdd = new IntentFilter();
+ toAdd.readFromXml(parser);
+ chooserIntentFilters.add(toAdd);
+ continue;
}
throw ShortcutService.throwForInvalidTag(depth, tag);
}
@@ -1551,10 +1605,10 @@
// Verify each shortcut's status.
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
- if (!(si.isDeclaredInManifest() || si.isDynamic() || si.isPinned())) {
+ if (!(si.isDeclaredInManifest() || si.isDynamicOrChooser() || si.isPinned())) {
failed = true;
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
- + " is not manifest, dynamic or pinned.");
+ + " is not manifest, dynamic, chooser or pinned.");
}
if (si.isDeclaredInManifest() && si.isDynamic()) {
failed = true;
@@ -1596,6 +1650,11 @@
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ " has a dummy target activity");
}
+ if (si.getIntent() == null && !si.isChooser()) {
+ failed = true;
+ Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ + " has a null intent, but is not a chooser");
+ }
}
if (failed) {
diff --git a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
index 6eac5e3..b0689b8 100644
--- a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
+++ b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
@@ -48,7 +48,7 @@
/**
* Internal for {@link android.content.pm.LauncherApps.PinItemRequest} which receives callbacks.
*/
- private static class PinItemRequestInner extends IPinItemRequest.Stub {
+ private abstract static class PinItemRequestInner extends IPinItemRequest.Stub {
protected final ShortcutRequestPinProcessor mProcessor;
private final IntentSender mResultIntent;
private final int mLauncherUid;
@@ -63,6 +63,14 @@
mLauncherUid = launcherUid;
}
+ public ShortcutInfo getShortcutInfo() {
+ return null;
+ }
+
+ public AppWidgetProviderInfo getAppWidgetProviderInfo() {
+ return null;
+ }
+
/**
* Returns true if the caller is same as the default launcher app when this request
* object was created.
@@ -126,6 +134,26 @@
/**
* Internal for {@link android.content.pm.LauncherApps.PinItemRequest} which receives callbacks.
*/
+ private static class PinAppWidgetRequestInner extends PinItemRequestInner {
+ final AppWidgetProviderInfo mAppWidgetProviderInfo;
+
+ private PinAppWidgetRequestInner(ShortcutRequestPinProcessor processor,
+ IntentSender resultIntent, int launcherUid,
+ AppWidgetProviderInfo appWidgetProviderInfo) {
+ super(processor, resultIntent, launcherUid);
+
+ mAppWidgetProviderInfo = appWidgetProviderInfo;
+ }
+
+ @Override
+ public AppWidgetProviderInfo getAppWidgetProviderInfo() {
+ return mAppWidgetProviderInfo;
+ }
+ }
+
+ /**
+ * Internal for {@link android.content.pm.LauncherApps.PinItemRequest} which receives callbacks.
+ */
private static class PinShortcutRequestInner extends PinItemRequestInner {
/** Original shortcut passed by the app. */
public final ShortcutInfo shortcutOriginal;
@@ -153,6 +181,11 @@
}
@Override
+ public ShortcutInfo getShortcutInfo() {
+ return shortcutForLauncher;
+ }
+
+ @Override
protected boolean tryAccept() {
if (DEBUG) {
Slog.d(TAG, "Launcher accepted shortcut. ID=" + shortcutOriginal.getId()
@@ -208,8 +241,9 @@
} else {
int launcherUid = mService.injectGetPackageUid(
confirmActivity.first.getPackageName(), launcherUserId);
- request = new PinItemRequest(inAppWidget,
- new PinItemRequestInner(this, resultIntent, launcherUid));
+ request = new PinItemRequest(
+ new PinAppWidgetRequestInner(this, resultIntent, launcherUid, inAppWidget),
+ PinItemRequest.REQUEST_TYPE_APPWIDGET);
}
return startRequestConfirmActivity(confirmActivity.first, launcherUserId, request,
requestType);
@@ -319,7 +353,7 @@
mService.injectGetPackageUid(launcherPackage, launcherUserId),
existsAlready);
- return new PinItemRequest(shortcutForLauncher, inner);
+ return new PinItemRequest(inner, PinItemRequest.REQUEST_TYPE_SHORTCUT);
}
private void validateExistingShortcut(ShortcutInfo shortcutInfo) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 057e781..74eb340 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -27,6 +27,7 @@
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -64,6 +65,7 @@
import android.os.Handler;
import android.os.LocaleList;
import android.os.Looper;
+import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.Process;
@@ -1750,6 +1752,7 @@
ps.clearAllImplicitRanks();
assignImplicitRanks(newShortcuts);
+ // TODO: Consider removing Chooser fields. If so, the FLAG_CHOOSER should be removed
for (int i = 0; i < size; i++) {
final ShortcutInfo source = newShortcuts.get(i);
fixUpIncomingShortcutInfo(source, /* forUpdate= */ true);
@@ -1789,6 +1792,13 @@
if (replacingIcon || source.hasStringResources()) {
fixUpShortcutResourceNamesAndValues(target);
}
+
+ // While updating, we keep the dynamic flag as it previously was, but refresh the
+ // chooser flag.
+ // TODO: If we support clearing Chooser fields, we should also remove the flag.
+ if (target.getChooserIntentFilters() != null) {
+ target.addFlags(ShortcutInfo.FLAG_CHOOSER);
+ }
}
// Lastly, adjust the ranks.
@@ -1852,6 +1862,7 @@
return true;
}
+ // TODO: Ensure non-launchable shortcuts can not be pinned
@Override
public boolean requestPinShortcut(String packageName, ShortcutInfo shortcut,
IntentSender resultIntent, int userId) {
@@ -2007,7 +2018,7 @@
return getShortcutsWithQueryLocked(
packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
- ShortcutInfo::isDynamic);
+ ShortcutInfo::isDynamicOrChooser);
}
}
@@ -2200,6 +2211,14 @@
synchronized (mLock) {
throwIfUserLockedL(userId);
+ // For the chooser, we just check is the system is calling.
+ // STOPSHIP: We need to implement a new permission here rather than this terrible check.
+ // The packageName check is to try to distinguish between when an actual
+ // launcher is making the call, and when it's the system.
+ if (isCallerSystem() && packageName.equals("android")) {
+ return true;
+ }
+
final ShortcutUser user = getUserShortcutsLocked(userId);
// Always trust the cached component.
@@ -2372,7 +2391,7 @@
public List<ShortcutInfo> getShortcuts(int launcherUserId,
@NonNull String callingPackage, long changedSince,
@Nullable String packageName, @Nullable List<String> shortcutIds,
- @Nullable ComponentName componentName,
+ @Nullable ComponentName componentName, @Nullable Intent intent,
int queryFlags, int userId) {
final ArrayList<ShortcutInfo> ret = new ArrayList<>();
@@ -2394,13 +2413,13 @@
if (packageName != null) {
getShortcutsInnerLocked(launcherUserId,
callingPackage, packageName, shortcutIds, changedSince,
- componentName, queryFlags, userId, ret, cloneFlag);
+ componentName, intent, queryFlags, userId, ret, cloneFlag);
} else {
final List<String> shortcutIdsF = shortcutIds;
getUserShortcutsLocked(userId).forAllPackages(p -> {
getShortcutsInnerLocked(launcherUserId,
callingPackage, p.getPackageName(), shortcutIdsF, changedSince,
- componentName, queryFlags, userId, ret, cloneFlag);
+ componentName, intent, queryFlags, userId, ret, cloneFlag);
});
}
}
@@ -2409,7 +2428,7 @@
private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage,
@Nullable String packageName, @Nullable List<String> shortcutIds, long changedSince,
- @Nullable ComponentName componentName, int queryFlags,
+ @Nullable ComponentName componentName, Intent intent, int queryFlags,
int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) {
final ArraySet<String> ids = shortcutIds == null ? null
: new ArraySet<>(shortcutIds);
@@ -2434,6 +2453,15 @@
return false;
}
}
+ if (intent != null
+ && !si.hasMatchingFilter(mContext.getContentResolver(), intent)) {
+ return false;
+ }
+
+ if (((queryFlags & ShortcutQuery.FLAG_MATCH_CHOOSER) != 0)
+ && si.isChooser()) {
+ return true;
+ }
if (((queryFlags & ShortcutQuery.FLAG_GET_DYNAMIC) != 0)
&& si.isDynamic()) {
return true;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index b76a249..d3931fb 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -51,21 +51,23 @@
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
-import android.provider.Settings.Secure;
import android.provider.Settings.SettingNotFoundException;
import android.service.dreams.DreamManagerInternal;
+import android.service.power.PowerServiceDumpProto;
+import android.service.power.PowerServiceSettingsAndConfigurationDumpProto;
+import android.service.power.SuspendBlockerProto;
+import android.service.power.WakeLockProto;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
import android.util.EventLog;
import android.util.KeyValueListParser;
-import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import android.view.Display;
import android.view.WindowManagerPolicy;
-
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BackgroundThread;
@@ -78,7 +80,7 @@
import com.android.server.am.BatteryStatsService;
import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
-import com.android.server.vr.VrManagerService;
+
import libcore.util.Objects;
import java.io.FileDescriptor;
@@ -575,6 +577,13 @@
pw.print(" "); pw.print(KEY_NO_CACHED_WAKE_LOCKS); pw.print("=");
pw.println(NO_CACHED_WAKE_LOCKS);
}
+
+ void dumpProto(ProtoOutputStream proto) {
+ final long constantsToken = proto.start(PowerServiceDumpProto.CONSTANTS);
+ proto.write(PowerServiceDumpProto.ConstantsProto.IS_NO_CACHED_WAKE_LOCKS,
+ NO_CACHED_WAKE_LOCKS);
+ proto.end(constantsToken);
+ }
}
final Constants mConstants;
@@ -3244,6 +3253,354 @@
}
}
+ private void dumpProto(FileDescriptor fd) {
+ final WirelessChargerDetector wcd;
+ final ProtoOutputStream proto = new ProtoOutputStream(fd);
+
+ synchronized (mLock) {
+ mConstants.dumpProto(proto);
+ proto.write(PowerServiceDumpProto.DIRTY, mDirty);
+ proto.write(PowerServiceDumpProto.WAKEFULNESS, mWakefulness);
+ proto.write(PowerServiceDumpProto.IS_WAKEFULNESS_CHANGING, mWakefulnessChanging);
+ proto.write(PowerServiceDumpProto.IS_POWERED, mIsPowered);
+ proto.write(PowerServiceDumpProto.PLUG_TYPE, mPlugType);
+ proto.write(PowerServiceDumpProto.BATTERY_LEVEL, mBatteryLevel);
+ proto.write(
+ PowerServiceDumpProto.BATTERY_LEVEL_WHEN_DREAM_STARTED,
+ mBatteryLevelWhenDreamStarted);
+ proto.write(PowerServiceDumpProto.DOCK_STATE, mDockState);
+ proto.write(PowerServiceDumpProto.IS_STAY_ON, mStayOn);
+ proto.write(PowerServiceDumpProto.IS_PROXIMITY_POSITIVE, mProximityPositive);
+ proto.write(PowerServiceDumpProto.IS_BOOT_COMPLETED, mBootCompleted);
+ proto.write(PowerServiceDumpProto.IS_SYSTEM_READY, mSystemReady);
+ proto.write(
+ PowerServiceDumpProto.IS_HAL_AUTO_SUSPEND_MODE_ENABLED,
+ mHalAutoSuspendModeEnabled);
+ proto.write(
+ PowerServiceDumpProto.IS_HAL_AUTO_INTERACTIVE_MODE_ENABLED,
+ mHalInteractiveModeEnabled);
+
+ final long activeWakeLocksToken = proto.start(PowerServiceDumpProto.ACTIVE_WAKE_LOCKS);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_CPU,
+ (mWakeLockSummary & WAKE_LOCK_CPU) != 0);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_SCREEN_BRIGHT,
+ (mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_SCREEN_DIM,
+ (mWakeLockSummary & WAKE_LOCK_SCREEN_DIM) != 0);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_BUTTON_BRIGHT,
+ (mWakeLockSummary & WAKE_LOCK_BUTTON_BRIGHT) != 0);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_PROXIMITY_SCREEN_OFF,
+ (mWakeLockSummary & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_STAY_AWAKE,
+ (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_DOZE,
+ (mWakeLockSummary & WAKE_LOCK_DOZE) != 0);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_DRAW,
+ (mWakeLockSummary & WAKE_LOCK_DRAW) != 0);
+ proto.end(activeWakeLocksToken);
+
+ proto.write(PowerServiceDumpProto.NOTIFY_LONG_SCHEDULED_MS, mNotifyLongScheduled);
+ proto.write(PowerServiceDumpProto.NOTIFY_LONG_DISPATCHED_MS, mNotifyLongDispatched);
+ proto.write(PowerServiceDumpProto.NOTIFY_LONG_NEXT_CHECK_MS, mNotifyLongNextCheck);
+
+ final long userActivityToken = proto.start(PowerServiceDumpProto.USER_ACTIVITY);
+ proto.write(
+ PowerServiceDumpProto.UserActivityProto.IS_SCREEN_BRIGHT,
+ (mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0);
+ proto.write(
+ PowerServiceDumpProto.UserActivityProto.IS_SCREEN_DIM,
+ (mUserActivitySummary & USER_ACTIVITY_SCREEN_DIM) != 0);
+ proto.write(
+ PowerServiceDumpProto.UserActivityProto.IS_SCREEN_DREAM,
+ (mUserActivitySummary & USER_ACTIVITY_SCREEN_DREAM) != 0);
+ proto.end(userActivityToken);
+
+ proto.write(
+ PowerServiceDumpProto.IS_REQUEST_WAIT_FOR_NEGATIVE_PROXIMITY,
+ mRequestWaitForNegativeProximity);
+ proto.write(PowerServiceDumpProto.IS_SANDMAN_SCHEDULED, mSandmanScheduled);
+ proto.write(PowerServiceDumpProto.IS_SANDMAN_SUMMONED, mSandmanSummoned);
+ proto.write(PowerServiceDumpProto.IS_LOW_POWER_MODE_ENABLED, mLowPowerModeEnabled);
+ proto.write(PowerServiceDumpProto.IS_BATTERY_LEVEL_LOW, mBatteryLevelLow);
+ proto.write(PowerServiceDumpProto.IS_LIGHT_DEVICE_IDLE_MODE, mLightDeviceIdleMode);
+ proto.write(PowerServiceDumpProto.IS_DEVICE_IDLE_MODE, mDeviceIdleMode);
+
+ for (int id : mDeviceIdleWhitelist) {
+ proto.write(PowerServiceDumpProto.DEVICE_IDLE_WHITELIST, id);
+ }
+ for (int id : mDeviceIdleTempWhitelist) {
+ proto.write(PowerServiceDumpProto.DEVICE_IDLE_TEMP_WHITELIST, id);
+ }
+
+ proto.write(PowerServiceDumpProto.LAST_WAKE_TIME_MS, mLastWakeTime);
+ proto.write(PowerServiceDumpProto.LAST_SLEEP_TIME_MS, mLastSleepTime);
+ proto.write(PowerServiceDumpProto.LAST_USER_ACTIVITY_TIME_MS, mLastUserActivityTime);
+ proto.write(
+ PowerServiceDumpProto.LAST_USER_ACTIVITY_TIME_NO_CHANGE_LIGHTS_MS,
+ mLastUserActivityTimeNoChangeLights);
+ proto.write(
+ PowerServiceDumpProto.LAST_INTERACTIVE_POWER_HINT_TIME_MS,
+ mLastInteractivePowerHintTime);
+ proto.write(
+ PowerServiceDumpProto.LAST_SCREEN_BRIGHTNESS_BOOST_TIME_MS,
+ mLastScreenBrightnessBoostTime);
+ proto.write(
+ PowerServiceDumpProto.IS_SCREEN_BRIGHTNESS_BOOST_IN_PROGRESS,
+ mScreenBrightnessBoostInProgress);
+ proto.write(PowerServiceDumpProto.IS_DISPLAY_READY, mDisplayReady);
+ proto.write(
+ PowerServiceDumpProto.IS_HOLDING_WAKE_LOCK_SUSPEND_BLOCKER,
+ mHoldingWakeLockSuspendBlocker);
+ proto.write(
+ PowerServiceDumpProto.IS_HOLDING_DISPLAY_SUSPEND_BLOCKER,
+ mHoldingDisplaySuspendBlocker);
+
+ final long settingsAndConfigurationToken =
+ proto.start(PowerServiceDumpProto.SETTINGS_AND_CONFIGURATION);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .IS_DECOUPLE_HAL_AUTO_SUSPEND_MODE_FROM_DISPLAY_CONFIG,
+ mDecoupleHalAutoSuspendModeFromDisplayConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .IS_DECOUPLE_HAL_INTERACTIVE_MODE_FROM_DISPLAY_CONFIG,
+ mDecoupleHalInteractiveModeFromDisplayConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .IS_WAKE_UP_WHEN_PLUGGED_OR_UNPLUGGED_CONFIG,
+ mWakeUpWhenPluggedOrUnpluggedConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .IS_WAKE_UP_WHEN_PLUGGED_OR_UNPLUGGED_IN_THEATER_MODE_CONFIG,
+ mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.IS_THEATER_MODE_ENABLED,
+ mTheaterModeEnabled);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .IS_SUSPEND_WHEN_SCREEN_OFF_DUE_TO_PROXIMITY_CONFIG,
+ mSuspendWhenScreenOffDueToProximityConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.ARE_DREAMS_SUPPORTED_CONFIG,
+ mDreamsSupportedConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .ARE_DREAMS_ENABLED_BY_DEFAULT_CONFIG,
+ mDreamsEnabledByDefaultConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .ARE_DREAMS_ACTIVATED_ON_SLEEP_BY_DEFAULT_CONFIG,
+ mDreamsActivatedOnSleepByDefaultConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .ARE_DREAMS_ACTIVATED_ON_DOCK_BY_DEFAULT_CONFIG,
+ mDreamsActivatedOnDockByDefaultConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .ARE_DREAMS_ENABLED_ON_BATTERY_CONFIG,
+ mDreamsEnabledOnBatteryConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .DREAMS_BATTERY_LEVEL_MINIMUM_WHEN_POWERED_CONFIG,
+ mDreamsBatteryLevelMinimumWhenPoweredConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .DREAMS_BATTERY_LEVEL_MINIMUM_WHEN_NOT_POWERED_CONFIG,
+ mDreamsBatteryLevelMinimumWhenNotPoweredConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .DREAMS_BATTERY_LEVEL_DRAIN_CUTOFF_CONFIG,
+ mDreamsBatteryLevelDrainCutoffConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.ARE_DREAMS_ENABLED_SETTING,
+ mDreamsEnabledSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .ARE_DREAMS_ACTIVATE_ON_SLEEP_SETTING,
+ mDreamsActivateOnSleepSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .ARE_DREAMS_ACTIVATE_ON_DOCK_SETTING,
+ mDreamsActivateOnDockSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.IS_DOZE_AFTER_SCREEN_OFF_CONFIG,
+ mDozeAfterScreenOffConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.IS_LOW_POWER_MODE_SETTING,
+ mLowPowerModeSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.IS_AUTO_LOW_POWER_MODE_CONFIGURED,
+ mAutoLowPowerModeConfigured);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.IS_AUTO_LOW_POWER_MODE_SNOOZING,
+ mAutoLowPowerModeSnoozing);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .MINIMUM_SCREEN_OFF_TIMEOUT_CONFIG_MS,
+ mMinimumScreenOffTimeoutConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .MAXIMUM_SCREEN_DIM_DURATION_CONFIG_MS,
+ mMaximumScreenDimDurationConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.MAXIMUM_SCREEN_DIM_RATIO_CONFIG,
+ mMaximumScreenDimRatioConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.SCREEN_OFF_TIMEOUT_SETTING_MS,
+ mScreenOffTimeoutSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.SLEEP_TIMEOUT_SETTING_MS,
+ mSleepTimeoutSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .MAXIMUM_SCREEN_OFF_TIMEOUT_FROM_DEVICE_ADMIN_MS,
+ mMaximumScreenOffTimeoutFromDeviceAdmin);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .IS_MAXIMUM_SCREEN_OFF_TIMEOUT_FROM_DEVICE_ADMIN_ENFORCED_LOCKED,
+ isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked());
+
+ final long stayOnWhilePluggedInToken =
+ proto.start(
+ PowerServiceSettingsAndConfigurationDumpProto.STAY_ON_WHILE_PLUGGED_IN);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.StayOnWhilePluggedInProto
+ .IS_STAY_ON_WHILE_PLUGGED_IN_AC,
+ ((mStayOnWhilePluggedInSetting & BatteryManager.BATTERY_PLUGGED_AC) != 0));
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.StayOnWhilePluggedInProto
+ .IS_STAY_ON_WHILE_PLUGGED_IN_USB,
+ ((mStayOnWhilePluggedInSetting & BatteryManager.BATTERY_PLUGGED_USB) != 0));
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.StayOnWhilePluggedInProto
+ .IS_STAY_ON_WHILE_PLUGGED_IN_WIRELESS,
+ ((mStayOnWhilePluggedInSetting & BatteryManager.BATTERY_PLUGGED_WIRELESS)
+ != 0));
+ proto.end(stayOnWhilePluggedInToken);
+
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.SCREEN_BRIGHTNESS_SETTING,
+ mScreenBrightnessSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_SETTING,
+ mScreenAutoBrightnessAdjustmentSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.SCREEN_BRIGHTNESS_MODE_SETTING,
+ mScreenBrightnessModeSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .SCREEN_BRIGHTNESS_OVERRIDE_FROM_WINDOW_MANAGER,
+ mScreenBrightnessOverrideFromWindowManager);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .USER_ACTIVITY_TIMEOUT_OVERRIDE_FROM_WINDOW_MANAGER_MS,
+ mUserActivityTimeoutOverrideFromWindowManager);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .IS_USER_INACTIVE_OVERRIDE_FROM_WINDOW_MANAGER,
+ mUserInactiveOverrideFromWindowManager);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .TEMPORARY_SCREEN_BRIGHTNESS_SETTING_OVERRIDE,
+ mTemporaryScreenBrightnessSettingOverride);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .TEMPORARY_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_SETTING_OVERRIDE,
+ mTemporaryScreenAutoBrightnessAdjustmentSettingOverride);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .DOZE_SCREEN_STATE_OVERRIDE_FROM_DREAM_MANAGER,
+ mDozeScreenStateOverrideFromDreamManager);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .DOZED_SCREEN_BRIGHTNESS_OVERRIDE_FROM_DREAM_MANAGER,
+ mDozeScreenBrightnessOverrideFromDreamManager);
+
+ final long screenBrightnessSettingLimitsToken =
+ proto.start(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .SCREEN_BRIGHTNESS_SETTING_LIMITS);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
+ .SETTING_MINIMUM,
+ mScreenBrightnessSettingMinimum);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
+ .SETTING_MAXIMUM,
+ mScreenBrightnessSettingMaximum);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
+ .SETTING_DEFAULT,
+ mScreenBrightnessSettingDefault);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
+ .SETTING_FOR_VR_DEFAULT,
+ mScreenBrightnessForVrSettingDefault);
+ proto.end(screenBrightnessSettingLimitsToken);
+
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.SCREEN_BRIGHTNESS_FOR_VR_SETTING,
+ mScreenBrightnessForVrSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.IS_DOUBLE_TAP_WAKE_ENABLED,
+ mDoubleTapWakeEnabled);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.IS_VR_MODE_ENABLED,
+ mIsVrModeEnabled);
+ proto.end(settingsAndConfigurationToken);
+
+ final int sleepTimeout = getSleepTimeoutLocked();
+ final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
+ final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
+ proto.write(PowerServiceDumpProto.SLEEP_TIMEOUT_MS, sleepTimeout);
+ proto.write(PowerServiceDumpProto.SCREEN_OFF_TIMEOUT_MS, screenOffTimeout);
+ proto.write(PowerServiceDumpProto.SCREEN_DIM_DURATION_MS, screenDimDuration);
+ proto.write(PowerServiceDumpProto.ARE_UIDS_CHANGING, mUidsChanging);
+ proto.write(PowerServiceDumpProto.ARE_UIDS_CHANGED, mUidsChanged);
+
+ for (int i = 0; i < mUidState.size(); i++) {
+ final UidState state = mUidState.valueAt(i);
+ final long uIDToken = proto.start(PowerServiceDumpProto.UIDS);
+ final int uid = mUidState.keyAt(i);
+ proto.write(PowerServiceDumpProto.UidProto.UID, uid);
+ proto.write(PowerServiceDumpProto.UidProto.UID_STRING, UserHandle.formatUid(uid));
+ proto.write(PowerServiceDumpProto.UidProto.IS_ACTIVE, state.mActive);
+ proto.write(PowerServiceDumpProto.UidProto.NUM_WAKE_LOCKS, state.mNumWakeLocks);
+ if (state.mProcState == ActivityManager.PROCESS_STATE_UNKNOWN) {
+ proto.write(PowerServiceDumpProto.UidProto.IS_PROCESS_STATE_UNKNOWN, true);
+ } else {
+ proto.write(PowerServiceDumpProto.UidProto.PROCESS_STATE, state.mProcState);
+ }
+ proto.end(uIDToken);
+ }
+
+ mHandler.getLooper().writeToProto(proto, PowerServiceDumpProto.LOOPER);
+
+ for (WakeLock wl : mWakeLocks) {
+ wl.writeToProto(proto, PowerServiceDumpProto.WAKE_LOCKS);
+ }
+
+ for (SuspendBlocker sb : mSuspendBlockers) {
+ sb.writeToProto(proto, PowerServiceDumpProto.SUSPEND_BLOCKERS);
+ }
+ wcd = mWirelessChargerDetector;
+ }
+
+ if (wcd != null) {
+ wcd.writeToProto(proto, PowerServiceDumpProto.WIRELESS_CHARGER_DETECTOR);
+ }
+ proto.flush();
+ }
+
private SuspendBlocker createSuspendBlockerLocked(String name) {
SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name);
mSuspendBlockers.add(suspendBlocker);
@@ -3471,6 +3828,32 @@
return sb.toString();
}
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long wakeLockToken = proto.start(fieldId);
+ proto.write(WakeLockProto.LOCK_LEVEL, (mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK));
+ proto.write(WakeLockProto.TAG, mTag);
+
+ final long wakeLockFlagsToken = proto.start(WakeLockProto.FLAGS);
+ proto.write(WakeLockProto.WakeLockFlagsProto.IS_ACQUIRE_CAUSES_WAKEUP,
+ (mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP)!=0);
+ proto.write(WakeLockProto.WakeLockFlagsProto.IS_ON_AFTER_RELEASE,
+ (mFlags & PowerManager.ON_AFTER_RELEASE)!=0);
+ proto.end(wakeLockFlagsToken);
+
+ proto.write(WakeLockProto.IS_DISABLED, mDisabled);
+ if (mNotifiedAcquired) {
+ proto.write(WakeLockProto.ACQ_MS, mAcquireTime);
+ }
+ proto.write(WakeLockProto.IS_NOTIFIED_LONG, mNotifiedLong);
+ proto.write(WakeLockProto.UID, mOwnerUid);
+ proto.write(WakeLockProto.PID, mOwnerPid);
+
+ if (mWorkSource != null) {
+ mWorkSource.writeToProto(proto, WakeLockProto.WORK_SOURCE);
+ }
+ proto.end(wakeLockToken);
+ }
+
@SuppressWarnings("deprecation")
private String getLockLevelString() {
switch (mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
@@ -3568,6 +3951,15 @@
return mName + ": ref count=" + mReferenceCount;
}
}
+
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long sbToken = proto.start(fieldId);
+ synchronized (this) {
+ proto.write(SuspendBlockerProto.NAME, mName);
+ proto.write(SuspendBlockerProto.REFERENCE_COUNT, mReferenceCount);
+ }
+ proto.end(sbToken);
+ }
}
static final class UidState {
@@ -4055,8 +4447,19 @@
}
final long ident = Binder.clearCallingIdentity();
+
+ boolean isDumpProto = false;
+ for (String arg : args) {
+ if (arg.equals("--proto")) {
+ isDumpProto = true;
+ }
+ }
try {
- dumpInternal(pw);
+ if (isDumpProto) {
+ dumpProto(fd);
+ } else {
+ dumpInternal(pw);
+ }
} finally {
Binder.restoreCallingIdentity(ident);
}
diff --git a/services/core/java/com/android/server/power/SuspendBlocker.java b/services/core/java/com/android/server/power/SuspendBlocker.java
index 70b278a..30b35f0 100644
--- a/services/core/java/com/android/server/power/SuspendBlocker.java
+++ b/services/core/java/com/android/server/power/SuspendBlocker.java
@@ -16,6 +16,8 @@
package com.android.server.power;
+import android.util.proto.ProtoOutputStream;
+
/**
* Low-level suspend blocker mechanism equivalent to holding a partial wake lock.
*
@@ -40,4 +42,6 @@
* The system may crash.
*/
void release();
+
+ void writeToProto(ProtoOutputStream proto, long fieldId);
}
diff --git a/services/core/java/com/android/server/power/WirelessChargerDetector.java b/services/core/java/com/android/server/power/WirelessChargerDetector.java
index 38f5d77..6ee9dcd 100644
--- a/services/core/java/com/android/server/power/WirelessChargerDetector.java
+++ b/services/core/java/com/android/server/power/WirelessChargerDetector.java
@@ -24,8 +24,10 @@
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
+import android.service.power.WirelessChargerDetectorProto;
import android.util.Slog;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import java.io.PrintWriter;
@@ -170,6 +172,44 @@
}
}
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long wcdToken = proto.start(fieldId);
+ synchronized (mLock) {
+ proto.write(WirelessChargerDetectorProto.IS_POWERED_WIRELESSLY, mPoweredWirelessly);
+ proto.write(WirelessChargerDetectorProto.IS_AT_REST, mAtRest);
+
+ final long restVectorToken = proto.start(WirelessChargerDetectorProto.REST);
+ proto.write(WirelessChargerDetectorProto.VectorProto.X, mRestX);
+ proto.write(WirelessChargerDetectorProto.VectorProto.Y, mRestY);
+ proto.write(WirelessChargerDetectorProto.VectorProto.Z, mRestZ);
+ proto.end(restVectorToken);
+
+ proto.write(
+ WirelessChargerDetectorProto.IS_DETECTION_IN_PROGRESS, mDetectionInProgress);
+ proto.write(WirelessChargerDetectorProto.DETECTION_START_TIME_MS, mDetectionStartTime);
+ proto.write(
+ WirelessChargerDetectorProto.IS_MUST_UPDATE_REST_POSITION,
+ mMustUpdateRestPosition);
+ proto.write(WirelessChargerDetectorProto.TOTAL_SAMPLES, mTotalSamples);
+ proto.write(WirelessChargerDetectorProto.MOVING_SAMPLES, mMovingSamples);
+
+ final long firstSampleVectorToken =
+ proto.start(WirelessChargerDetectorProto.FIRST_SAMPLE);
+ proto.write(WirelessChargerDetectorProto.VectorProto.X, mFirstSampleX);
+ proto.write(WirelessChargerDetectorProto.VectorProto.Y, mFirstSampleY);
+ proto.write(WirelessChargerDetectorProto.VectorProto.Z, mFirstSampleZ);
+ proto.end(firstSampleVectorToken);
+
+ final long lastSampleVectorToken =
+ proto.start(WirelessChargerDetectorProto.LAST_SAMPLE);
+ proto.write(WirelessChargerDetectorProto.VectorProto.X, mLastSampleX);
+ proto.write(WirelessChargerDetectorProto.VectorProto.Y, mLastSampleY);
+ proto.write(WirelessChargerDetectorProto.VectorProto.Z, mLastSampleZ);
+ proto.end(lastSampleVectorToken);
+ }
+ proto.end(wcdToken);
+ }
+
/**
* Updates the charging state and returns true if docking was detected.
*
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index d179ea7..3df4d24 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -680,10 +680,10 @@
}
}
- mCurrentVrModeComponent = calling;
if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) {
sendUpdatedCaller = true;
}
+ mCurrentVrModeComponent = calling;
if (mCurrentVrModeUser != userId) {
mCurrentVrModeUser = userId;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 2c315445..2f9868e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1588,9 +1588,24 @@
// TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
// same display. Or even when the current IME/target are not on the same screen as the next
// IME/target. For now only look for input windows on the main screen.
- mUpdateImeTarget = updateImeTarget;
- WindowState target = getWindow(mComputeImeTargetPredicate);
+ // The target candidate provided by the IME tells us which window token, but not which
+ // window within the token (e.g. child windows...). So, we use the token to look-up the
+ // best target window.
+ // TODO: Have the input method service report the right window with the token vs. just the
+ // base window of the token.
+ final WindowState baseWin = mService.getWindow(mService.mInputMethodTargetCandidate);
+ final WindowToken targetToken = baseWin != null ? baseWin.mToken : null;
+ WindowState target = targetToken != null ?
+ targetToken.getWindow(mComputeImeTargetPredicate) : null;
+ // If there isn't a better candidate in the token (maybe because they are not visible), then
+ // fall back to targeting the base window of the token, so the IME can still maintain the
+ // right z-order based on the last person that set it vs. changing its z-order to the very
+ // up since there if target is null.
+ // TODO: Consider z-ordering IME to bottom instead of top if there is no visible target.
+ // Also, consider tying the visible the visibility of the IME to the current target. I.e if
+ // target isn't visible, then IME shouldn't be visible.
+ target = target == null ? baseWin : target;
// Yet more tricksyness! If this window is a "starting" window, we do actually want
// to be on top of it, but it is not -really- where input will go. So look down below
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 5f41187..2a20a70 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -230,32 +230,37 @@
}
/**
- * @param preChangeTargetBounds The final bounds of the stack if it is currently animating
- * @return the repositioned PIP bounds given it's pre-change bounds, and the new display
- * content.
+ * Updates the display info, calculating and returning the new stack and movement bounds in the
+ * new orientation of the device if necessary.
*/
- Rect onDisplayChanged(Rect preChangeStackBounds, Rect preChangeTargetBounds,
- DisplayContent displayContent) {
- final Rect postChangeStackBounds = new Rect(preChangeTargetBounds);
- final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- if (!mDisplayInfo.equals(displayInfo)) {
- // Calculate the snap fraction of the current stack along the old movement bounds, and
- // then update the stack bounds to the same fraction along the rotated movement bounds.
- final Rect preChangeMovementBounds = getMovementBounds(preChangeStackBounds);
- final float snapFraction = mSnapAlgorithm.getSnapFraction(preChangeStackBounds,
- preChangeMovementBounds);
- mDisplayInfo.copyFrom(displayInfo);
-
- final Rect postChangeMovementBounds = getMovementBounds(preChangeStackBounds,
- false /* adjustForIme */);
- mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
- snapFraction);
- if (mIsMinimized) {
- applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
- }
- notifyMovementBoundsChanged(false /* fromImeAdjustment */);
+ void onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
+ final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
+ if (mDisplayInfo.equals(displayInfo)) {
+ return;
}
- return postChangeStackBounds;
+
+ mTmpRect.set(targetBounds);
+ final Rect postChangeStackBounds = mTmpRect;
+
+ // Calculate the snap fraction of the current stack along the old movement bounds
+ final Rect preChangeMovementBounds = getMovementBounds(postChangeStackBounds);
+ final float snapFraction = mSnapAlgorithm.getSnapFraction(postChangeStackBounds,
+ preChangeMovementBounds);
+ mDisplayInfo.copyFrom(displayInfo);
+
+ // Calculate the stack bounds in the new orientation to the same same fraction along the
+ // rotated movement bounds.
+ final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds,
+ false /* adjustForIme */);
+ mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
+ snapFraction);
+ if (mIsMinimized) {
+ applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
+ }
+
+ notifyMovementBoundsChanged(false /* fromImeAdjustment */);
+
+ outBounds.set(postChangeStackBounds);
}
/**
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 2b74f84..5041138 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -19,6 +19,7 @@
import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.ActivityManager.StackId;
import android.app.ActivityManager.TaskSnapshot;
import android.graphics.GraphicBuffer;
@@ -65,26 +66,22 @@
}
void onTransitionStarting() {
- if (!ENABLE_TASK_SNAPSHOTS) {
- return;
- }
handleClosingApps(mService.mClosingApps);
}
-
/**
* Called when the visibility of an app changes outside of the regular app transition flow.
*/
void notifyAppVisibilityChanged(AppWindowToken appWindowToken, boolean visible) {
- if (!ENABLE_TASK_SNAPSHOTS) {
- return;
- }
if (!visible) {
handleClosingApps(Sets.newArraySet(appWindowToken));
}
}
private void handleClosingApps(ArraySet<AppWindowToken> closingApps) {
+ if (!ENABLE_TASK_SNAPSHOTS || ActivityManager.isLowRamDeviceStatic()) {
+ return;
+ }
// We need to take a snapshot of the task if and only if all activities of the task are
// either closing or hidden.
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index c7532ac..34e99a6 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -262,6 +262,12 @@
if (mDisplayContent != null) {
mDisplayContent.mDimLayerController.updateDimLayer(this);
+ if (mStackId == PINNED_STACK_ID) {
+ // Update the bounds based on any changes to the display info
+ getAnimatingBounds(mTmpRect2);
+ mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(mTmpRect2,
+ bounds);
+ }
mAnimationBackgroundSurface.setBounds(bounds);
}
@@ -391,15 +397,18 @@
return false;
}
+ if (StackId.tasksAreFloating(mStackId)) {
+ // Update stack bounds again since the display info has changed since updateDisplayInfo,
+ // however, for floating tasks, we don't need to apply the new rotation to the bounds,
+ // we can just update and return them here
+ setBounds(mBounds);
+ mBoundsAfterRotation.set(mBounds);
+ return true;
+ }
+
mTmpRect2.set(mBounds);
mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
switch (mStackId) {
- case PINNED_STACK_ID:
- Rect targetBounds = new Rect();
- getAnimatingBounds(targetBounds);
- mTmpRect2 = mDisplayContent.getPinnedStackController().onDisplayChanged(mBounds,
- targetBounds, mDisplayContent);
- break;
case DOCKED_STACK_ID:
repositionDockedStackAfterRotation(mTmpRect2);
snapDockedStackAfterRotation(mTmpRect2);
@@ -651,7 +660,6 @@
mAnimationBackgroundSurface = new DimLayer(mService, this, mDisplayContent.getDisplayId(),
"animation background stackId=" + mStackId);
- final Rect oldBounds = new Rect(mBounds);
Rect bounds = null;
final TaskStack dockedStack = dc.getDockedStackIgnoringVisibility();
if (mStackId == DOCKED_STACK_ID
@@ -675,15 +683,6 @@
}
updateDisplayInfo(bounds);
-
- // Update the pinned stack controller after the display info is updated
- if (mStackId == PINNED_STACK_ID) {
- Rect targetBounds = new Rect();
- getAnimatingBounds(targetBounds);
- mDisplayContent.getPinnedStackController().onDisplayChanged(oldBounds, targetBounds,
- mDisplayContent);
- }
-
super.onDisplayChanged(dc);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 474610b..2a4dfc4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.MANAGE_APP_TOKENS;
import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
@@ -30,7 +29,6 @@
import static android.content.Intent.EXTRA_UID;
import static android.content.Intent.EXTRA_USER_HANDLE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.UserHandle.USER_NULL;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.DOCKED_INVALID;
@@ -69,8 +67,6 @@
import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END;
import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
-import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
-import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
import static com.android.server.wm.KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
@@ -112,7 +108,6 @@
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.IActivityManager;
-import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -626,9 +621,14 @@
WindowState mCurrentFocus = null;
WindowState mLastFocus = null;
- /** This just indicates the window the input method is on top of, not
- * necessarily the window its input is going to. */
+ // TODO: All the IME window tracking should be moved to DisplayContent and tracked per display.
+ // This just indicates the window the input method is on top of, not necessarily the window its
+ // input is going to.
WindowState mInputMethodTarget = null;
+ // The binder token currently using the IME as determined by the input method service.
+ // Window manager uses this to determine the final input method target
+ // (almost always this candidate) for z-ordering.
+ IBinder mInputMethodTargetCandidate = null;
/** If true hold off on modifying the animation layer of mInputMethodTarget */
boolean mInputMethodTargetWaitingAnim;
@@ -5172,7 +5172,7 @@
// Async Handler
// -------------------------------------------------------------
- final class H extends Handler {
+ final class H extends android.os.Handler {
public static final int REPORT_FOCUS_CHANGE = 2;
public static final int REPORT_LOSING_FOCUS = 3;
public static final int DO_TRAVERSAL = 4;
@@ -6951,8 +6951,9 @@
pw.print(" mLastFocus="); pw.println(mLastFocus);
}
pw.print(" mFocusedApp="); pw.println(mFocusedApp);
- if (mInputMethodTarget != null) {
- pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
+ if (mInputMethodTarget != null || mInputMethodTargetCandidate != null) {
+ pw.println(" mInputMethodTarget=" + mInputMethodTarget
+ + " mInputMethodTargetCandidate=" + getWindow(mInputMethodTargetCandidate));
}
pw.print(" mInTouchMode="); pw.print(mInTouchMode);
pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
@@ -7819,11 +7820,28 @@
@Override
public void updateInputMethodWindowStatus(@NonNull IBinder imeToken,
boolean imeWindowVisible, @Nullable IBinder targetWindowToken) {
- // TODO (b/34628091): Use this method to address the window animation issue.
- if (DEBUG_INPUT_METHOD) {
- Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken
- + " imeWindowVisible=" + imeWindowVisible
- + " targetWindowToken=" + targetWindowToken);
+ synchronized (mWindowMap) {
+ final WindowState newTargetWin = getWindow(targetWindowToken);
+ final WindowState currentTargetWin = getWindow(mInputMethodTargetCandidate);
+
+ if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken="
+ + imeToken + " imeWindowVisible=" + imeWindowVisible
+ + " targetWindowToken=" + targetWindowToken
+ + " newTargetWin=" + newTargetWin
+ + " currentTargetWin=" + currentTargetWin);
+
+ if (newTargetWin == currentTargetWin) {
+ return;
+ }
+
+ final DisplayContent dc = newTargetWin != null
+ ? newTargetWin.getDisplayContent() : currentTargetWin.getDisplayContent();
+
+ // It is possible the window for the target candidate isn't added yet, so we
+ // remember the token instead and use it to look-up the window each time we compute
+ // the ime target.
+ mInputMethodTargetCandidate = targetWindowToken;
+ dc.computeImeTarget(true /* updateImeTarget */);
}
}
@@ -7869,6 +7887,10 @@
}
}
+ WindowState getWindow(IBinder binder) {
+ return binder == null ? null : mWindowMap.get(binder);
+ }
+
void registerAppFreezeListener(AppFreezeListener listener) {
if (!mAppFreezeListeners.contains(listener)) {
mAppFreezeListeners.add(listener);
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 4c89705..20b70a6 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1036,7 +1036,7 @@
}
// TODO(b/31632518)
- gnssHal = IGnss::getService("gnss");
+ gnssHal = IGnss::getService();
if (gnssHal != nullptr) {
auto gnssXtra = gnssHal->getExtensionXtra();
if (!gnssXtra.isOk()) {
diff --git a/services/core/jni/com_android_server_vr_VrManagerService.cpp b/services/core/jni/com_android_server_vr_VrManagerService.cpp
index e06e051..9052697 100644
--- a/services/core/jni/com_android_server_vr_VrManagerService.cpp
+++ b/services/core/jni/com_android_server_vr_VrManagerService.cpp
@@ -38,7 +38,7 @@
return;
}
- gVr = IVr::getService("vr");
+ gVr = IVr::getService();
if (gVr == nullptr) {
ALOGW("%s: Could not open IVr interface", __FUNCTION__);
return;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 65a4d3a..c2abb38 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -41,6 +41,7 @@
import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
+import static android.app.admin.DevicePolicyManager.PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
@@ -332,15 +333,6 @@
}
/**
- * Keyguard features that when set on a managed profile that doesn't have its own challenge will
- * affect the profile's parent user. These can also be set on the managed profile's parent DPM
- * instance.
- */
- private static final int PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER =
- DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS
- | DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
-
- /**
* Keyguard features that when set on a profile affect the profile content or challenge only.
* These cannot be set on the managed profile's parent DPM instance
*/
@@ -4859,19 +4851,15 @@
private void sendPrivateKeyAliasResponse(final String alias, final IBinder responseBinder) {
final IKeyChainAliasCallback keyChainAliasResponse =
IKeyChainAliasCallback.Stub.asInterface(responseBinder);
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... unused) {
- try {
- keyChainAliasResponse.alias(alias);
- } catch (Exception e) {
- // Catch everything (not just RemoteException): caller could throw a
- // RuntimeException back across processes.
- Log.e(LOG_TAG, "error while responding to callback", e);
- }
- return null;
- }
- }.execute();
+ // Send the response. It's OK to do this from the main thread because IKeyChainAliasCallback
+ // is oneway, which means it won't block if the recipient lives in another process.
+ try {
+ keyChainAliasResponse.alias(alias);
+ } catch (Exception e) {
+ // Caller could throw RuntimeException or RemoteException back across processes. Catch
+ // everything just to be sure.
+ Log.e(LOG_TAG, "error while responding to callback", e);
+ }
}
/**
diff --git a/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java b/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
index b26bac3..0cf4994 100644
--- a/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
@@ -89,6 +89,7 @@
when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
NotificationChannel channel =
new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
+ when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
channel.setShowBadge(false);
NotificationRecord r = getNotificationRecord(channel);
@@ -107,6 +108,7 @@
NotificationChannel channel =
new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_HIGH);
channel.setShowBadge(true);
+ when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
NotificationRecord r = getNotificationRecord(channel);
@@ -124,6 +126,7 @@
NotificationChannel channel =
new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
channel.setShowBadge(true);
+ when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
NotificationRecord r = getNotificationRecord(channel);
@@ -141,6 +144,7 @@
NotificationChannel channel =
new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
channel.setShowBadge(false);
+ when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
NotificationRecord r = getNotificationRecord(channel);
diff --git a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
index 69724f4..c5abba8 100644
--- a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
@@ -18,6 +18,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -27,6 +28,7 @@
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.support.test.InstrumentationRegistry;
@@ -71,8 +73,11 @@
public void testSnoozeForTime() throws Exception {
NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
mSnoozeHelper.snooze(r, 1000);
+ ArgumentCaptor<Long> captor = ArgumentCaptor.forClass(Long.class);
verify(mAm, times(1)).setExactAndAllowWhileIdle(
- anyInt(), eq((long) 1000), any(PendingIntent.class));
+ anyInt(), captor.capture(), any(PendingIntent.class));
+ long actualSnoozedUntilDuration = captor.getValue() - SystemClock.elapsedRealtime();
+ assertTrue(Math.abs(actualSnoozedUntilDuration - 1000) < 2);
assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 665f01f..4141f2f 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -56,8 +56,7 @@
import android.net.INetworkScoreCache;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
-import android.net.NetworkScorerAppManager;
-import android.net.NetworkScorerAppManager.NetworkScorerAppData;
+import android.net.NetworkScorerAppData;
import android.net.RecommendationRequest;
import android.net.RecommendationResult;
import android.net.ScoredNetwork;
@@ -201,10 +200,10 @@
}
@Test
- public void testSystemRunning() {
+ public void testOnUserUnlocked() {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
- mNetworkScoreService.systemRunning();
+ mNetworkScoreService.onUserUnlocked(0);
verify(mContext).bindServiceAsUser(MockUtils.checkIntent(
new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
@@ -549,9 +548,9 @@
}
@Test
- public void testSetActiveScorer_noScoreNetworksPermission() {
- doThrow(new SecurityException()).when(mContext)
- .enforceCallingOrSelfPermission(eq(permission.SCORE_NETWORKS), anyString());
+ public void testSetActiveScorer_noRequestNetworkScoresPermission() {
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
try {
mNetworkScoreService.setActiveScorer(null);
@@ -630,7 +629,7 @@
@Test
public void testIsCallerActiveScorer_noBoundService() throws Exception {
- mNetworkScoreService.systemRunning();
+ mNetworkScoreService.onUserUnlocked(0);
assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
}
@@ -651,7 +650,7 @@
@Test
public void testGetActiveScorerPackage_notActive() throws Exception {
- mNetworkScoreService.systemRunning();
+ mNetworkScoreService.onUserUnlocked(0);
assertNull(mNetworkScoreService.getActiveScorerPackage());
}
@@ -659,7 +658,7 @@
@Test
public void testGetActiveScorerPackage_active() throws Exception {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
- mNetworkScoreService.systemRunning();
+ mNetworkScoreService.onUserUnlocked(0);
assertEquals(NEW_SCORER.getRecommendationServicePackageName(),
mNetworkScoreService.getActiveScorerPackage());
@@ -960,7 +959,7 @@
return true;
}
});
- mNetworkScoreService.systemRunning();
+ mNetworkScoreService.onUserUnlocked(0);
}
private void bindToScorer(boolean callerIsScorer) {
@@ -974,7 +973,7 @@
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
isA(UserHandle.class))).thenReturn(true);
- mNetworkScoreService.systemRunning();
+ mNetworkScoreService.onUserUnlocked(0);
}
private static class OnResultListener implements RemoteCallback.OnResultListener {
diff --git a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
similarity index 61%
rename from core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
rename to services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
index 347024d..e9a2d34 100644
--- a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
@@ -14,13 +14,22 @@
* limitations under the License
*/
-package android.net;
+package com.android.server;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.Manifest.permission;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -29,144 +38,84 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
-import android.net.NetworkScorerAppManager.NetworkScorerAppData;
+import android.net.NetworkScoreManager;
+import android.net.NetworkScorerAppData;
import android.os.Bundle;
import android.provider.Settings;
-import android.test.InstrumentationTestCase;
+import android.support.test.runner.AndroidJUnit4;
import com.android.internal.R;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
import java.util.List;
-public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
+@RunWith(AndroidJUnit4.class)
+public class NetworkScorerAppManagerTest {
@Mock private Context mMockContext;
@Mock private PackageManager mMockPm;
@Mock private Resources mResources;
- @Mock private ContentResolver mContentResolver;
- private Context mTargetContext;
+ @Mock private NetworkScorerAppManager.SettingsFacade mSettingsFacade;
private NetworkScorerAppManager mNetworkScorerAppManager;
+ private List<ResolveInfo> mAvailableServices;
- @Override
+ @Before
public void setUp() throws Exception {
- super.setUp();
-
- // Configuration needed to make mockito/dexcache work.
- mTargetContext = getInstrumentation().getTargetContext();
- System.setProperty("dexmaker.dexcache", mTargetContext.getCacheDir().getPath());
- ClassLoader newClassLoader = getInstrumentation().getClass().getClassLoader();
- Thread.currentThread().setContextClassLoader(newClassLoader);
-
MockitoAnnotations.initMocks(this);
+ mAvailableServices = new ArrayList<>();
when(mMockContext.getPackageManager()).thenReturn(mMockPm);
+ when(mMockPm.queryIntentServices(Mockito.argThat(new ArgumentMatcher<Intent>() {
+ @Override
+ public boolean matches(Object object) {
+ Intent intent = (Intent) object;
+ return NetworkScoreManager.ACTION_RECOMMEND_NETWORKS.equals(intent.getAction());
+ }
+ }), eq(PackageManager.GET_META_DATA))).thenReturn(mAvailableServices);
when(mMockContext.getResources()).thenReturn(mResources);
- when(mMockContext.getContentResolver()).thenReturn(mTargetContext.getContentResolver());
- mNetworkScorerAppManager = new NetworkScorerAppManager(mMockContext);
+
+ mNetworkScorerAppManager = new NetworkScorerAppManager(mMockContext, mSettingsFacade);
}
- public void testGetPotentialRecommendationProviderPackages_emptyConfig() throws Exception {
- setNetworkRecommendationPackageNames(/*no configured packages*/);
- assertTrue(mNetworkScorerAppManager.getPotentialRecommendationProviderPackages().isEmpty());
- }
-
- public void testGetPotentialRecommendationProviderPackages_permissionNotGranted()
- throws Exception {
- setNetworkRecommendationPackageNames("package1");
- mockScoreNetworksDenied("package1");
-
- assertTrue(mNetworkScorerAppManager.getPotentialRecommendationProviderPackages().isEmpty());
- }
-
- public void testGetPotentialRecommendationProviderPackages_permissionGranted()
- throws Exception {
- setNetworkRecommendationPackageNames("package1");
- mockScoreNetworksGranted("package1");
-
- List<String> potentialProviderPackages =
- mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
-
- assertFalse(potentialProviderPackages.isEmpty());
- assertEquals("package1", potentialProviderPackages.get(0));
- }
-
- public void testGetPotentialRecommendationProviderPackages_multipleConfigured()
- throws Exception {
- setNetworkRecommendationPackageNames("package1", "package2");
- mockScoreNetworksDenied("package1");
- mockScoreNetworksGranted("package2");
-
- List<String> potentialProviderPackages =
- mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
-
- assertEquals(1, potentialProviderPackages.size());
- assertEquals("package2", potentialProviderPackages.get(0));
- }
-
- public void testGetNetworkRecommendationProviderData_noPotentialPackages() throws Exception {
- setNetworkRecommendationPackageNames(/*no configured packages*/);
- assertNull(mNetworkScorerAppManager.getNetworkRecommendationProviderData());
- }
-
- public void testGetNetworkRecommendationProviderData_serviceMissing() throws Exception {
- setNetworkRecommendationPackageNames("package1");
- mockScoreNetworksGranted("package1");
-
- assertNull(mNetworkScorerAppManager.getNetworkRecommendationProviderData());
- }
-
- public void testGetNetworkRecommendationProviderData_scoreNetworksNotGranted()
- throws Exception {
- final ComponentName recoComponent = new ComponentName("package1", "class1");
- setNetworkRecommendationPackageNames(recoComponent.getPackageName());
- mockScoreNetworksDenied(recoComponent.getPackageName());
- mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
-
- assertNull(mNetworkScorerAppManager.getNetworkRecommendationProviderData());
- }
-
- public void testGetNetworkRecommendationProviderData_available() throws Exception {
- final ComponentName recoComponent = new ComponentName("package1", "class1");
- setNetworkRecommendationPackageNames(recoComponent.getPackageName());
- mockScoreNetworksGranted(recoComponent.getPackageName());
- mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
-
- NetworkScorerAppData appData =
- mNetworkScorerAppManager.getNetworkRecommendationProviderData();
- assertNotNull(appData);
- assertEquals(recoComponent, appData.getRecommendationServiceComponent());
- assertEquals(924, appData.packageUid);
- }
-
+ @Test
public void testGetActiveScorer_providerAvailable() throws Exception {
final ComponentName recoComponent = new ComponentName("package1", "class1");
- setNetworkRecommendationPackageNames(recoComponent.getPackageName());
+ setNetworkRecoPackageSetting(recoComponent.getPackageName());
mockScoreNetworksGranted(recoComponent.getPackageName());
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
- ContentResolver cr = mTargetContext.getContentResolver();
- Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
-
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
assertNotNull(activeScorer);
assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
assertEquals(924, activeScorer.packageUid);
}
+ @Test
+ public void testGetActiveScorer_permissionMissing() throws Exception {
+ final ComponentName recoComponent = new ComponentName("package1", "class1");
+ setNetworkRecoPackageSetting(recoComponent.getPackageName());
+ mockScoreNetworksDenied(recoComponent.getPackageName());
+ mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
+
+ final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
+ assertNull(activeScorer);
+ }
+
+ @Test
public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityNotSet()
throws Exception {
final ComponentName recoComponent = new ComponentName("package1", "class1");
- setNetworkRecommendationPackageNames(recoComponent.getPackageName());
+ setNetworkRecoPackageSetting(recoComponent.getPackageName());
mockScoreNetworksGranted(recoComponent.getPackageName());
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
null /* enableUseOpenWifiPackageActivityPackage*/);
- ContentResolver cr = mTargetContext.getContentResolver();
- Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
-
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
assertNotNull(activeScorer);
assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
@@ -174,17 +123,15 @@
assertNull(activeScorer.getEnableUseOpenWifiActivity());
}
+ @Test
public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityNotResolved()
throws Exception {
final ComponentName recoComponent = new ComponentName("package1", "class1");
- setNetworkRecommendationPackageNames(recoComponent.getPackageName());
+ setNetworkRecoPackageSetting(recoComponent.getPackageName());
mockScoreNetworksGranted(recoComponent.getPackageName());
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
"package2" /* enableUseOpenWifiPackageActivityPackage*/);
- ContentResolver cr = mTargetContext.getContentResolver();
- Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
-
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
assertNotNull(activeScorer);
assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
@@ -192,19 +139,17 @@
assertNull(activeScorer.getEnableUseOpenWifiActivity());
}
+ @Test
public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityResolved()
throws Exception {
final ComponentName recoComponent = new ComponentName("package1", "class1");
final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
- setNetworkRecommendationPackageNames(recoComponent.getPackageName());
+ setNetworkRecoPackageSetting(recoComponent.getPackageName());
mockScoreNetworksGranted(recoComponent.getPackageName());
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
enableUseOpenWifiComponent.getPackageName());
mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
- ContentResolver cr = mTargetContext.getContentResolver();
- Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
-
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
assertNotNull(activeScorer);
assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
@@ -212,33 +157,105 @@
assertEquals(enableUseOpenWifiComponent, activeScorer.getEnableUseOpenWifiActivity());
}
- public void testGetActiveScorer_providerNotAvailable()
+ @Test
+ public void testGetActiveScorer_packageSettingIsNull()
throws Exception {
- ContentResolver cr = mTargetContext.getContentResolver();
- Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
+ // NETWORK_RECOMMENDATIONS_PACKAGE is null
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
assertNull(activeScorer);
}
- public void testGetActiveScorer_recommendationsDisabled() throws Exception {
+ @Test
+ public void testGetActiveScorer_packageSettingIsInvalid() throws Exception {
final ComponentName recoComponent = new ComponentName("package1", "class1");
- setNetworkRecommendationPackageNames(recoComponent.getPackageName());
+ setDefaultNetworkRecommendationPackage(recoComponent.getPackageName());
mockScoreNetworksGranted(recoComponent.getPackageName());
- mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
- ContentResolver cr = mTargetContext.getContentResolver();
- Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0);
+ // NETWORK_RECOMMENDATIONS_PACKAGE is set to a package that isn't a recommender.
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
assertNull(activeScorer);
}
- private void setNetworkRecommendationPackageNames(String... names) {
- if (names == null) {
- names = new String[0];
- }
- when(mResources.getStringArray(R.array.config_networkRecommendationPackageNames))
- .thenReturn(names);
+ @Test
+ public void testSetActiveScorer_noChange() throws Exception {
+ String packageName = "package";
+ setNetworkRecoPackageSetting(packageName);
+
+ assertTrue(mNetworkScorerAppManager.setActiveScorer(packageName));
+ verify(mSettingsFacade, never()).putString(any(), any(), any());
+ }
+
+ @Test
+ public void testSetActiveScorer_nullPackage() throws Exception {
+ String packageName = "package";
+ String defaultPackage = "defaultPackage";
+ setNetworkRecoPackageSetting(packageName);
+ setDefaultNetworkRecommendationPackage(defaultPackage);
+
+ assertTrue(mNetworkScorerAppManager.setActiveScorer(null));
+ verify(mSettingsFacade).putString(mMockContext,
+ Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
+ }
+
+ @Test
+ public void testSetActiveScorer_validPackage() throws Exception {
+ String packageName = "package";
+ String newPackage = "newPackage";
+ setNetworkRecoPackageSetting(packageName);
+ final ComponentName recoComponent = new ComponentName(newPackage, "class1");
+ mockScoreNetworksGranted(recoComponent.getPackageName());
+ mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
+
+ assertTrue(mNetworkScorerAppManager.setActiveScorer(newPackage));
+ verify(mSettingsFacade).putString(mMockContext,
+ Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, newPackage);
+ }
+
+ @Test
+ public void testSetActiveScorer_invalidPackage() throws Exception {
+ String packageName = "package";
+ String newPackage = "newPackage";
+ setNetworkRecoPackageSetting(packageName);
+ // newPackage doesn't resolve to a valid recommender
+
+ assertFalse(mNetworkScorerAppManager.setActiveScorer(newPackage));
+ verify(mSettingsFacade, never()).putString(any(), any(), any());
+ }
+
+
+ @Test
+ public void testRevertToDefaultIfNoActive_notActive() throws Exception {
+ String defaultPackage = "defaultPackage";
+ setDefaultNetworkRecommendationPackage(defaultPackage);
+
+ mNetworkScorerAppManager.revertToDefaultIfNoActive();
+
+ verify(mSettingsFacade).putString(mMockContext,
+ Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
+ }
+
+ @Test
+ public void testRevertToDefaultIfNoActive_active() throws Exception {
+ String packageName = "package";
+ setNetworkRecoPackageSetting(packageName);
+ final ComponentName recoComponent = new ComponentName(packageName, "class1");
+ mockScoreNetworksGranted(recoComponent.getPackageName());
+ mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
+
+ mNetworkScorerAppManager.revertToDefaultIfNoActive();
+
+ verify(mSettingsFacade, never()).putString(any(), any(), any());
+ }
+
+ private void setNetworkRecoPackageSetting(String packageName) {
+ when(mSettingsFacade.getString(mMockContext,
+ Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE)).thenReturn(packageName);
+ }
+
+ private void setDefaultNetworkRecommendationPackage(String name) {
+ when(mResources.getString(R.string.config_defaultNetworkRecommendationProviderPackage))
+ .thenReturn(name);
}
private void mockScoreNetworksGranted(String packageName) {
@@ -281,6 +298,8 @@
&& compName.getPackageName().equals(intent.getPackage());
}
}), Mockito.eq(flags))).thenReturn(serviceInfo);
+
+ mAvailableServices.add(serviceInfo);
}
private void mockEnableUseOpenWifiActivity(final ComponentName useOpenWifiComp) {
diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index f615bf3..33e1a16 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -10,7 +10,6 @@
import android.test.AndroidTestCase;
import android.test.RenamingDelegatingContext;
import android.util.Log;
-import android.util.ArraySet;
import com.android.server.job.JobStore.JobSet;
import com.android.server.job.controllers.JobStatus;
@@ -278,6 +277,8 @@
assertEquals("Invalid charging constraint.", first.isRequireCharging(),
second.isRequireCharging());
+ assertEquals("Invalid battery not low constraint.", first.isRequireBatteryNotLow(),
+ second.isRequireBatteryNotLow());
assertEquals("Invalid idle constraint.", first.isRequireDeviceIdle(),
second.isRequireDeviceIdle());
assertEquals("Invalid unmetered constraint.",
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 100338e..1b59d72 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -34,6 +34,7 @@
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
@@ -1324,20 +1325,23 @@
protected ShortcutInfo makeShortcut(String id) {
return makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
}
@Deprecated // Title was renamed to short label.
protected ShortcutInfo makeShortcutWithTitle(String id, String title) {
return makeShortcut(
id, title, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
}
protected ShortcutInfo makeShortcutWithShortLabel(String id, String shortLabel) {
return makeShortcut(
id, shortLabel, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
}
/**
@@ -1346,7 +1350,8 @@
protected ShortcutInfo makeShortcutWithTimestamp(String id, long timestamp) {
final ShortcutInfo s = makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
s.setTimestamp(timestamp);
return s;
}
@@ -1358,7 +1363,8 @@
ComponentName activity) {
final ShortcutInfo s = makeShortcut(
id, "Title-" + id, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
s.setTimestamp(timestamp);
return s;
}
@@ -1369,7 +1375,27 @@
protected ShortcutInfo makeShortcutWithIcon(String id, Icon icon) {
return makeShortcut(
id, "Title-" + id, /* activity =*/ null, icon,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ }
+
+ protected ShortcutInfo makeChooserShortcut(String id, int i, boolean includeIntent) {
+ List<IntentFilter> filters = new ArrayList<>();
+ List<ComponentName> componentNames = new ArrayList<>();
+ for(int j = 0; j < i; j++) {
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction("view");
+ filters.add(filter);
+
+ componentNames.add(new ComponentName("xxxx", "yy" + i));
+ }
+ Intent intent = null;
+ if (includeIntent) {
+ intent = makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class);
+ }
+ return makeShortcut(
+ id, "Title-" + id, /* activity =*/ null, /* icon */ null,
+ intent, /* rank =*/ 0, filters, componentNames);
}
protected ShortcutInfo makePackageShortcut(String packageName, String id) {
@@ -1378,7 +1404,8 @@
setCaller(packageName);
ShortcutInfo s = makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
setCaller(origCaller); // restore the caller
return s;
@@ -1402,39 +1429,52 @@
protected ShortcutInfo makeShortcutWithActivity(String id, ComponentName activity) {
return makeShortcut(
id, "Title-" + id, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
}
protected ShortcutInfo makeShortcutWithIntent(String id, Intent intent) {
return makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- intent, /* rank =*/ 0);
+ intent, /* rank =*/ 0, /* chooserFilters =*/ null,
+ /* chooserComponentNames =*/ null);
+
}
protected ShortcutInfo makeShortcutWithActivityAndTitle(String id, ComponentName activity,
String title) {
return makeShortcut(
id, title, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
}
protected ShortcutInfo makeShortcutWithActivityAndRank(String id, ComponentName activity,
int rank) {
return makeShortcut(
id, "Title-" + id, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank,
+ /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
}
/**
* Make a shortcut with details.
*/
protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity,
- Icon icon, Intent intent, int rank) {
+ Icon icon, Intent intent, int rank, @Nullable List<IntentFilter> chooserFilters,
+ @Nullable List<ComponentName> chooserComponentNames) {
final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id)
.setActivity(new ComponentName(mClientContext.getPackageName(), "main"))
.setShortLabel(title)
- .setRank(rank)
- .setIntent(intent);
+ .setRank(rank);
+ if (intent != null) {
+ b.setIntent(intent);
+ }
+ if (chooserFilters != null) {
+ for (int i = 0; i < chooserFilters.size(); i++) {
+ b.addChooserIntentFilter(chooserFilters.get(i), chooserComponentNames.get(i));
+ }
+ }
if (icon != null) {
b.setIcon(icon);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 28596f7..d8db331 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -413,9 +413,7 @@
assertTrue(Arrays.equals(a.sharedLibraryFiles, that.sharedLibraryFiles));
assertEquals(a.dataDir, that.dataDir);
assertEquals(a.deviceProtectedDataDir, that.deviceProtectedDataDir);
- assertEquals(a.deviceEncryptedDataDir, that.deviceEncryptedDataDir);
assertEquals(a.credentialProtectedDataDir, that.credentialProtectedDataDir);
- assertEquals(a.credentialEncryptedDataDir, that.credentialEncryptedDataDir);
assertEquals(a.nativeLibraryDir, that.nativeLibraryDir);
assertEquals(a.secondaryNativeLibraryDir, that.secondaryNativeLibraryDir);
assertEquals(a.nativeLibraryRootDir, that.nativeLibraryRootDir);
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index e4d92ba..94ff07f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -15,6 +15,7 @@
*/
package com.android.server.pm;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllChooser;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDisabled;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamic;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamicOrPinned;
@@ -256,7 +257,9 @@
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
+ /* weight */ 10,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
final ShortcutInfo si2 = makeShortcut(
"shortcut2",
@@ -264,14 +267,18 @@
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12);
+ /* weight */ 12,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
final ShortcutInfo si3 = makeShortcut(
"shortcut3",
"Title 3",
/* activity */ null,
icon3,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 13);
+ /* weight */ 13,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2, si3)));
assertShortcutIds(assertAllNotKeyFieldsOnly(
@@ -982,8 +989,10 @@
makeShortcut("s2"),
makeShortcut("s3"),
makeShortcut("s4"),
- makeShortcut("s5")
- )));
+ makeShortcut("s5"),
+ makeChooserShortcut("s6", 2, true),
+ makeChooserShortcut("s7", 2, true),
+ makeChooserShortcut("s8", 1, true))));
});
runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
@@ -991,11 +1000,13 @@
makeShortcut("s2"),
makeShortcut("s3"),
makeShortcut("s4"),
- makeShortcut("s5")
- )));
+ makeShortcut("s5"),
+ makeChooserShortcut("s6", 2, true),
+ makeChooserShortcut("s7", 2, true),
+ makeChooserShortcut("s8", 1, true))));
});
runWithCaller(LAUNCHER_1, UserHandle.USER_SYSTEM, () -> {
- mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3"),
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3", "s6"),
getCallingUser());
mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s4", "s5"),
getCallingUser());
@@ -1008,19 +1019,20 @@
mManager.removeDynamicShortcuts(list("s1"));
mManager.removeDynamicShortcuts(list("s3"));
mManager.removeDynamicShortcuts(list("s5"));
+ mManager.removeDynamicShortcuts(list("s7"));
});
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s3", "s4", "s5");
+ "s3", "s4", "s5", "s6", "s7", "s8");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
- "s2", "s3");
+ "s2", "s3", "s6");
});
runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s2", "s4");
+ "s2", "s4", "s6", "s8");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
"s4", "s5");
@@ -1057,10 +1069,10 @@
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s3", "s4", "s5");
+ "s3", "s4", "s5", "s6", "s7", "s8");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
- "s2", "s3");
+ "s2", "s3", "s6");
ShortcutInfo s = getCallerShortcut("s2");
assertTrue(s.hasIconResource());
@@ -1076,7 +1088,7 @@
runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s2", "s4");
+ "s2", "s4", "s6", "s8");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
"s4", "s5");
@@ -1173,7 +1185,46 @@
});
}
- // === Test for launcher side APIs ===
+ public void testUpdateShortcuts_chooser() {
+ runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("s1"),
+ makeChooserShortcut("s2", 2, false),
+ makeChooserShortcut("s3", 2, false)
+ )));
+
+ assertFalse(getCallerShortcut("s1").isChooser());
+ assertTrue(getCallerShortcut("s2").isChooser());
+ assertTrue(getCallerShortcut("s3").isChooser());
+
+ ShortcutInfo s = getCallerShortcut("s1");
+ assertNull(s.getChooserIntentFilters());
+ assertNull(s.getChooserComponentNames());
+
+ assertTrue(getCallerShortcut("s1").isDynamic());
+ assertFalse(getCallerShortcut("s2").isDynamic());
+ assertFalse(getCallerShortcut("s3").isDynamic());
+
+
+ // Replace 2 with a chooser shortcut
+ mManager.updateShortcuts(list(makeChooserShortcut("s1", 2, true)));
+
+ s = getCallerShortcut("s1");
+ assertEquals(2, s.getChooserIntentFilters().length);
+ assertEquals(2, s.getChooserComponentNames().length);
+
+ assertShortcutIds(assertAllChooser(
+ mManager.getDynamicShortcuts()),
+ "s1", "s2", "s3");
+
+ assertTrue(getCallerShortcut("s1").isDynamic());
+ assertFalse(getCallerShortcut("s2").isDynamic());
+ assertFalse(getCallerShortcut("s3").isDynamic());
+ });
+ }
+
+
+ // === Test for launcher side APIs ===
public void testGetShortcuts() {
@@ -1484,15 +1535,17 @@
/* icon =*/ null,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
+ /* weight */ 10, /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
final ShortcutInfo s1_2 = makeShortcut(
- "s2",
- "Title 2",
+ "s2", "Title 2",
/* activity */ null,
/* icon =*/ null,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12);
+ /* weight */ 12,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2)));
dumpsysOnLogcat();
@@ -1505,7 +1558,9 @@
/* icon =*/ null,
makeIntent(Intent.ACTION_ANSWER, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
+ /* weight */ 10,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
dumpsysOnLogcat();
@@ -2674,10 +2729,12 @@
final ShortcutInfo s1_2 = makeShortcut(
"s2",
"Title 2",
- /* activity */ null,
- /* icon =*/ null,
+ /* activity */ null,
+ /* icon =*/ null,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* rank */ 12);
+ /* rank */ 12,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
final ShortcutInfo s1_3 = makeShortcut("s3");
@@ -2692,7 +2749,9 @@
/* icon =*/ null,
makeIntent(Intent.ACTION_ANSWER, ShortcutActivity.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
+ /* weight */ 10,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
});
@@ -3110,7 +3169,9 @@
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
+ /* weight */ 10,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
final ShortcutInfo si2 = makeShortcut(
"s2",
@@ -3118,7 +3179,9 @@
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12);
+ /* weight */ 12,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
@@ -3136,8 +3199,8 @@
makeComponent(ShortcutActivity.class),
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
- "key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
+ "key1", "val1", "nest", makeBundle("key", 123)), /* weight */ 10,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
final ShortcutInfo si2 = makeShortcut(
"s2",
@@ -3145,7 +3208,8 @@
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12);
+ /* weight */ 12, /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
@@ -3167,7 +3231,8 @@
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
+ /* weight */ 10, /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
final ShortcutInfo si2 = makeShortcut(
"s2",
@@ -3175,7 +3240,8 @@
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12);
+ /* weight */ 12, /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
@@ -6800,10 +6866,12 @@
mManager.setDynamicShortcuts(list(
makeShortcut("ms1", "title1",
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
- /* icon */ null, new Intent("action1"), /* rank */ 0),
+ /* icon */ null, new Intent("action1"), /* rank */ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null),
makeShortcut("ms2", "title2",
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
- /* icon */ null, new Intent("action1"), /* rank */ 0)));
+ /* icon */ null, new Intent("action1"), /* rank */ 0, /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null)));
});
runWithCaller(LAUNCHER_1, USER_0, () -> {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 28ec4fd..c54fa02 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -34,6 +34,7 @@
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
@@ -93,11 +94,6 @@
assertExpectException(
RuntimeException.class,
- "intents cannot contain null",
- () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(null));
-
- assertExpectException(
- RuntimeException.class,
"action must be set",
() -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
@@ -142,6 +138,19 @@
"disabledMessage cannot be empty",
() -> new ShortcutInfo.Builder(getTestContext(), "id").setDisabledMessage(""));
+
+ assertExpectException(
+ RuntimeException.class,
+ "component name cannot be null",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id")
+ .addChooserIntentFilter(new IntentFilter(Intent.ACTION_SEND), null));
+
+ assertExpectException(
+ RuntimeException.class,
+ "intent filter cannot be null",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id")
+ .addChooserIntentFilter(null, new ComponentName("xxx", "s")));
+
assertExpectException(NullPointerException.class, "action must be set",
() -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
@@ -240,6 +249,10 @@
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
+ IntentFilter chooserFilter = new IntentFilter();
+ chooserFilter.addAction(Intent.ACTION_VIEW);
+ PersistableBundle pb2 = new PersistableBundle();
+ pb2.putInt("l", 1);
si = new ShortcutInfo.Builder(getTestContext())
.setId("id")
@@ -252,6 +265,8 @@
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setRank(123)
.setExtras(pb)
+ .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+ .setChooserExtras(pb2)
.build();
si.addFlags(ShortcutInfo.FLAG_PINNED);
si.setBitmapPath("abc");
@@ -282,6 +297,12 @@
assertEquals(null, si.getTextResName());
assertEquals(0, si.getDisabledMessageResourceId());
assertEquals(null, si.getDisabledMessageResName());
+
+ assertEquals(1, si.getChooserIntentFilters().length);
+ assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
+ assertEquals(1, si.getChooserComponentNames().length);
+ assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
+ assertEquals(1, si.getChooserExtras().getInt("l"));
}
public void testShortcutInfoParcel_resId() {
@@ -290,6 +311,10 @@
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
+ IntentFilter chooserFilter = new IntentFilter();
+ chooserFilter.addAction(Intent.ACTION_VIEW);
+ PersistableBundle pb2 = new PersistableBundle();
+ pb2.putInt("l", 1);
si = new ShortcutInfo.Builder(getTestContext())
.setId("id")
@@ -302,6 +327,8 @@
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setRank(123)
.setExtras(pb)
+ .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+ .setChooserExtras(pb2)
.build();
si.addFlags(ShortcutInfo.FLAG_PINNED);
si.setBitmapPath("abc");
@@ -338,6 +365,11 @@
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
+ IntentFilter chooserFilter = new IntentFilter();
+ chooserFilter.addAction(Intent.ACTION_VIEW);
+ PersistableBundle pb2 = new PersistableBundle();
+ pb2.putInt("l", 1);
+
ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setActivity(new ComponentName("a", "b"))
@@ -349,6 +381,8 @@
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
+ .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+ .setChooserExtras(pb2)
.build();
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
@@ -378,6 +412,12 @@
assertEquals(456, si.getIconResourceId());
assertEquals("string/r456", si.getIconResName());
+ assertEquals(1, si.getChooserIntentFilters().length);
+ assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
+ assertEquals(1, si.getChooserComponentNames().length);
+ assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
+ assertEquals(1, si.getChooserExtras().getInt("l"));
+
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
assertEquals(mClientContext.getPackageName(), si.getPackage());
@@ -445,6 +485,10 @@
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
+ IntentFilter chooserFilter = new IntentFilter();
+ chooserFilter.addAction(Intent.ACTION_VIEW);
+ PersistableBundle pb2 = new PersistableBundle();
+ pb2.putInt("l", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setActivity(new ComponentName("a", "b"))
@@ -456,6 +500,8 @@
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
+ .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+ .setChooserExtras(pb2)
.build();
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
@@ -488,6 +534,12 @@
assertEquals(456, si.getIconResourceId());
assertEquals("string/r456", si.getIconResName());
+ assertEquals(1, si.getChooserIntentFilters().length);
+ assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
+ assertEquals(1, si.getChooserComponentNames().length);
+ assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
+ assertEquals(1, si.getChooserExtras().getInt("l"));
+
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
assertEquals(mClientContext.getPackageName(), si.getPackage());
@@ -603,6 +655,10 @@
public void testShortcutInfoCopyNonNullFieldsFrom() throws InterruptedException {
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
+ IntentFilter chooserFilter = new IntentFilter();
+ chooserFilter.addAction(Intent.ACTION_VIEW);
+ PersistableBundle pb2 = new PersistableBundle();
+ pb2.putInt("l", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
.setId("id")
.setActivity(new ComponentName("a", "b"))
@@ -714,12 +770,12 @@
assertEquals(999, si.getRank());
- PersistableBundle pb2 = new PersistableBundle();
- pb2.putInt("x", 99);
+ PersistableBundle pb3 = new PersistableBundle();
+ pb3.putInt("x", 99);
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
- .setExtras(pb2).build());
+ .setExtras(pb3).build());
assertEquals("text", si.getText());
assertEquals(99, si.getExtras().getInt("x"));
}
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
index 0bd014c..42ddedf 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
@@ -45,12 +45,12 @@
final int userId = 0;
AppIdleHistory aih = new AppIdleHistory(mStorageDir, 0);
- aih.updateDisplayLocked(true, /* elapsedRealtime= */ 1000);
- aih.updateDisplayLocked(false, /* elapsedRealtime= */ 2000);
+ aih.updateDisplay(true, /* elapsedRealtime= */ 1000);
+ aih.updateDisplay(false, /* elapsedRealtime= */ 2000);
// Screen On time file should be written right away
assertTrue(aih.getScreenOnTimeFile().exists());
- aih.writeAppIdleTimesLocked(userId);
+ aih.writeAppIdleTimes(userId);
// stats file should be written now
assertTrue(new File(new File(mStorageDir, "users/" + userId),
AppIdleHistory.APP_IDLE_FILENAME).exists());
@@ -58,43 +58,43 @@
public void testScreenOnTime() {
AppIdleHistory aih = new AppIdleHistory(mStorageDir, 1000);
- aih.updateDisplayLocked(false, 2000);
- assertEquals(aih.getScreenOnTimeLocked(2000), 0);
- aih.updateDisplayLocked(true, 3000);
- assertEquals(aih.getScreenOnTimeLocked(4000), 1000);
- assertEquals(aih.getScreenOnTimeLocked(5000), 2000);
- aih.updateDisplayLocked(false, 6000);
+ aih.updateDisplay(false, 2000);
+ assertEquals(aih.getScreenOnTime(2000), 0);
+ aih.updateDisplay(true, 3000);
+ assertEquals(aih.getScreenOnTime(4000), 1000);
+ assertEquals(aih.getScreenOnTime(5000), 2000);
+ aih.updateDisplay(false, 6000);
// Screen on time should not keep progressing with screen is off
- assertEquals(aih.getScreenOnTimeLocked(7000), 3000);
- assertEquals(aih.getScreenOnTimeLocked(8000), 3000);
- aih.writeAppIdleDurationsLocked();
+ assertEquals(aih.getScreenOnTime(7000), 3000);
+ assertEquals(aih.getScreenOnTime(8000), 3000);
+ aih.writeAppIdleDurations();
// Check if the screen on time is persisted across instantiations
AppIdleHistory aih2 = new AppIdleHistory(mStorageDir, 0);
- assertEquals(aih2.getScreenOnTimeLocked(11000), 3000);
- aih2.updateDisplayLocked(true, 4000);
- aih2.updateDisplayLocked(false, 5000);
- assertEquals(aih2.getScreenOnTimeLocked(13000), 4000);
+ assertEquals(aih2.getScreenOnTime(11000), 3000);
+ aih2.updateDisplay(true, 4000);
+ aih2.updateDisplay(false, 5000);
+ assertEquals(aih2.getScreenOnTime(13000), 4000);
}
public void testPackageEvents() {
AppIdleHistory aih = new AppIdleHistory(mStorageDir, 1000);
aih.setThresholds(4000, 1000);
- aih.updateDisplayLocked(true, 1000);
+ aih.updateDisplay(true, 1000);
// App is not-idle by default
- assertFalse(aih.isIdleLocked(PACKAGE_1, 0, 1500));
+ assertFalse(aih.isIdle(PACKAGE_1, 0, 1500));
// Still not idle
- assertFalse(aih.isIdleLocked(PACKAGE_1, 0, 3000));
+ assertFalse(aih.isIdle(PACKAGE_1, 0, 3000));
// Idle now
- assertTrue(aih.isIdleLocked(PACKAGE_1, 0, 8000));
+ assertTrue(aih.isIdle(PACKAGE_1, 0, 8000));
// Not idle
- assertFalse(aih.isIdleLocked(PACKAGE_2, 0, 9000));
+ assertFalse(aih.isIdle(PACKAGE_2, 0, 9000));
// Screen off
- aih.updateDisplayLocked(false, 9100);
+ aih.updateDisplay(false, 9100);
// Still idle after 10 seconds because screen hasn't been on long enough
- assertFalse(aih.isIdleLocked(PACKAGE_2, 0, 20000));
- aih.updateDisplayLocked(true, 21000);
- assertTrue(aih.isIdleLocked(PACKAGE_2, 0, 23000));
+ assertFalse(aih.isIdle(PACKAGE_2, 0, 20000));
+ aih.updateDisplay(true, 21000);
+ assertTrue(aih.isIdle(PACKAGE_2, 0, 23000));
}
}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index bd3271b..73ad7c2 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -22,6 +22,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
@@ -146,6 +147,7 @@
final WindowState appWin = createWindow(null, TYPE_APPLICATION, sDisplayContent, "appWin");
appWin.setHasSurface(true);
assertTrue(appWin.canBeImeTarget());
+ sWm.mInputMethodTargetCandidate = appWin.mClient.asBinder();
WindowState imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
assertEquals(appWin, imeTarget);
@@ -156,6 +158,20 @@
assertTrue(childWin.canBeImeTarget());
imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
assertEquals(childWin, imeTarget);
+
+ final WindowState appWin2 =
+ createWindow(null, TYPE_APPLICATION, sDisplayContent, "appWin2");
+ appWin2.setHasSurface(true);
+ assertTrue(appWin2.canBeImeTarget());
+ // Verify that the IME target isn't adjusted since mInputMethodTargetCandidate didn't change
+ // to the new app.
+ imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
+ assertNotEquals(appWin2, imeTarget);
+
+ sWm.mInputMethodTargetCandidate = appWin2.mClient.asBinder();
+ // Verify app is not IME target since its token is set as a candidate.
+ imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
+ assertEquals(appWin2, imeTarget);
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 52e10a5..b9c2eed 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -69,7 +69,6 @@
class WindowTestsBase {
static WindowManagerService sWm = null;
static TestWindowManagerPolicy sPolicy = null;
- private final static IWindow sIWindow = new TestIWindow();
private final static Session sMockSession = mock(Session.class);
private static int sNextDisplayId = Display.DEFAULT_DISPLAY + 1;
static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
@@ -148,6 +147,7 @@
}
sWm.mInputMethodTarget = null;
+ sWm.mInputMethodTargetCandidate = null;
}
private static WindowState createCommonWindow(WindowState parent, int type, String name) {
@@ -237,11 +237,12 @@
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
attrs.setTitle(name);
- final WindowState w = new WindowState(sWm, sMockSession, sIWindow, token, parent, OP_NONE,
- 0, attrs, 0, 0, ownerCanAddInternalSystemWindow);
+ final WindowState w = new WindowState(sWm, sMockSession, new TestIWindow(), token, parent,
+ OP_NONE, 0, attrs, 0, 0, ownerCanAddInternalSystemWindow);
// TODO: Probably better to make this call in the WindowState ctor to avoid errors with
// adding it to the token...
token.addWindow(w);
+ sWm.mWindowMap.put(w.mClient.asBinder(), w);
return w;
}
@@ -463,8 +464,9 @@
boolean resizeReported;
TestWindowState(WindowManager.LayoutParams attrs, WindowToken token) {
- super(sWm, sMockSession, sIWindow, token, null, OP_NONE, 0, attrs, 0, 0,
+ super(sWm, sMockSession, new TestIWindow(), token, null, OP_NONE, 0, attrs, 0, 0,
false /* ownerCanAddInternalSystemWindow */);
+ sWm.mWindowMap.put(mClient.asBinder(), this);
}
@Override
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index ea45bd1..fd335c3 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -508,6 +508,13 @@
return actualShortcuts;
}
+ public static List<ShortcutInfo> assertAllChooser(List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertTrue("ID " + s.getId(), s.isChooser());
+ }
+ return actualShortcuts;
+ }
+
public static List<ShortcutInfo> assertAllPinned(List<ShortcutInfo> actualShortcuts) {
for (ShortcutInfo s : actualShortcuts) {
assertTrue("ID " + s.getId(), s.isPinned());
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index f69dae4..f298559 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -18,7 +18,6 @@
import android.os.Environment;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.Slog;
@@ -101,7 +100,7 @@
mElapsedSnapshot = elapsedRealtime;
mScreenOnSnapshot = elapsedRealtime;
mStorageDir = storageDir;
- readScreenOnTimeLocked();
+ readScreenOnTime();
}
public void setThresholds(long elapsedTimeThreshold, long screenOnTimeThreshold) {
@@ -109,7 +108,7 @@
mScreenOnTimeThreshold = screenOnTimeThreshold;
}
- public void updateDisplayLocked(boolean screenOn, long elapsedRealtime) {
+ public void updateDisplay(boolean screenOn, long elapsedRealtime) {
if (screenOn == mScreenOn) return;
mScreenOn = screenOn;
@@ -122,7 +121,7 @@
}
}
- public long getScreenOnTimeLocked(long elapsedRealtime) {
+ public long getScreenOnTime(long elapsedRealtime) {
long screenOnTime = mScreenOnDuration;
if (mScreenOn) {
screenOnTime += elapsedRealtime - mScreenOnSnapshot;
@@ -135,7 +134,7 @@
return new File(mStorageDir, "screen_on_time");
}
- private void readScreenOnTimeLocked() {
+ private void readScreenOnTime() {
File screenOnTimeFile = getScreenOnTimeFile();
if (screenOnTimeFile.exists()) {
try {
@@ -146,11 +145,11 @@
} catch (IOException | NumberFormatException e) {
}
} else {
- writeScreenOnTimeLocked();
+ writeScreenOnTime();
}
}
- private void writeScreenOnTimeLocked() {
+ private void writeScreenOnTime() {
AtomicFile screenOnTimeFile = new AtomicFile(getScreenOnTimeFile());
FileOutputStream fos = null;
try {
@@ -166,30 +165,30 @@
/**
* To be called periodically to keep track of elapsed time when app idle times are written
*/
- public void writeAppIdleDurationsLocked() {
+ public void writeAppIdleDurations() {
final long elapsedRealtime = SystemClock.elapsedRealtime();
// Only bump up and snapshot the elapsed time. Don't change screen on duration.
mElapsedDuration += elapsedRealtime - mElapsedSnapshot;
mElapsedSnapshot = elapsedRealtime;
- writeScreenOnTimeLocked();
+ writeScreenOnTime();
}
- public void reportUsageLocked(String packageName, int userId, long elapsedRealtime) {
- ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
- PackageHistory packageHistory = getPackageHistoryLocked(userHistory, packageName,
+ public void reportUsage(String packageName, int userId, long elapsedRealtime) {
+ ArrayMap<String, PackageHistory> userHistory = getUserHistory(userId);
+ PackageHistory packageHistory = getPackageHistory(userHistory, packageName,
elapsedRealtime);
shiftHistoryToNow(userHistory, elapsedRealtime);
packageHistory.lastUsedElapsedTime = mElapsedDuration
+ (elapsedRealtime - mElapsedSnapshot);
- packageHistory.lastUsedScreenTime = getScreenOnTimeLocked(elapsedRealtime);
+ packageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
packageHistory.recent[HISTORY_SIZE - 1] = FLAG_LAST_STATE | FLAG_PARTIAL_ACTIVE;
}
public void setIdle(String packageName, int userId, long elapsedRealtime) {
- ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
- PackageHistory packageHistory = getPackageHistoryLocked(userHistory, packageName,
+ ArrayMap<String, PackageHistory> userHistory = getUserHistory(userId);
+ PackageHistory packageHistory = getPackageHistory(userHistory, packageName,
elapsedRealtime);
shiftHistoryToNow(userHistory, elapsedRealtime);
@@ -222,23 +221,23 @@
mLastPeriod = thisPeriod;
}
- private ArrayMap<String, PackageHistory> getUserHistoryLocked(int userId) {
+ private ArrayMap<String, PackageHistory> getUserHistory(int userId) {
ArrayMap<String, PackageHistory> userHistory = mIdleHistory.get(userId);
if (userHistory == null) {
userHistory = new ArrayMap<>();
mIdleHistory.put(userId, userHistory);
- readAppIdleTimesLocked(userId, userHistory);
+ readAppIdleTimes(userId, userHistory);
}
return userHistory;
}
- private PackageHistory getPackageHistoryLocked(ArrayMap<String, PackageHistory> userHistory,
+ private PackageHistory getPackageHistory(ArrayMap<String, PackageHistory> userHistory,
String packageName, long elapsedRealtime) {
PackageHistory packageHistory = userHistory.get(packageName);
if (packageHistory == null) {
packageHistory = new PackageHistory();
- packageHistory.lastUsedElapsedTime = getElapsedTimeLocked(elapsedRealtime);
- packageHistory.lastUsedScreenTime = getScreenOnTimeLocked(elapsedRealtime);
+ packageHistory.lastUsedElapsedTime = getElapsedTime(elapsedRealtime);
+ packageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
userHistory.put(packageName, packageHistory);
}
return packageHistory;
@@ -248,41 +247,41 @@
mIdleHistory.remove(userId);
}
- public boolean isIdleLocked(String packageName, int userId, long elapsedRealtime) {
- ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
+ public boolean isIdle(String packageName, int userId, long elapsedRealtime) {
+ ArrayMap<String, PackageHistory> userHistory = getUserHistory(userId);
PackageHistory packageHistory =
- getPackageHistoryLocked(userHistory, packageName, elapsedRealtime);
+ getPackageHistory(userHistory, packageName, elapsedRealtime);
if (packageHistory == null) {
return false; // Default to not idle
} else {
- return hasPassedThresholdsLocked(packageHistory, elapsedRealtime);
+ return hasPassedThresholds(packageHistory, elapsedRealtime);
}
}
- private long getElapsedTimeLocked(long elapsedRealtime) {
+ private long getElapsedTime(long elapsedRealtime) {
return (elapsedRealtime - mElapsedSnapshot + mElapsedDuration);
}
- public void setIdleLocked(String packageName, int userId, boolean idle, long elapsedRealtime) {
- ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
- PackageHistory packageHistory = getPackageHistoryLocked(userHistory, packageName,
+ public void setIdle(String packageName, int userId, boolean idle, long elapsedRealtime) {
+ ArrayMap<String, PackageHistory> userHistory = getUserHistory(userId);
+ PackageHistory packageHistory = getPackageHistory(userHistory, packageName,
elapsedRealtime);
- packageHistory.lastUsedElapsedTime = getElapsedTimeLocked(elapsedRealtime)
+ packageHistory.lastUsedElapsedTime = getElapsedTime(elapsedRealtime)
- mElapsedTimeThreshold;
- packageHistory.lastUsedScreenTime = getScreenOnTimeLocked(elapsedRealtime)
+ packageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime)
- (idle ? mScreenOnTimeThreshold : 0) - 1000 /* just a second more */;
}
- public void clearUsageLocked(String packageName, int userId) {
- ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
+ public void clearUsage(String packageName, int userId) {
+ ArrayMap<String, PackageHistory> userHistory = getUserHistory(userId);
userHistory.remove(packageName);
}
- private boolean hasPassedThresholdsLocked(PackageHistory packageHistory, long elapsedRealtime) {
+ private boolean hasPassedThresholds(PackageHistory packageHistory, long elapsedRealtime) {
return (packageHistory.lastUsedScreenTime
- <= getScreenOnTimeLocked(elapsedRealtime) - mScreenOnTimeThreshold)
+ <= getScreenOnTime(elapsedRealtime) - mScreenOnTimeThreshold)
&& (packageHistory.lastUsedElapsedTime
- <= getElapsedTimeLocked(elapsedRealtime) - mElapsedTimeThreshold);
+ <= getElapsedTime(elapsedRealtime) - mElapsedTimeThreshold);
}
private File getUserFile(int userId) {
@@ -290,7 +289,7 @@
Integer.toString(userId)), APP_IDLE_FILENAME);
}
- private void readAppIdleTimesLocked(int userId, ArrayMap<String, PackageHistory> userHistory) {
+ private void readAppIdleTimes(int userId, ArrayMap<String, PackageHistory> userHistory) {
FileInputStream fis = null;
try {
AtomicFile appIdleFile = new AtomicFile(getUserFile(userId));
@@ -332,7 +331,7 @@
}
}
- public void writeAppIdleTimesLocked(int userId) {
+ public void writeAppIdleTimes(int userId) {
FileOutputStream fos = null;
AtomicFile appIdleFile = new AtomicFile(getUserFile(userId));
try {
@@ -346,7 +345,7 @@
xml.startTag(null, TAG_PACKAGES);
- ArrayMap<String,PackageHistory> userHistory = getUserHistoryLocked(userId);
+ ArrayMap<String,PackageHistory> userHistory = getUserHistory(userId);
final int N = userHistory.size();
for (int i = 0; i < N; i++) {
String packageName = userHistory.keyAt(i);
@@ -374,8 +373,8 @@
idpw.increaseIndent();
ArrayMap<String, PackageHistory> userHistory = mIdleHistory.get(userId);
final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long totalElapsedTime = getElapsedTimeLocked(elapsedRealtime);
- final long screenOnTime = getScreenOnTimeLocked(elapsedRealtime);
+ final long totalElapsedTime = getElapsedTime(elapsedRealtime);
+ final long screenOnTime = getScreenOnTime(elapsedRealtime);
if (userHistory == null) return;
final int P = userHistory.size();
for (int p = 0; p < P; p++) {
@@ -386,15 +385,15 @@
TimeUtils.formatDuration(totalElapsedTime - packageHistory.lastUsedElapsedTime, idpw);
idpw.print(" lastUsedScreenOn=");
TimeUtils.formatDuration(screenOnTime - packageHistory.lastUsedScreenTime, idpw);
- idpw.print(" idle=" + (isIdleLocked(packageName, userId, elapsedRealtime) ? "y" : "n"));
+ idpw.print(" idle=" + (isIdle(packageName, userId, elapsedRealtime) ? "y" : "n"));
idpw.println();
}
idpw.println();
idpw.print("totalElapsedTime=");
- TimeUtils.formatDuration(getElapsedTimeLocked(elapsedRealtime), idpw);
+ TimeUtils.formatDuration(getElapsedTime(elapsedRealtime), idpw);
idpw.println();
idpw.print("totalScreenOnTime=");
- TimeUtils.formatDuration(getScreenOnTimeLocked(elapsedRealtime), idpw);
+ TimeUtils.formatDuration(getScreenOnTime(elapsedRealtime), idpw);
idpw.println();
idpw.decreaseIndent();
}
@@ -410,7 +409,7 @@
for (int i = 0; i < HISTORY_SIZE; i++) {
idpw.print(history[i] == 0 ? '.' : 'A');
}
- idpw.print(" idle=" + (isIdleLocked(packageName, userId, elapsedRealtime) ? "y" : "n"));
+ idpw.print(" idle=" + (isIdle(packageName, userId, elapsedRealtime) ? "y" : "n"));
idpw.print(" " + packageName);
idpw.println();
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 3c743b5..469a8f1 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -153,13 +153,17 @@
private volatile boolean mPendingOneTimeCheckIdleStates;
private boolean mSystemServicesReady = false;
- @GuardedBy("mLock")
+ private final Object mAppIdleLock = new Object();
+ @GuardedBy("mAppIdleLock")
private AppIdleHistory mAppIdleHistory;
+ @GuardedBy("mAppIdleLock")
private ArrayList<UsageStatsManagerInternal.AppIdleStateChangeListener>
mPackageAccessListeners = new ArrayList<>();
+ @GuardedBy("mAppIdleLock")
private boolean mHaveCarrierPrivilegedApps;
+ @GuardedBy("mAppIdleLock")
private List<String> mCarrierPrivilegedApps;
public UsageStatsService(Context context) {
@@ -206,6 +210,8 @@
synchronized (mLock) {
cleanUpRemovedUsersLocked();
+ }
+ synchronized (mAppIdleLock) {
mAppIdleHistory = new AppIdleHistory(SystemClock.elapsedRealtime());
}
@@ -234,8 +240,8 @@
mPowerManager = getContext().getSystemService(PowerManager.class);
mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
- synchronized (mLock) {
- mAppIdleHistory.updateDisplayLocked(isDisplayOn(), SystemClock.elapsedRealtime());
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.updateDisplay(isDisplayOn(), SystemClock.elapsedRealtime());
}
if (mPendingOneTimeCheckIdleStates) {
@@ -324,8 +330,8 @@
@Override public void onDisplayChanged(int displayId) {
if (displayId == Display.DEFAULT_DISPLAY) {
final boolean displayOn = isDisplayOn();
- synchronized (UsageStatsService.this.mLock) {
- mAppIdleHistory.updateDisplayLocked(displayOn, SystemClock.elapsedRealtime());
+ synchronized (UsageStatsService.this.mAppIdleLock) {
+ mAppIdleHistory.updateDisplay(displayOn, SystemClock.elapsedRealtime());
}
}
}
@@ -386,18 +392,20 @@
PackageManager.MATCH_DISABLED_COMPONENTS,
userId);
final int packageCount = packages.size();
- for (int i = 0; i < packageCount; i++) {
- final PackageInfo pi = packages.get(i);
- String packageName = pi.packageName;
- if (pi.applicationInfo != null && pi.applicationInfo.isSystemApp()) {
- mAppIdleHistory.reportUsageLocked(packageName, userId, elapsedRealtime);
+ synchronized (mAppIdleLock) {
+ for (int i = 0; i < packageCount; i++) {
+ final PackageInfo pi = packages.get(i);
+ String packageName = pi.packageName;
+ if (pi.applicationInfo != null && pi.applicationInfo.isSystemApp()) {
+ mAppIdleHistory.reportUsage(packageName, userId, elapsedRealtime);
+ }
}
}
}
void clearAppIdleForPackage(String packageName, int userId) {
- synchronized (mLock) {
- mAppIdleHistory.clearUsageLocked(packageName, userId);
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.clearUsage(packageName, userId);
}
}
@@ -429,7 +437,7 @@
}
void setChargingState(boolean charging) {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
if (mCharging != charging) {
mCharging = charging;
postParoleStateChanged();
@@ -439,15 +447,16 @@
/** Paroled here means temporary pardon from being inactive */
void setAppIdleParoled(boolean paroled) {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
+ final long now = System.currentTimeMillis();
if (mAppIdleTempParoled != paroled) {
mAppIdleTempParoled = paroled;
if (DEBUG) Slog.d(TAG, "Changing paroled to " + mAppIdleTempParoled);
if (paroled) {
postParoleEndTimeout();
} else {
- mLastAppIdleParoledTime = checkAndGetTimeLocked();
- postNextParoleTimeout();
+ mLastAppIdleParoledTime = now;
+ postNextParoleTimeout(now);
}
postParoleStateChanged();
}
@@ -455,19 +464,18 @@
}
boolean isParoledOrCharging() {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
return mAppIdleTempParoled || mCharging;
}
}
- private void postNextParoleTimeout() {
+ private void postNextParoleTimeout(long now) {
if (DEBUG) Slog.d(TAG, "Posting MSG_CHECK_PAROLE_TIMEOUT");
mHandler.removeMessages(MSG_CHECK_PAROLE_TIMEOUT);
// Compute when the next parole needs to happen. We check more frequently than necessary
// since the message handler delays are based on elapsedRealTime and not wallclock time.
// The comparison is done in wallclock time.
- long timeLeft = (mLastAppIdleParoledTime + mAppIdleParoleIntervalMillis)
- - checkAndGetTimeLocked();
+ long timeLeft = (mLastAppIdleParoledTime + mAppIdleParoleIntervalMillis) - now;
if (timeLeft < 0) {
timeLeft = 0;
}
@@ -546,7 +554,7 @@
mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS,
userId, isIdle ? 1 : 0, packageName));
if (isIdle) {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
mAppIdleHistory.setIdle(packageName, userId, elapsedRealtime);
}
}
@@ -561,18 +569,23 @@
/** Check if it's been a while since last parole and let idle apps do some work */
void checkParoleTimeout() {
- synchronized (mLock) {
+ boolean setParoled = false;
+ synchronized (mAppIdleLock) {
+ final long now = System.currentTimeMillis();
if (!mAppIdleTempParoled) {
- final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime;
+ final long timeSinceLastParole = now - mLastAppIdleParoledTime;
if (timeSinceLastParole > mAppIdleParoleIntervalMillis) {
if (DEBUG) Slog.d(TAG, "Crossed default parole interval");
- setAppIdleParoled(true);
+ setParoled = true;
} else {
if (DEBUG) Slog.d(TAG, "Not long enough to go to parole");
- postNextParoleTimeout();
+ postNextParoleTimeout(now);
}
}
}
+ if (setParoled) {
+ setAppIdleParoled(true);
+ }
}
private void notifyBatteryStats(String packageName, int userId, boolean idle) {
@@ -593,17 +606,23 @@
void onDeviceIdleModeChanged() {
final boolean deviceIdle = mPowerManager.isDeviceIdleMode();
if (DEBUG) Slog.i(TAG, "DeviceIdleMode changed to " + deviceIdle);
- synchronized (mLock) {
- final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime;
+ boolean paroled = false;
+ synchronized (mAppIdleLock) {
+ final long timeSinceLastParole = System.currentTimeMillis() - mLastAppIdleParoledTime;
if (!deviceIdle
&& timeSinceLastParole >= mAppIdleParoleIntervalMillis) {
- if (DEBUG) Slog.i(TAG, "Bringing idle apps out of inactive state due to deviceIdleMode=false");
- setAppIdleParoled(true);
+ if (DEBUG) {
+ Slog.i(TAG, "Bringing idle apps out of inactive state due to deviceIdleMode=false");
+ }
+ paroled = true;
} else if (deviceIdle) {
if (DEBUG) Slog.i(TAG, "Device idle, back to prison");
- setAppIdleParoled(false);
+ paroled = false;
+ } else {
+ return;
}
}
+ setAppIdleParoled(paroled);
}
private static void deleteRecursively(File f) {
@@ -682,21 +701,24 @@
final UserUsageStatsService service =
getUserDataAndInitializeIfNeededLocked(userId, timeNow);
- // TODO: Ideally this should call isAppIdleFiltered() to avoid calling back
- // about apps that are on some kind of whitelist anyway.
- final boolean previouslyIdle = mAppIdleHistory.isIdleLocked(
- event.mPackage, userId, elapsedRealtime);
service.reportEvent(event);
- // Inform listeners if necessary
- if ((event.mEventType == Event.MOVE_TO_FOREGROUND
- || event.mEventType == Event.MOVE_TO_BACKGROUND
- || event.mEventType == Event.SYSTEM_INTERACTION
- || event.mEventType == Event.USER_INTERACTION)) {
- mAppIdleHistory.reportUsageLocked(event.mPackage, userId, elapsedRealtime);
- if (previouslyIdle) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
- /* idle = */ 0, event.mPackage));
- notifyBatteryStats(event.mPackage, userId, false);
+
+ synchronized (mAppIdleLock) {
+ // TODO: Ideally this should call isAppIdleFiltered() to avoid calling back
+ // about apps that are on some kind of whitelist anyway.
+ final boolean previouslyIdle = mAppIdleHistory.isIdle(
+ event.mPackage, userId, elapsedRealtime);
+ // Inform listeners if necessary
+ if ((event.mEventType == Event.MOVE_TO_FOREGROUND
+ || event.mEventType == Event.MOVE_TO_BACKGROUND
+ || event.mEventType == Event.SYSTEM_INTERACTION
+ || event.mEventType == Event.USER_INTERACTION)) {
+ mAppIdleHistory.reportUsage(event.mPackage, userId, elapsedRealtime);
+ if (previouslyIdle) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
+ /* idle = */ 0, event.mPackage));
+ notifyBatteryStats(event.mPackage, userId, false);
+ }
}
}
}
@@ -716,7 +738,7 @@
continue;
}
if (!packageName.equals(providerPkgName)) {
- forceIdleState(packageName, userId, false);
+ setAppIdleAsync(packageName, false, userId);
}
} catch (NameNotFoundException e) {
// Shouldn't happen
@@ -728,25 +750,28 @@
* Forces the app's beginIdleTime and lastUsedTime to reflect idle or active. If idle,
* then it rolls back the beginIdleTime and lastUsedTime to a point in time that's behind
* the threshold for idle.
+ *
+ * This method is always called from the handler thread, so not much synchronization is
+ * required.
*/
void forceIdleState(String packageName, int userId, boolean idle) {
final int appId = getAppId(packageName);
if (appId < 0) return;
- synchronized (mLock) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
- final boolean previouslyIdle = isAppIdleFiltered(packageName, appId,
- userId, elapsedRealtime);
- mAppIdleHistory.setIdleLocked(packageName, userId, idle, elapsedRealtime);
- final boolean stillIdle = isAppIdleFiltered(packageName, appId,
- userId, elapsedRealtime);
- // Inform listeners if necessary
- if (previouslyIdle != stillIdle) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
- /* idle = */ stillIdle ? 1 : 0, packageName));
- if (!stillIdle) {
- notifyBatteryStats(packageName, userId, idle);
- }
+ final boolean previouslyIdle = isAppIdleFiltered(packageName, appId,
+ userId, elapsedRealtime);
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.setIdle(packageName, userId, idle, elapsedRealtime);
+ }
+ final boolean stillIdle = isAppIdleFiltered(packageName, appId,
+ userId, elapsedRealtime);
+ // Inform listeners if necessary
+ if (previouslyIdle != stillIdle) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
+ /* idle = */ stillIdle ? 1 : 0, packageName));
+ if (!stillIdle) {
+ notifyBatteryStats(packageName, userId, idle);
}
}
}
@@ -767,7 +792,9 @@
synchronized (mLock) {
Slog.i(TAG, "Removing user " + userId + " and all data.");
mUserState.remove(userId);
- mAppIdleHistory.onUserRemoved(userId);
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.onUserRemoved(userId);
+ }
cleanUpRemovedUsersLocked();
}
}
@@ -822,13 +849,13 @@
}
private boolean isAppIdleUnfiltered(String packageName, int userId, long elapsedRealtime) {
- synchronized (mLock) {
- return mAppIdleHistory.isIdleLocked(packageName, userId, elapsedRealtime);
+ synchronized (mAppIdleLock) {
+ return mAppIdleHistory.isIdle(packageName, userId, elapsedRealtime);
}
}
void addListener(AppIdleStateChangeListener listener) {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
if (!mPackageAccessListeners.contains(listener)) {
mPackageAccessListeners.add(listener);
}
@@ -836,7 +863,7 @@
}
void removeListener(AppIdleStateChangeListener listener) {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
mPackageAccessListeners.remove(listener);
}
}
@@ -988,7 +1015,7 @@
return res;
}
- void setAppIdle(String packageName, boolean idle, int userId) {
+ void setAppIdleAsync(String packageName, boolean idle, int userId) {
if (packageName == null) return;
mHandler.obtainMessage(MSG_FORCE_IDLE_STATE, userId, idle ? 1 : 0, packageName)
@@ -1012,9 +1039,9 @@
}
private boolean isCarrierApp(String packageName) {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
if (!mHaveCarrierPrivilegedApps) {
- fetchCarrierPrivilegedAppsLocked();
+ fetchCarrierPrivilegedAppsLA();
}
if (mCarrierPrivilegedApps != null) {
return mCarrierPrivilegedApps.contains(packageName);
@@ -1027,13 +1054,14 @@
if (DEBUG) {
Slog.i(TAG, "Clearing carrier privileged apps list");
}
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
mHaveCarrierPrivilegedApps = false;
mCarrierPrivilegedApps = null; // Need to be refetched.
}
}
- private void fetchCarrierPrivilegedAppsLocked() {
+ @GuardedBy("mAppIdleLock")
+ private void fetchCarrierPrivilegedAppsLA() {
TelephonyManager telephonyManager =
getContext().getSystemService(TelephonyManager.class);
mCarrierPrivilegedApps = telephonyManager.getPackagesWithCarrierPrivileges();
@@ -1071,11 +1099,15 @@
for (int i = 0; i < userCount; i++) {
UserUsageStatsService service = mUserState.valueAt(i);
service.persistActiveStats();
- mAppIdleHistory.writeAppIdleTimesLocked(mUserState.keyAt(i));
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.writeAppIdleTimes(mUserState.keyAt(i));
+ }
}
// Persist elapsed and screen on time. If this fails for whatever reason, the apps will be
// considered not-idle, which is the safest outcome in such an event.
- mAppIdleHistory.writeAppIdleDurationsLocked();
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.writeAppIdleDurations();
+ }
mHandler.removeMessages(MSG_FLUSH_TO_DISK);
}
@@ -1100,20 +1132,26 @@
idpw.println();
if (args.length > 0) {
if ("history".equals(args[0])) {
- mAppIdleHistory.dumpHistory(idpw, mUserState.keyAt(i));
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.dumpHistory(idpw, mUserState.keyAt(i));
+ }
} else if ("flush".equals(args[0])) {
UsageStatsService.this.flushToDiskLocked();
pw.println("Flushed stats to disk");
}
}
}
- mAppIdleHistory.dump(idpw, mUserState.keyAt(i));
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.dump(idpw, mUserState.keyAt(i));
+ }
idpw.decreaseIndent();
}
pw.println();
- pw.println("Carrier privileged apps (have=" + mHaveCarrierPrivilegedApps
- + "): " + mCarrierPrivilegedApps);
+ synchronized (mAppIdleLock) {
+ pw.println("Carrier privileged apps (have=" + mHaveCarrierPrivilegedApps
+ + "): " + mCarrierPrivilegedApps);
+ }
pw.println();
pw.println("Settings:");
@@ -1252,7 +1290,7 @@
}
void updateSettings() {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
// Look at global settings for this.
// TODO: Maybe apply different thresholds for different users.
try {
@@ -1384,7 +1422,7 @@
try {
userId = ActivityManager.getService().handleIncomingUser(
Binder.getCallingPid(), callingUid, userId, false, true,
- "setAppIdle", null);
+ "setAppInactive", null);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -1394,7 +1432,7 @@
try {
final int appId = getAppId(packageName);
if (appId < 0) return;
- UsageStatsService.this.setAppIdle(packageName, idle, userId);
+ UsageStatsService.this.setAppIdleAsync(packageName, idle, userId);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1586,21 +1624,25 @@
@Override
public byte[] getBackupPayload(int user, String key) {
// Check to ensure that only user 0's data is b/r for now
- if (user == UserHandle.USER_SYSTEM) {
- final UserUsageStatsService userStats =
- getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
- return userStats.getBackupPayload(key);
- } else {
- return null;
+ synchronized (UsageStatsService.this.mLock) {
+ if (user == UserHandle.USER_SYSTEM) {
+ final UserUsageStatsService userStats =
+ getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
+ return userStats.getBackupPayload(key);
+ } else {
+ return null;
+ }
}
}
@Override
public void applyRestoredPayload(int user, String key, byte[] payload) {
- if (user == UserHandle.USER_SYSTEM) {
- final UserUsageStatsService userStats =
- getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
- userStats.applyRestoredPayload(key, payload);
+ synchronized (UsageStatsService.this.mLock) {
+ if (user == UserHandle.USER_SYSTEM) {
+ final UserUsageStatsService userStats =
+ getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
+ userStats.applyRestoredPayload(key, payload);
+ }
}
}
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index d9f352c..8d335a5 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -529,7 +529,6 @@
pw.decreaseIndent();
pw.println();
- pw.increaseIndent();
pw.println("ChooserCounts");
pw.increaseIndent();
for (UsageStats usageStats : pkgStats.values()) {
@@ -553,6 +552,7 @@
}
pw.println();
}
+ pw.decreaseIndent();
pw.println("configurations");
pw.increaseIndent();
diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java
index 4b8e4c8..bae7cdc 100644
--- a/services/usb/java/com/android/server/usb/UsbPortManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPortManager.java
@@ -455,9 +455,9 @@
public void notifyRoleSwitchStatus(String portName, PortRole role, int retval) {
if (retval == Status.SUCCESS) {
- logAndPrint(Log.INFO, pw, portName + "role switch successful");
+ logAndPrint(Log.INFO, pw, portName + " role switch successful");
} else {
- logAndPrint(Log.ERROR, pw, portName + "role switch failed");
+ logAndPrint(Log.ERROR, pw, portName + " role switch failed");
}
}
};
@@ -498,11 +498,12 @@
mProxy.setCallback(mHALCallback);
mProxy.queryPortStatus();
} catch (NoSuchElementException e) {
- logAndPrint(Log.ERROR, pw, sSERVICENAME + "not found."
- + " Did the service failed to start ?");
+ logAndPrint(Log.ERROR, pw, sSERVICENAME + " not found."
+ + " Did the service fail to start?");
Thread.dumpStack();
} catch (RemoteException e) {
- logAndPrint(Log.ERROR, pw, sSERVICENAME + "connectToProxy: Service not responding");
+ logAndPrint(Log.ERROR, pw, sSERVICENAME
+ + " connectToProxy: Service not responding");
Thread.dumpStack();
}
}
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index 216603c..e0e3a08 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -235,7 +235,7 @@
StringBuilder sb = new StringBuilder();
sb.append("Audio");
- if (isAudioOnly(videoState)) {
+ if (videoState == STATE_AUDIO_ONLY) {
sb.append(" Only");
} else {
if (isTransmissionEnabled(videoState)) {
@@ -256,6 +256,9 @@
/**
* Indicates whether the video state is audio only.
+ * <p>
+ * Note: Considers only whether either both the {@link #STATE_RX_ENABLED} or
+ * {@link #STATE_TX_ENABLED} bits are off, but not {@link #STATE_PAUSED}.
*
* @param videoState The video state.
* @return {@code True} if the video state is audio only, {@code false} otherwise.
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 7bb58dd4..632a1d6 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1282,6 +1282,14 @@
"support_3gpp_call_forwarding_while_roaming_bool";
/**
+ * When {@code true}, the user will be notified when they attempt to place an international call
+ * when the call is placed using wifi calling.
+ * @hide
+ */
+ public static final String KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL =
+ "notify_international_call_on_wfc_bool";
+
+ /**
* Determine whether user edited tether APN (type dun) has effect
* {@code false} - Default. APN with dun type in telephony database has no effect.
*
@@ -1529,6 +1537,7 @@
sDefaults.putStringArray(KEY_CARRIER_WIFI_STRING_ARRAY, null);
sDefaults.putInt(KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT, -1);
sDefaults.putBoolean(KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL, true);
+ sDefaults.putBoolean(KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL, false);
sDefaults.putBoolean(KEY_EDITABLE_TETHER_APN_BOOL, false);
sDefaults.putStringArray(KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY,
null);
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 6f51c6e..a3e11c8 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1140,6 +1140,8 @@
private static final String KOREA_ISO_COUNTRY_CODE = "KR";
+ private static final String JAPAN_ISO_COUNTRY_CODE = "JP";
+
/**
* Breaks the given number down and formats it according to the rules
* for the country the number is from.
@@ -1438,6 +1440,30 @@
}
/**
+ * Determines if a {@param phoneNumber} is international if dialed from
+ * {@param defaultCountryIso}.
+ *
+ * @param phoneNumber The phone number.
+ * @param defaultCountryIso The current country ISO.
+ * @return {@code true} if the number is international, {@code false} otherwise.
+ * @hide
+ */
+ public static boolean isInternationalNumber(String phoneNumber, String defaultCountryIso) {
+ // If it starts with # or * its not international.
+ if (phoneNumber.startsWith("#") || phoneNumber.startsWith("*")) {
+ return false;
+ }
+
+ PhoneNumberUtil util = PhoneNumberUtil.getInstance();
+ try {
+ PhoneNumber pn = util.parseAndKeepRawInput(phoneNumber, defaultCountryIso);
+ return pn.getCountryCode() != util.getCountryCodeForRegion(defaultCountryIso);
+ } catch (NumberParseException e) {
+ return false;
+ }
+ }
+
+ /**
* Format a phone number.
* <p>
* If the given number doesn't have the country code, the phone will be
@@ -1460,15 +1486,25 @@
String result = null;
try {
PhoneNumber pn = util.parseAndKeepRawInput(phoneNumber, defaultCountryIso);
- /**
- * Need to reformat any local Korean phone numbers (when the user is in Korea) with
- * country code to corresponding national format which would replace the leading
- * +82 with 0.
- */
- if (KOREA_ISO_COUNTRY_CODE.equals(defaultCountryIso) &&
+
+ if (KOREA_ISO_COUNTRY_CODE.equalsIgnoreCase(defaultCountryIso) &&
(pn.getCountryCode() == util.getCountryCodeForRegion(KOREA_ISO_COUNTRY_CODE)) &&
(pn.getCountryCodeSource() ==
PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN)) {
+ /**
+ * Need to reformat any local Korean phone numbers (when the user is in Korea) with
+ * country code to corresponding national format which would replace the leading
+ * +82 with 0.
+ */
+ result = util.format(pn, PhoneNumberUtil.PhoneNumberFormat.NATIONAL);
+ } else if (JAPAN_ISO_COUNTRY_CODE.equalsIgnoreCase(defaultCountryIso) &&
+ pn.getCountryCode() == util.getCountryCodeForRegion(JAPAN_ISO_COUNTRY_CODE) &&
+ (pn.getCountryCodeSource() ==
+ PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN)) {
+ /**
+ * Need to reformat Japanese phone numbers (when user is in Japan) with the national
+ * dialing format.
+ */
result = util.format(pn, PhoneNumberUtil.PhoneNumberFormat.NATIONAL);
} else {
result = util.formatInOriginalFormat(pn, defaultCountryIso);
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index dd03305..afff6d5 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -208,7 +208,9 @@
*
* @see #onOemHookRawEvent
* @hide
+ * @deprecated OEM needs a vendor-extension hal and their apps should use that instead
*/
+ @Deprecated
public static final int LISTEN_OEM_HOOK_RAW_EVENT = 0x00008000;
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a4235d7..81e87b3 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -819,6 +819,21 @@
public static final String EVENT_DOWNGRADE_DATA_DISABLED =
"android.telephony.event.EVENT_DOWNGRADE_DATA_DISABLED";
+ /**
+ * {@link android.telecom.Connection} event used to indicate that the InCall UI should notify
+ * the user when an international call is placed while on WFC only.
+ * <p>
+ * Used when the carrier config value
+ * {@link CarrierConfigManager#KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL} is true, the device
+ * is on WFC (VoLTE not available) and an international number is dialed.
+ * <p>
+ * Sent via {@link android.telecom.Connection#sendConnectionEvent(String, Bundle)}.
+ * The {@link Bundle} parameter is expected to be null when this connection event is used.
+ * @hide
+ */
+ public static final String EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC =
+ "android.telephony.event.EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC";
+
/* Visual voicemail protocols */
/**
@@ -5229,7 +5244,9 @@
* 0 request was handled succesfully, but no response data
* positive value success, data length of response
* @hide
+ * @deprecated OEM needs a vendor-extension hal and their apps should use that instead
*/
+ @Deprecated
public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
try {
ITelephony telephony = getITelephony();
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index fe8dbfb..406f01e 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -41,6 +41,9 @@
import com.android.ims.internal.IImsUt;
import com.android.internal.annotations.VisibleForTesting;
+import static android.Manifest.permission.MODIFY_PHONE_STATE;
+import static android.Manifest.permission.READ_PHONE_STATE;
+
/**
* Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend
* ImsService must register the service in their AndroidManifest to be detected by the framework.
@@ -94,6 +97,7 @@
public void createImsFeature(int slotId, int feature, IImsFeatureStatusCallback c)
throws RemoteException {
synchronized (mFeatures) {
+ enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "createImsFeature");
onCreateImsFeatureInternal(slotId, feature, c);
}
}
@@ -101,6 +105,7 @@
@Override
public void removeImsFeature(int slotId, int feature) throws RemoteException {
synchronized (mFeatures) {
+ enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "removeImsFeature");
onRemoveImsFeatureInternal(slotId, feature);
}
}
@@ -108,6 +113,7 @@
@Override
public int startSession(int slotId, int featureType, PendingIntent incomingCallIntent,
IImsRegistrationListener listener) throws RemoteException {
+ enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "startSession");
synchronized (mFeatures) {
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
@@ -120,6 +126,7 @@
@Override
public void endSession(int slotId, int featureType, int sessionId) throws RemoteException {
synchronized (mFeatures) {
+ enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "endSession");
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
feature.endSession(sessionId);
@@ -130,6 +137,7 @@
@Override
public boolean isConnected(int slotId, int featureType, int callSessionType, int callType)
throws RemoteException {
+ enforceCallingOrSelfPermission(READ_PHONE_STATE, "isConnected");
synchronized (mFeatures) {
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
@@ -141,6 +149,7 @@
@Override
public boolean isOpened(int slotId, int featureType) throws RemoteException {
+ enforceCallingOrSelfPermission(READ_PHONE_STATE, "isOpened");
synchronized (mFeatures) {
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
@@ -152,6 +161,7 @@
@Override
public int getFeatureStatus(int slotId, int featureType) throws RemoteException {
+ enforceCallingOrSelfPermission(READ_PHONE_STATE, "getFeatureStatus");
int status = ImsFeature.STATE_NOT_AVAILABLE;
synchronized (mFeatures) {
SparseArray<ImsFeature> featureMap = mFeatures.get(slotId);
@@ -168,6 +178,7 @@
@Override
public void addRegistrationListener(int slotId, int featureType,
IImsRegistrationListener listener) throws RemoteException {
+ enforceCallingOrSelfPermission(READ_PHONE_STATE, "addRegistrationListener");
synchronized (mFeatures) {
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
@@ -179,6 +190,7 @@
@Override
public void removeRegistrationListener(int slotId, int featureType,
IImsRegistrationListener listener) throws RemoteException {
+ enforceCallingOrSelfPermission(READ_PHONE_STATE, "removeRegistrationListener");
synchronized (mFeatures) {
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
@@ -190,6 +202,7 @@
@Override
public ImsCallProfile createCallProfile(int slotId, int featureType, int sessionId,
int callSessionType, int callType) throws RemoteException {
+ enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "createCallProfile");
synchronized (mFeatures) {
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
@@ -202,6 +215,7 @@
@Override
public IImsCallSession createCallSession(int slotId, int featureType, int sessionId,
ImsCallProfile profile, IImsCallSessionListener listener) throws RemoteException {
+ enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "createCallSession");
synchronized (mFeatures) {
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
@@ -214,6 +228,7 @@
@Override
public IImsCallSession getPendingCallSession(int slotId, int featureType, int sessionId,
String callId) throws RemoteException {
+ enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "getPendingCallSession");
synchronized (mFeatures) {
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
@@ -226,6 +241,7 @@
@Override
public IImsUt getUtInterface(int slotId, int featureType)
throws RemoteException {
+ enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "getUtInterface");
synchronized (mFeatures) {
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
@@ -238,6 +254,7 @@
@Override
public IImsConfig getConfigInterface(int slotId, int featureType)
throws RemoteException {
+ enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "getConfigInterface");
synchronized (mFeatures) {
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
@@ -249,6 +266,7 @@
@Override
public void turnOnIms(int slotId, int featureType) throws RemoteException {
+ enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "turnOnIms");
synchronized (mFeatures) {
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
@@ -259,6 +277,7 @@
@Override
public void turnOffIms(int slotId, int featureType) throws RemoteException {
+ enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "turnOffIms");
synchronized (mFeatures) {
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
@@ -270,6 +289,7 @@
@Override
public IImsEcbm getEcbmInterface(int slotId, int featureType)
throws RemoteException {
+ enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "getEcbmInterface");
synchronized (mFeatures) {
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
@@ -282,6 +302,7 @@
@Override
public void setUiTTYMode(int slotId, int featureType, int uiTtyMode, Message onComplete)
throws RemoteException {
+ enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "setUiTTYMode");
synchronized (mFeatures) {
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
@@ -293,6 +314,7 @@
@Override
public IImsMultiEndpoint getMultiEndpointInterface(int slotId, int featureType)
throws RemoteException {
+ enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "getMultiEndpointInterface");
synchronized (mFeatures) {
MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
if (feature != null) {
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index d40835b..bcaac6e 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -264,22 +264,13 @@
= "android.intent.action.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS";
/**
- * Activity Action: Start this activity to invoke the carrier setup app.
- * The carrier app must be signed using a certificate that matches the UICC access rules.
- *
- * <p class="note">Callers of this should hold the android.permission.INVOKE_CARRIER_SETUP
- * permission.</p>
- */
- public static final String ACTION_CARRIER_SETUP = "android.intent.action.ACTION_CARRIER_SETUP";
-
- /**
* <p>Broadcast Action: Indicates that the action is forbidden by network.
* <p class="note">
* This is for the OEM applications to understand about possible provisioning issues.
* Used in OMA-DM applications.
*/
public static final String ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION
- = "android.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION";
+ = "com.android.internal.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION";
/**
* Broadcast Action: A "secret code" has been entered in the dialer. Secret codes are
diff --git a/tests/SoundTriggerTestApp/res/layout/main.xml b/tests/SoundTriggerTestApp/res/layout/main.xml
index 0fd8b12..2c6c8d7 100644
--- a/tests/SoundTriggerTestApp/res/layout/main.xml
+++ b/tests/SoundTriggerTestApp/res/layout/main.xml
@@ -87,6 +87,7 @@
android:text="@string/capture"
android:id="@+id/caputre_check_box"
android:layout_gravity="center_horizontal"
+ android:onClick="onCaptureAudioCheckboxClicked"
android:padding="20dp" />
<Button
@@ -94,6 +95,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/play_capture"
+ android:onClick="onPlayCapturedAudioButtonClicked"
android:padding="20dp"
android:enabled="false" />
</LinearLayout>
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 56aad23..9b1a9f2 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -297,6 +297,7 @@
Notification n = new Notification.Builder(NotificationTestList.this)
.setSmallIcon(R.drawable.icon2)
.setContentTitle("Low priority")
+ .setTimeout(60000)
.setLights(0xff0000ff, 1, 0)
.setPriority(Notification.PRIORITY_LOW)
.build();
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
index 174bbcf..cc7631a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
@@ -571,6 +571,8 @@
@NonNull
public Consumer<Float> getFloatPropertySetter(int propertyIdx) {
switch (propertyIdx) {
+ case STROKE_WIDTH_INDEX:
+ return this::setStrokeWidth;
case STROKE_ALPHA_INDEX:
return this::setStrokeAlpha;
case FILL_ALPHA_INDEX:
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
index a53dcba..f15d669 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
index 05a3665..456b5f6 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
@@ -263,7 +263,8 @@
android:id="@id/radioButton2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="New RadioButton" />
+ android:text="New RadioButton"
+ android:checked="true" />
</RadioGroup>
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
index adf189b..57b98e9 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -31,8 +31,7 @@
* {@link PublishDiscoverySession} and {@link SubscribeDiscoverySession}. This
* class provides functionality common to both publish and subscribe discovery sessions:
* <ul>
- * <li>Sending messages: {@link #sendMessage(PeerHandle, int, byte[])} or
- * {@link #sendMessage(PeerHandle, int, byte[], int)} methods.
+ * <li>Sending messages: {@link #sendMessage(PeerHandle, int, byte[])}.
* <li>Creating a network-specifier when requesting a Aware connection:
* {@link #createNetworkSpecifier(PeerHandle, byte[])}.
* </ul>
@@ -62,6 +61,8 @@
* {@link #sendMessage(PeerHandle, int, byte[], int)}.
*
* @return Maximum retry count when sending messages.
+ *
+ * @hide
*/
public static int getMaxSendRetryCount() {
return MAX_SEND_RETRY_COUNT;
@@ -163,6 +164,8 @@
* or MAC level) retries should be attempted if there is no ACK from the receiver
* (note: no retransmissions are attempted in other failure cases). A value of 0
* indicates no retries. Max permitted value is {@link #getMaxSendRetryCount()}.
+ *
+ * @hide
*/
public void sendMessage(@NonNull PeerHandle peerHandle, int messageId,
@Nullable byte[] message, int retryCount) {
@@ -195,8 +198,6 @@
* The peer will get a callback indicating a message was received using
* {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])}.
- * Equivalent to {@link #sendMessage(PeerHandle, int, byte[], int)}
- * with a {@code retryCount} of 0.
*
* @param peerHandle The peer's handle for the message. Must be a result of an
* {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
index 33da182..9645b1d 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
@@ -124,10 +124,9 @@
}
/**
- * Called when message transmission fails - when no ACK is received from the peer.
- * Retries when ACKs are not received are done by hardware, MAC, and in the Aware stack (using
- * the {@link DiscoverySession#sendMessage(PeerHandle, int,
- * byte[], int)} method) - this event is received after all retries are exhausted.
+ * Called when message transmission initiated with
+ * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])} fails. E.g. when no ACK is
+ * received from the peer.
* <p>
* Note that either this callback or
* {@link DiscoverySessionCallback#onMessageSendSucceeded(int)} will be received
@@ -141,9 +140,7 @@
/**
* Called when a message is received from a discovery session peer - in response to the
- * peer's {@link DiscoverySession#sendMessage(PeerHandle, int,
- * byte[])} or {@link DiscoverySession#sendMessage(PeerHandle,
- * int, byte[], int)}.
+ * peer's {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])}.
*
* @param peerHandle An opaque handle to the peer matching our discovery operation.
* @param message A byte array containing the message.