Merge "Only match addresses without zip codes if at the end." into pi-dev
diff --git a/api/current.txt b/api/current.txt
index 7ece217..2572cd3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -27274,7 +27274,6 @@
method public int describeContents();
method public boolean hasCapability(int);
method public boolean hasTransport(int);
- method public boolean hasUnwantedCapability(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.NetworkRequest> CREATOR;
}
@@ -27283,7 +27282,6 @@
ctor public NetworkRequest.Builder();
method public android.net.NetworkRequest.Builder addCapability(int);
method public android.net.NetworkRequest.Builder addTransportType(int);
- method public android.net.NetworkRequest.Builder addUnwantedCapability(int);
method public android.net.NetworkRequest build();
method public android.net.NetworkRequest.Builder removeCapability(int);
method public android.net.NetworkRequest.Builder removeTransportType(int);
@@ -47891,7 +47889,7 @@
method public void setVerticalScrollBarEnabled(boolean);
method public void setVerticalScrollbarPosition(int);
method public void setVisibility(int);
- method public void setWillNotCacheDrawing(boolean);
+ method public deprecated void setWillNotCacheDrawing(boolean);
method public void setWillNotDraw(boolean);
method public void setX(float);
method public void setY(float);
@@ -47909,7 +47907,7 @@
method public void unscheduleDrawable(android.graphics.drawable.Drawable);
method public final void updateDragShadow(android.view.View.DragShadowBuilder);
method protected boolean verifyDrawable(android.graphics.drawable.Drawable);
- method public boolean willNotCacheDrawing();
+ method public deprecated boolean willNotCacheDrawing();
method public boolean willNotDraw();
field public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 2; // 0x2
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
diff --git a/api/removed.txt b/api/removed.txt
index 1d6a8c2..8d72483 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -291,6 +291,14 @@
public static abstract class NetworkBadging.Badging implements java.lang.annotation.Annotation {
}
+ public class NetworkRequest implements android.os.Parcelable {
+ method public boolean hasUnwantedCapability(int);
+ }
+
+ public static class NetworkRequest.Builder {
+ method public android.net.NetworkRequest.Builder addUnwantedCapability(int);
+ }
+
public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 23b6819..9f2aaab 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -469,6 +469,10 @@
package android.media {
+ public final class AudioFocusRequest {
+ method public android.media.AudioManager.OnAudioFocusChangeListener getOnAudioFocusChangeListener();
+ }
+
public final class AudioFormat implements android.os.Parcelable {
method public static int channelCountFromInChannelMask(int);
method public static int channelCountFromOutChannelMask(int);
@@ -476,6 +480,12 @@
method public static boolean isEncodingLinearPcm(int);
}
+ public final class AudioPresentation {
+ ctor public AudioPresentation(int, int, java.util.Map<java.lang.String, java.lang.String>, java.lang.String, int, boolean, boolean, boolean);
+ method public int getPresentationId();
+ method public int getProgramId();
+ }
+
public static final class VolumeShaper.Configuration.Builder {
method public android.media.VolumeShaper.Configuration.Builder setOptionFlags(int);
}
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index f16109c..d3cda63 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -178,23 +178,34 @@
}
bool verbose = false;
+ bool proto = false;
if (args.size() > 0 && !args[0].compare(String16("-v"))) {
verbose = true;
}
+ if (args.size() > 0 && !args[args.size()-1].compare(String16("--proto"))) {
+ proto = true;
+ }
- // TODO: Proto format for incident reports
- dump_impl(out, verbose);
+ dump_impl(out, verbose, proto);
fclose(out);
return NO_ERROR;
}
/**
- * Write debugging data about statsd in text format.
+ * Write debugging data about statsd in text or proto format.
*/
-void StatsService::dump_impl(FILE* out, bool verbose) {
- StatsdStats::getInstance().dumpStats(out);
- mProcessor->dumpStates(out, verbose);
+void StatsService::dump_impl(FILE* out, bool verbose, bool proto) {
+ if (proto) {
+ vector<uint8_t> data;
+ StatsdStats::getInstance().dumpStats(&data, false); // does not reset statsdStats.
+ for (size_t i = 0; i < data.size(); i ++) {
+ fprintf(out, "%c", data[i]);
+ }
+ } else {
+ StatsdStats::getInstance().dumpStats(out);
+ mProcessor->dumpStates(out, verbose);
+ }
}
/**
@@ -325,6 +336,7 @@
fprintf(out, "\n");
fprintf(out, "usage: adb shell cmd stats print-stats\n");
fprintf(out, " Prints some basic stats.\n");
+ fprintf(out, " --proto Print proto binary instead of string format.\n");
fprintf(out, "\n");
fprintf(out, "\n");
fprintf(out, "usage: adb shell cmd stats clear-puller-cache\n");
@@ -524,13 +536,28 @@
}
status_t StatsService::cmd_print_stats(FILE* out, const Vector<String8>& args) {
- vector<ConfigKey> configs = mConfigManager->GetAllConfigKeys();
- for (const ConfigKey& key : configs) {
- fprintf(out, "Config %s uses %zu bytes\n", key.ToString().c_str(),
- mProcessor->GetMetricsSize(key));
+ int argCount = args.size();
+ bool proto = false;
+ if (!std::strcmp("--proto", args[argCount-1].c_str())) {
+ proto = true;
+ argCount -= 1;
}
StatsdStats& statsdStats = StatsdStats::getInstance();
- statsdStats.dumpStats(out);
+ if (proto) {
+ vector<uint8_t> data;
+ statsdStats.dumpStats(&data, false); // does not reset statsdStats.
+ for (size_t i = 0; i < data.size(); i ++) {
+ fprintf(out, "%c", data[i]);
+ }
+
+ } else {
+ vector<ConfigKey> configs = mConfigManager->GetAllConfigKeys();
+ for (const ConfigKey& key : configs) {
+ fprintf(out, "Config %s uses %zu bytes\n", key.ToString().c_str(),
+ mProcessor->GetMetricsSize(key));
+ }
+ statsdStats.dumpStats(out);
+ }
return NO_ERROR;
}
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index a4552e1..648e9c5 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -149,9 +149,9 @@
uint32_t serial);
/**
- * Text output of dumpsys.
+ * Text or proto output of dumpsys.
*/
- void dump_impl(FILE* out, bool verbose);
+ void dump_impl(FILE* out, bool verbose, bool proto);
/**
* Print usage information for the commands
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index bf17d70..1cddd2a 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -2245,7 +2245,6 @@
Landroid/view/SurfaceView;->mSurfaceHolder:Landroid/view/SurfaceHolder;
Landroid/view/SurfaceView;->surfacePositionLost_uiRtSync(J)V
Landroid/view/SurfaceView;->updateSurfacePosition_renderWorker(JIIII)V
-Landroid/view/textclassifier/Logger;->DISABLED:Landroid/view/textclassifier/Logger;
Landroid/view/textclassifier/logging/SmartSelectionEventTracker;-><init>(Landroid/content/Context;I)V
Landroid/view/textclassifier/logging/SmartSelectionEventTracker;->logEvent(Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;)V
Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionAction(III)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 8719875..4ab6724 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -6431,6 +6431,7 @@
/**
* @return the user to be displayed for any replies sent by the user
*/
+ @NonNull
public Person getUser() {
return mUser;
}
@@ -6505,7 +6506,8 @@
*
* @return this object for method chaining
*/
- public MessagingStyle addMessage(CharSequence text, long timestamp, Person sender) {
+ public MessagingStyle addMessage(@NonNull CharSequence text, long timestamp,
+ @Nullable Person sender) {
return addMessage(new Message(text, timestamp, sender));
}
@@ -6935,7 +6937,7 @@
* to differentiate between the different users.
* </p>
*/
- public Message(CharSequence text, long timestamp, @Nullable Person sender){
+ public Message(@NonNull CharSequence text, long timestamp, @Nullable Person sender) {
mText = text;
mTimestamp = timestamp;
mSender = sender;
diff --git a/core/java/android/app/RemoteAction.java b/core/java/android/app/RemoteAction.java
index 47741c0..c174665 100644
--- a/core/java/android/app/RemoteAction.java
+++ b/core/java/android/app/RemoteAction.java
@@ -122,6 +122,7 @@
public RemoteAction clone() {
RemoteAction action = new RemoteAction(mIcon, mTitle, mContentDescription, mActionIntent);
action.setEnabled(mEnabled);
+ action.setShouldShowIcon(mShouldShowIcon);
return action;
}
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index b2fe958..85f4efc 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -305,6 +305,8 @@
* {@link java.lang.System#currentTimeMillis}.
* @param uid UID of app
* @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
+ * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
+ * traffic from all states.
* @return Statistics object or null if an error happened during statistics collection.
* @throws SecurityException if permissions are insufficient to read network statistics.
*/
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index 8f8083e..159e165 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -421,29 +421,29 @@
}
/**
- * Check whether the device is active.
+ * Get the connected physical Hearing Aid devices that are active
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH}
* permission.
*
- * @return the connected device that is active or null if no device
- * is active
+ * @return the list of active devices. The first element is the left active
+ * device; the second element is the right active device. If either or both side
+ * is not active, it will be null on that position. Returns empty list on error.
* @hide
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
- public boolean isActiveDevice(@Nullable BluetoothDevice device) {
- if (VDBG) log("isActiveDevice()");
+ public List<BluetoothDevice> getActiveDevices() {
+ if (VDBG) log("getActiveDevices()");
try {
mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
- && ((device == null) || isValidDevice(device))) {
- return mService.isActiveDevice(device);
+ if (mService != null && isEnabled()) {
+ return mService.getActiveDevices();
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
- return false;
+ return new ArrayList<>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return false;
+ return new ArrayList<>();
} finally {
mServiceLock.readLock().unlock();
}
diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java
index af99bf7..3bc8544 100644
--- a/core/java/android/bluetooth/BluetoothHidDevice.java
+++ b/core/java/android/bluetooth/BluetoothHidDevice.java
@@ -701,6 +701,28 @@
}
/**
+ * Gets the application name of the current HidDeviceService user.
+ *
+ * @return the current user name, or empty string if cannot get the name
+ * {@hide}
+ */
+ public String getUserAppName() {
+ final IBluetoothHidDevice service = mService;
+
+ if (service != null) {
+ try {
+ return service.getUserAppName();
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+
+ return "";
+ }
+
+ /**
* Initiates connection to host which is currently paired with this device. If the application
* is not registered, #connect(BluetoothDevice) will fail. The connection state should be
* tracked by the application by handling callback from Callback#onConnectionStateChanged. The
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index efc9b6d..01ee671 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -6810,6 +6810,9 @@
case "--activity-task-on-home":
intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
break;
+ case "--activity-match-external":
+ intent.addFlags(Intent.FLAG_ACTIVITY_MATCH_EXTERNAL);
+ break;
case "--receiver-registered-only":
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
break;
@@ -6946,7 +6949,7 @@
" [--activity-no-user-action] [--activity-previous-is-top]",
" [--activity-reorder-to-front] [--activity-reset-task-if-needed]",
" [--activity-single-top] [--activity-clear-task]",
- " [--activity-task-on-home]",
+ " [--activity-task-on-home] [--activity-match-external]",
" [--receiver-registered-only] [--receiver-replace-pending]",
" [--receiver-foreground] [--receiver-no-abort]",
" [--receiver-include-background]",
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 82af5d3..6f812ac 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -233,6 +233,8 @@
*
* @param capability The capability to add to unwanted capability list.
* @return The builder to facilitate chaining.
+ *
+ * @removed
*/
public Builder addUnwantedCapability(@NetworkCapabilities.NetCapability int capability) {
mNetworkCapabilities.addUnwantedCapability(capability);
@@ -439,6 +441,8 @@
/**
* @see Builder#addUnwantedCapability(int)
+ *
+ * @removed
*/
public boolean hasUnwantedCapability(@NetCapability int capability) {
return networkCapabilities.hasUnwantedCapability(capability);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b2a2c60..49fc78f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3133,9 +3133,6 @@
*/
public static final String SCREEN_BRIGHTNESS = "screen_brightness";
- private static final Validator SCREEN_BRIGHTNESS_VALIDATOR =
- new SettingsValidators.InclusiveIntegerRangeValidator(0, 255);
-
/**
* The screen backlight brightness between 0 and 255.
* @hide
@@ -4060,7 +4057,6 @@
FONT_SCALE,
DIM_SCREEN,
SCREEN_OFF_TIMEOUT,
- SCREEN_BRIGHTNESS,
SCREEN_BRIGHTNESS_MODE,
SCREEN_AUTO_BRIGHTNESS_ADJ,
SCREEN_BRIGHTNESS_FOR_VR,
@@ -4230,7 +4226,6 @@
VALIDATORS.put(FONT_SCALE, FONT_SCALE_VALIDATOR);
VALIDATORS.put(DIM_SCREEN, DIM_SCREEN_VALIDATOR);
VALIDATORS.put(SCREEN_OFF_TIMEOUT, SCREEN_OFF_TIMEOUT_VALIDATOR);
- VALIDATORS.put(SCREEN_BRIGHTNESS, SCREEN_BRIGHTNESS_VALIDATOR);
VALIDATORS.put(SCREEN_BRIGHTNESS_FOR_VR, SCREEN_BRIGHTNESS_FOR_VR_VALIDATOR);
VALIDATORS.put(SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_VALIDATOR);
VALIDATORS.put(MODE_RINGER_STREAMS_AFFECTED, MODE_RINGER_STREAMS_AFFECTED_VALIDATOR);
@@ -10806,6 +10801,15 @@
= "time_only_mode_constants";
/**
+ * Whether of not to send keycode sleep for ungaze when Home is the foreground activity on
+ * watch type devices.
+ * Type: int (0 for false, 1 for true)
+ * Default: 0
+ * @hide
+ */
+ public static final String UNGAZE_SLEEP_ENABLED = "ungaze_sleep_enabled";
+
+ /**
* Whether or not Network Watchlist feature is enabled.
* Type: int (0 for false, 1 for true)
* Default: 0
diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java
index 3445658..5256e47 100644
--- a/core/java/android/text/Selection.java
+++ b/core/java/android/text/Selection.java
@@ -180,7 +180,7 @@
* Remove the selection or cursor, if any, from the text.
*/
public static final void removeSelection(Spannable text) {
- text.removeSpan(SELECTION_START);
+ text.removeSpan(SELECTION_START, Spanned.SPAN_INTERMEDIATE);
text.removeSpan(SELECTION_END);
removeMemory(text);
}
diff --git a/core/java/android/text/Spannable.java b/core/java/android/text/Spannable.java
index 39b78eb..8315b2a 100644
--- a/core/java/android/text/Spannable.java
+++ b/core/java/android/text/Spannable.java
@@ -46,6 +46,19 @@
public void removeSpan(Object what);
/**
+ * Remove the specified object from the range of text to which it
+ * was attached, if any. It is OK to remove an object that was never
+ * attached in the first place.
+ *
+ * See {@link Spanned} for an explanation of what the flags mean.
+ *
+ * @hide
+ */
+ default void removeSpan(Object what, int flags) {
+ removeSpan(what);
+ }
+
+ /**
* Factory used by TextView to create new {@link Spannable Spannables}. You can subclass
* it to provide something other than {@link SpannableString}.
*
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index d41dfdc..41a9c45 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -312,7 +312,7 @@
// The following condition indicates that the span would become empty
(textIsRemoved || mSpanStarts[i] > start || mSpanEnds[i] < mGapStart)) {
mIndexOfSpan.remove(mSpans[i]);
- removeSpan(i);
+ removeSpan(i, 0 /* flags */);
return true;
}
return resolveGap(mSpanStarts[i]) <= end && (i & 1) != 0 &&
@@ -472,7 +472,7 @@
}
// Note: caller is responsible for removing the mIndexOfSpan entry.
- private void removeSpan(int i) {
+ private void removeSpan(int i, int flags) {
Object object = mSpans[i];
int start = mSpanStarts[i];
@@ -496,7 +496,9 @@
// Invariants must be restored before sending span removed notifications.
restoreInvariants();
- sendSpanRemoved(object, start, end);
+ if ((flags & Spanned.SPAN_INTERMEDIATE) == 0) {
+ sendSpanRemoved(object, start, end);
+ }
}
// Documentation from interface
@@ -782,10 +784,19 @@
* Remove the specified markup object from the buffer.
*/
public void removeSpan(Object what) {
+ removeSpan(what, 0 /* flags */);
+ }
+
+ /**
+ * Remove the specified markup object from the buffer.
+ *
+ * @hide
+ */
+ public void removeSpan(Object what, int flags) {
if (mIndexOfSpan == null) return;
Integer i = mIndexOfSpan.remove(what);
if (i != null) {
- removeSpan(i.intValue());
+ removeSpan(i.intValue(), flags);
}
}
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index 5dd1a52..bcc2fda 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -249,6 +249,13 @@
}
/* package */ void removeSpan(Object what) {
+ removeSpan(what, 0 /* flags */);
+ }
+
+ /**
+ * @hide
+ */
+ public void removeSpan(Object what, int flags) {
int count = mSpanCount;
Object[] spans = mSpans;
int[] data = mSpanData;
@@ -262,11 +269,13 @@
System.arraycopy(spans, i + 1, spans, i, c);
System.arraycopy(data, (i + 1) * COLUMNS,
- data, i * COLUMNS, c * COLUMNS);
+ data, i * COLUMNS, c * COLUMNS);
mSpanCount--;
- sendSpanRemoved(what, ostart, oend);
+ if ((flags & Spanned.SPAN_INTERMEDIATE) == 0) {
+ sendSpanRemoved(what, ostart, oend);
+ }
return;
}
}
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index b147928..db01cea 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -77,6 +77,55 @@
public static final int TEXT_HANDLE_MOVE = 9;
/**
+ * The user unlocked the device
+ * @hide
+ */
+ public static final int ENTRY_BUMP = 10;
+
+ /**
+ * The user has moved the dragged object within a droppable area.
+ * @hide
+ */
+ public static final int DRAG_CROSSING = 11;
+
+ /**
+ * The user has started a gesture (e.g. on the soft keyboard).
+ * @hide
+ */
+ public static final int GESTURE_START = 12;
+
+ /**
+ * The user has finished a gesture (e.g. on the soft keyboard).
+ * @hide
+ */
+ public static final int GESTURE_END = 13;
+
+ /**
+ * The user's squeeze crossed the gesture's initiation threshold.
+ * @hide
+ */
+ public static final int EDGE_SQUEEZE = 14;
+
+ /**
+ * The user's squeeze crossed the gesture's release threshold.
+ * @hide
+ */
+ public static final int EDGE_RELEASE = 15;
+
+ /**
+ * A haptic effect to signal the confirmation or successful completion of a user
+ * interaction.
+ * @hide
+ */
+ public static final int CONFIRM = 16;
+
+ /**
+ * A haptic effect to signal the rejection or failure of a user interaction.
+ * @hide
+ */
+ public static final int REJECT = 17;
+
+ /**
* The phone has booted with safe mode enabled.
* This is a private constant. Feel free to renumber as desired.
* @hide
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index d4610a5..5deee11 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -87,6 +87,7 @@
private static native void nativeMergeTransaction(long transactionObj,
long otherTransactionObj);
private static native void nativeSetAnimationTransaction(long transactionObj);
+ private static native void nativeSetEarlyWakeup(long transactionObj);
private static native void nativeSetLayer(long transactionObj, long nativeObject, int zorder);
private static native void nativeSetRelativeLayer(long transactionObj, long nativeObject,
@@ -1642,6 +1643,19 @@
}
/**
+ * Indicate that SurfaceFlinger should wake up earlier than usual as a result of this
+ * transaction. This should be used when the caller thinks that the scene is complex enough
+ * that it's likely to hit GL composition, and thus, SurfaceFlinger needs to more time in
+ * order not to miss frame deadlines.
+ * <p>
+ * Corresponds to setting ISurfaceComposer::eEarlyWakeup
+ */
+ public Transaction setEarlyWakeup() {
+ nativeSetEarlyWakeup(mNativeObject);
+ return this;
+ }
+
+ /**
* Merge the other transaction into this transaction, clearing the
* other transaction as if it had been applied.
*/
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 97e11b1..dc58f11 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10398,7 +10398,21 @@
*
* @param willNotCacheDrawing true if this view does not cache its
* drawing, false otherwise
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
}
@@ -10407,8 +10421,22 @@
* Returns whether or not this View can cache its drawing or not.
*
* @return true if this view does not cache its drawing, false otherwise
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
@ViewDebug.ExportedProperty(category = "drawing")
+ @Deprecated
public boolean willNotCacheDrawing() {
return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
}
diff --git a/core/java/android/view/autofill/AutofillPopupWindow.java b/core/java/android/view/autofill/AutofillPopupWindow.java
index 9b49248..a6495d1 100644
--- a/core/java/android/view/autofill/AutofillPopupWindow.java
+++ b/core/java/android/view/autofill/AutofillPopupWindow.java
@@ -79,9 +79,8 @@
public AutofillPopupWindow(@NonNull IAutofillWindowPresenter presenter) {
mWindowPresenter = new WindowPresenter(presenter);
- // Here is a bit of voodoo - we want to show the window as system
- // controlled one so it covers app windows, but at the same time it has to be
- // an application type (so it's contained inside the application area).
+ // We want to show the window as system controlled one so it covers app windows, but it has
+ // to be an application type (so it's contained inside the application area).
// Hence, we set it to the application type with the highest z-order, which currently
// is TYPE_APPLICATION_ABOVE_SUB_PANEL.
setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 5f7a0f7..090e19f 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -522,7 +522,7 @@
b = tmp;
}
- if (a == b) return null;
+ if (a == b || a < 0) return null;
if ((flags&GET_TEXT_WITH_STYLES) != 0) {
return content.subSequence(a, b);
diff --git a/core/java/android/view/textclassifier/GenerateLinksLogger.java b/core/java/android/view/textclassifier/GenerateLinksLogger.java
index 73cf43b..067513f 100644
--- a/core/java/android/view/textclassifier/GenerateLinksLogger.java
+++ b/core/java/android/view/textclassifier/GenerateLinksLogger.java
@@ -19,13 +19,13 @@
import android.annotation.Nullable;
import android.metrics.LogMaker;
import android.util.ArrayMap;
-import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.Preconditions;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
@@ -39,6 +39,7 @@
public final class GenerateLinksLogger {
private static final String LOG_TAG = "GenerateLinksLogger";
+ private static final boolean DEBUG_LOG_ENABLED = false;
private static final String ZERO = "0";
private final MetricsLogger mMetricsLogger;
@@ -127,7 +128,7 @@
}
private static void debugLog(LogMaker log) {
- if (!Logger.DEBUG_LOG_ENABLED) return;
+ if (!DEBUG_LOG_ENABLED) return;
final String callId = Objects.toString(
log.getTaggedData(MetricsEvent.FIELD_LINKIFY_CALL_ID), "");
@@ -142,8 +143,9 @@
final int latencyMs = Integer.parseInt(
Objects.toString(log.getTaggedData(MetricsEvent.FIELD_LINKIFY_LATENCY), ZERO));
- Log.d(LOG_TAG, String.format("%s:%s %d links (%d/%d chars) %dms %s", callId, entityType,
- numLinks, linkLength, textLength, latencyMs, log.getPackageName()));
+ Log.d(LOG_TAG,
+ String.format(Locale.US, "%s:%s %d links (%d/%d chars) %dms %s", callId, entityType,
+ numLinks, linkLength, textLength, latencyMs, log.getPackageName()));
}
/** Helper class for storing per-entity type statistics. */
diff --git a/core/java/android/view/textclassifier/Logger.java b/core/java/android/view/textclassifier/Logger.java
deleted file mode 100644
index f03906a..0000000
--- a/core/java/android/view/textclassifier/Logger.java
+++ /dev/null
@@ -1,397 +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.view.textclassifier;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-
-import com.android.internal.util.Preconditions;
-
-import java.text.BreakIterator;
-import java.util.Locale;
-import java.util.Objects;
-
-/**
- * A helper for logging TextClassifier related events.
- * @hide
- */
-public abstract class Logger {
-
- private static final String LOG_TAG = "Logger";
- /* package */ static final boolean DEBUG_LOG_ENABLED = true;
-
- private @SelectionEvent.InvocationMethod int mInvocationMethod;
- private SelectionEvent mPrevEvent;
- private SelectionEvent mSmartEvent;
- private SelectionEvent mStartEvent;
-
- /**
- * Logger that does not log anything.
- * @hide
- */
- public static final Logger DISABLED = new Logger() {
- @Override
- public void writeEvent(SelectionEvent event) {}
- };
-
- @Nullable
- private final Config mConfig;
-
- public Logger(Config config) {
- mConfig = Preconditions.checkNotNull(config);
- }
-
- private Logger() {
- mConfig = null;
- }
-
- /**
- * Writes the selection event to a log.
- */
- public abstract void writeEvent(@NonNull SelectionEvent event);
-
- /**
- * Returns true if the resultId matches that of a smart selection event (i.e.
- * {@link SelectionEvent#EVENT_SMART_SELECTION_SINGLE} or
- * {@link SelectionEvent#EVENT_SMART_SELECTION_MULTI}).
- * Returns false otherwise.
- */
- public boolean isSmartSelection(@NonNull String resultId) {
- return false;
- }
-
- /**
- * Returns a token iterator for tokenizing text for logging purposes.
- */
- public BreakIterator getTokenIterator(@NonNull Locale locale) {
- return BreakIterator.getWordInstance(Preconditions.checkNotNull(locale));
- }
-
- /**
- * Logs a "selection started" event.
- *
- * @param invocationMethod the way the selection was triggered
- * @param start the token index of the selected token
- */
- public final void logSelectionStartedEvent(
- @SelectionEvent.InvocationMethod int invocationMethod, int start) {
- if (mConfig == null) {
- return;
- }
-
- mInvocationMethod = invocationMethod;
- logEvent(new SelectionEvent(
- start, start + 1, SelectionEvent.EVENT_SELECTION_STARTED,
- TextClassifier.TYPE_UNKNOWN, mInvocationMethod, null, mConfig));
- }
-
- /**
- * Logs a "selection modified" event.
- * Use when the user modifies the selection.
- *
- * @param start the start token (inclusive) index of the selection
- * @param end the end token (exclusive) index of the selection
- */
- public final void logSelectionModifiedEvent(int start, int end) {
- Preconditions.checkArgument(end >= start, "end cannot be less than start");
-
- if (mConfig == null) {
- return;
- }
-
- logEvent(new SelectionEvent(
- start, end, SelectionEvent.EVENT_SELECTION_MODIFIED,
- TextClassifier.TYPE_UNKNOWN, mInvocationMethod, null, mConfig));
- }
-
- /**
- * Logs a "selection modified" event.
- * Use when the user modifies the selection and the selection's entity type is known.
- *
- * @param start the start token (inclusive) index of the selection
- * @param end the end token (exclusive) index of the selection
- * @param classification the TextClassification object returned by the TextClassifier that
- * classified the selected text
- */
- public final void logSelectionModifiedEvent(
- int start, int end, @NonNull TextClassification classification) {
- Preconditions.checkArgument(end >= start, "end cannot be less than start");
- Preconditions.checkNotNull(classification);
-
- if (mConfig == null) {
- return;
- }
-
- final String entityType = classification.getEntityCount() > 0
- ? classification.getEntity(0)
- : TextClassifier.TYPE_UNKNOWN;
- logEvent(new SelectionEvent(
- start, end, SelectionEvent.EVENT_SELECTION_MODIFIED,
- entityType, mInvocationMethod, classification.getId(), mConfig));
- }
-
- /**
- * Logs a "selection modified" event.
- * Use when a TextClassifier modifies the selection.
- *
- * @param start the start token (inclusive) index of the selection
- * @param end the end token (exclusive) index of the selection
- * @param selection the TextSelection object returned by the TextClassifier for the
- * specified selection
- */
- public final void logSelectionModifiedEvent(
- int start, int end, @NonNull TextSelection selection) {
- Preconditions.checkArgument(end >= start, "end cannot be less than start");
- Preconditions.checkNotNull(selection);
-
- if (mConfig == null) {
- return;
- }
-
- final int eventType;
- if (isSmartSelection(selection.getId())) {
- eventType = end - start > 1
- ? SelectionEvent.EVENT_SMART_SELECTION_MULTI
- : SelectionEvent.EVENT_SMART_SELECTION_SINGLE;
-
- } else {
- eventType = SelectionEvent.EVENT_AUTO_SELECTION;
- }
- final String entityType = selection.getEntityCount() > 0
- ? selection.getEntity(0)
- : TextClassifier.TYPE_UNKNOWN;
- logEvent(new SelectionEvent(start, end, eventType, entityType, mInvocationMethod,
- selection.getId(), mConfig));
- }
-
- /**
- * Logs an event specifying an action taken on a selection.
- * Use when the user clicks on an action to act on the selected text.
- *
- * @param start the start token (inclusive) index of the selection
- * @param end the end token (exclusive) index of the selection
- * @param actionType the action that was performed on the selection
- */
- public final void logSelectionActionEvent(
- int start, int end, @SelectionEvent.ActionType int actionType) {
- Preconditions.checkArgument(end >= start, "end cannot be less than start");
- checkActionType(actionType);
-
- if (mConfig == null) {
- return;
- }
-
- logEvent(new SelectionEvent(
- start, end, actionType, TextClassifier.TYPE_UNKNOWN, mInvocationMethod,
- null, mConfig));
- }
-
- /**
- * Logs an event specifying an action taken on a selection.
- * Use when the user clicks on an action to act on the selected text and the selection's
- * entity type is known.
- *
- * @param start the start token (inclusive) index of the selection
- * @param end the end token (exclusive) index of the selection
- * @param actionType the action that was performed on the selection
- * @param classification the TextClassification object returned by the TextClassifier that
- * classified the selected text
- *
- * @throws IllegalArgumentException If actionType is not a valid SelectionEvent actionType
- */
- public final void logSelectionActionEvent(
- int start, int end, @SelectionEvent.ActionType int actionType,
- @NonNull TextClassification classification) {
- Preconditions.checkArgument(end >= start, "end cannot be less than start");
- Preconditions.checkNotNull(classification);
- checkActionType(actionType);
-
- if (mConfig == null) {
- return;
- }
-
- final String entityType = classification.getEntityCount() > 0
- ? classification.getEntity(0)
- : TextClassifier.TYPE_UNKNOWN;
- logEvent(new SelectionEvent(start, end, actionType, entityType, mInvocationMethod,
- classification.getId(), mConfig));
- }
-
- private void logEvent(@NonNull SelectionEvent event) {
- Preconditions.checkNotNull(event);
-
- if (event.getEventType() != SelectionEvent.EVENT_SELECTION_STARTED
- && mStartEvent == null) {
- if (DEBUG_LOG_ENABLED) {
- Log.d(LOG_TAG, "Selection session not yet started. Ignoring event");
- }
- return;
- }
-
- final long now = System.currentTimeMillis();
- switch (event.getEventType()) {
- case SelectionEvent.EVENT_SELECTION_STARTED:
- Preconditions.checkArgument(event.getAbsoluteEnd() == event.getAbsoluteStart() + 1);
- event.setSessionId(startNewSession());
- mStartEvent = event;
- break;
- case SelectionEvent.EVENT_SMART_SELECTION_SINGLE: // fall through
- case SelectionEvent.EVENT_SMART_SELECTION_MULTI:
- mSmartEvent = event;
- break;
- case SelectionEvent.EVENT_SELECTION_MODIFIED: // fall through
- case SelectionEvent.EVENT_AUTO_SELECTION:
- if (mPrevEvent != null
- && mPrevEvent.getAbsoluteStart() == event.getAbsoluteStart()
- && mPrevEvent.getAbsoluteEnd() == event.getAbsoluteEnd()) {
- // Selection did not change. Ignore event.
- return;
- }
- break;
- default:
- // do nothing.
- }
-
- event.setEventTime(now);
- if (mStartEvent != null) {
- event.setSessionId(mStartEvent.getSessionId())
- .setDurationSinceSessionStart(now - mStartEvent.getEventTime())
- .setStart(event.getAbsoluteStart() - mStartEvent.getAbsoluteStart())
- .setEnd(event.getAbsoluteEnd() - mStartEvent.getAbsoluteStart());
- }
- if (mSmartEvent != null) {
- event.setResultId(mSmartEvent.getResultId())
- .setSmartStart(mSmartEvent.getAbsoluteStart() - mStartEvent.getAbsoluteStart())
- .setSmartEnd(mSmartEvent.getAbsoluteEnd() - mStartEvent.getAbsoluteStart());
- }
- if (mPrevEvent != null) {
- event.setDurationSincePreviousEvent(now - mPrevEvent.getEventTime())
- .setEventIndex(mPrevEvent.getEventIndex() + 1);
- }
- writeEvent(event);
- mPrevEvent = event;
-
- if (event.isTerminal()) {
- endSession();
- }
- }
-
- private TextClassificationSessionId startNewSession() {
- endSession();
- return new TextClassificationSessionId();
- }
-
- private void endSession() {
- mPrevEvent = null;
- mSmartEvent = null;
- mStartEvent = null;
- }
-
- /**
- * @throws IllegalArgumentException If eventType is not an {@link SelectionEvent.ActionType}
- */
- private static void checkActionType(@SelectionEvent.EventType int eventType)
- throws IllegalArgumentException {
- switch (eventType) {
- case SelectionEvent.ACTION_OVERTYPE: // fall through
- case SelectionEvent.ACTION_COPY: // fall through
- case SelectionEvent.ACTION_PASTE: // fall through
- case SelectionEvent.ACTION_CUT: // fall through
- case SelectionEvent.ACTION_SHARE: // fall through
- case SelectionEvent.ACTION_SMART_SHARE: // fall through
- case SelectionEvent.ACTION_DRAG: // fall through
- case SelectionEvent.ACTION_ABANDON: // fall through
- case SelectionEvent.ACTION_SELECT_ALL: // fall through
- case SelectionEvent.ACTION_RESET: // fall through
- return;
- default:
- throw new IllegalArgumentException(
- String.format(Locale.US, "%d is not an eventType", eventType));
- }
- }
-
-
- /**
- * A Logger config.
- */
- public static final class Config {
-
- private final String mPackageName;
- private final String mWidgetType;
- @Nullable private final String mWidgetVersion;
-
- /**
- * @param context Context of the widget the logger logs for
- * @param widgetType a name for the widget being logged for. e.g.
- * {@link TextClassifier#WIDGET_TYPE_TEXTVIEW}
- * @param widgetVersion a string version info for the widget the logger logs for
- */
- public Config(
- @NonNull Context context,
- @TextClassifier.WidgetType String widgetType,
- @Nullable String widgetVersion) {
- mPackageName = Preconditions.checkNotNull(context).getPackageName();
- mWidgetType = widgetType;
- mWidgetVersion = widgetVersion;
- }
-
- /**
- * Returns the package name of the application the logger logs for.
- */
- public String getPackageName() {
- return mPackageName;
- }
-
- /**
- * Returns the name for the widget being logged for. e.g.
- * {@link TextClassifier#WIDGET_TYPE_TEXTVIEW}.
- */
- public String getWidgetType() {
- return mWidgetType;
- }
-
- /**
- * Returns string version info for the logger. This is specific to the text classifier.
- */
- @Nullable
- public String getWidgetVersion() {
- return mWidgetVersion;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mPackageName, mWidgetType, mWidgetVersion);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- }
-
- if (!(obj instanceof Config)) {
- return false;
- }
-
- final Config other = (Config) obj;
- return Objects.equals(mPackageName, other.mPackageName)
- && Objects.equals(mWidgetType, other.mWidgetType)
- && Objects.equals(mWidgetVersion, other.mWidgetType);
- }
- }
-}
diff --git a/core/java/android/view/textclassifier/SelectionEvent.java b/core/java/android/view/textclassifier/SelectionEvent.java
index 1e978cc..ceab78a 100644
--- a/core/java/android/view/textclassifier/SelectionEvent.java
+++ b/core/java/android/view/textclassifier/SelectionEvent.java
@@ -150,20 +150,6 @@
mInvocationMethod = invocationMethod;
}
- SelectionEvent(
- int start, int end,
- @EventType int eventType, @EntityType String entityType,
- @InvocationMethod int invocationMethod, @Nullable String resultId,
- Logger.Config config) {
- this(start, end, eventType, entityType, invocationMethod, resultId);
- Preconditions.checkNotNull(config);
- setTextClassificationSessionContext(
- new TextClassificationContext.Builder(
- config.getPackageName(), config.getWidgetType())
- .setWidgetVersion(config.getWidgetVersion())
- .build());
- }
-
private SelectionEvent(Parcel in) {
mAbsoluteStart = in.readInt();
mAbsoluteEnd = in.readInt();
diff --git a/core/java/android/view/textclassifier/DefaultLogger.java b/core/java/android/view/textclassifier/SelectionSessionLogger.java
similarity index 88%
rename from core/java/android/view/textclassifier/DefaultLogger.java
rename to core/java/android/view/textclassifier/SelectionSessionLogger.java
index 203ca56..f2fb63e 100644
--- a/core/java/android/view/textclassifier/DefaultLogger.java
+++ b/core/java/android/view/textclassifier/SelectionSessionLogger.java
@@ -17,28 +17,29 @@
package android.view.textclassifier;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.metrics.LogMaker;
-import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.Preconditions;
+import java.text.BreakIterator;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.StringJoiner;
/**
- * Default Logger.
- * Used internally by TextClassifierImpl.
+ * A helper for logging selection session events.
* @hide
*/
-public final class DefaultLogger extends Logger {
+public final class SelectionSessionLogger {
- private static final String LOG_TAG = "DefaultLogger";
+ private static final String LOG_TAG = "SelectionSessionLogger";
+ private static final boolean DEBUG_LOG_ENABLED = false;
static final String CLASSIFIER_ID = "androidtc";
private static final int START_EVENT_DELTA = MetricsEvent.FIELD_SELECTION_SINCE_START;
@@ -59,23 +60,16 @@
private final MetricsLogger mMetricsLogger;
- public DefaultLogger(@NonNull Config config) {
- super(config);
+ public SelectionSessionLogger() {
mMetricsLogger = new MetricsLogger();
}
@VisibleForTesting
- public DefaultLogger(@NonNull Config config, @NonNull MetricsLogger metricsLogger) {
- super(config);
+ public SelectionSessionLogger(@NonNull MetricsLogger metricsLogger) {
mMetricsLogger = Preconditions.checkNotNull(metricsLogger);
}
- @Override
- public boolean isSmartSelection(@NonNull String signature) {
- return CLASSIFIER_ID.equals(SignatureParser.getClassifierId(signature));
- }
-
- @Override
+ /** Emits a selection event to the logs. */
public void writeEvent(@NonNull SelectionEvent event) {
Preconditions.checkNotNull(event);
final LogMaker log = new LogMaker(MetricsEvent.TEXT_SELECTION_SESSION)
@@ -93,7 +87,7 @@
.addTaggedData(SMART_END, event.getSmartEnd())
.addTaggedData(EVENT_START, event.getStart())
.addTaggedData(EVENT_END, event.getEnd())
- .addTaggedData(SESSION_ID, event.getSessionId());
+ .addTaggedData(SESSION_ID, event.getSessionId().flattenToString());
mMetricsLogger.write(log);
debugLog(log);
}
@@ -225,9 +219,17 @@
final int eventEnd = Integer.parseInt(
Objects.toString(log.getTaggedData(EVENT_END), ZERO));
- Log.d(LOG_TAG, String.format("%2d: %s/%s/%s, range=%d,%d - smart_range=%d,%d (%s/%s)",
- index, type, subType, entity, eventStart, eventEnd, smartStart, smartEnd, widget,
- model));
+ Log.d(LOG_TAG,
+ String.format(Locale.US, "%2d: %s/%s/%s, range=%d,%d - smart_range=%d,%d (%s/%s)",
+ index, type, subType, entity, eventStart, eventEnd, smartStart, smartEnd,
+ widget, model));
+ }
+
+ /**
+ * Returns a token iterator for tokenizing text for logging purposes.
+ */
+ public static BreakIterator getTokenIterator(@NonNull Locale locale) {
+ return BreakIterator.getWordInstance(Preconditions.checkNotNull(locale));
}
/**
@@ -260,8 +262,10 @@
return String.format(Locale.US, "%s|%s|%d", classifierId, modelName, hash);
}
- static String getClassifierId(String signature) {
- Preconditions.checkNotNull(signature);
+ static String getClassifierId(@Nullable String signature) {
+ if (signature == null) {
+ return "";
+ }
final int end = signature.indexOf("|");
if (end >= 0) {
return signature.substring(0, end);
@@ -269,8 +273,10 @@
return "";
}
- static String getModelName(String signature) {
- Preconditions.checkNotNull(signature);
+ static String getModelName(@Nullable String signature) {
+ if (signature == null) {
+ return "";
+ }
final int start = signature.indexOf("|") + 1;
final int end = signature.indexOf("|", start);
if (start >= 1 && end >= start) {
@@ -279,8 +285,10 @@
return "";
}
- static int getHash(String signature) {
- Preconditions.checkNotNull(signature);
+ static int getHash(@Nullable String signature) {
+ if (signature == null) {
+ return 0;
+ }
final int index1 = signature.indexOf("|");
final int index2 = signature.indexOf("|", index1);
if (index2 > 0) {
diff --git a/core/java/android/view/textclassifier/SystemTextClassifier.java b/core/java/android/view/textclassifier/SystemTextClassifier.java
index 45fd6bf..490c389 100644
--- a/core/java/android/view/textclassifier/SystemTextClassifier.java
+++ b/core/java/android/view/textclassifier/SystemTextClassifier.java
@@ -28,7 +28,6 @@
import android.service.textclassifier.ITextLinksCallback;
import android.service.textclassifier.ITextSelectionCallback;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
import com.android.internal.util.Preconditions;
@@ -49,13 +48,6 @@
private final TextClassificationConstants mSettings;
private final TextClassifier mFallback;
private final String mPackageName;
-
- private final Object mLoggerLock = new Object();
- @GuardedBy("mLoggerLock")
- private Logger.Config mLoggerConfig;
- @GuardedBy("mLoggerLock")
- private Logger mLogger;
- @GuardedBy("mLoggerLock")
private TextClassificationSessionId mSessionId;
public SystemTextClassifier(Context context, TextClassificationConstants settings)
@@ -147,27 +139,6 @@
}
@Override
- public Logger getLogger(@NonNull Logger.Config config) {
- Preconditions.checkNotNull(config);
- synchronized (mLoggerLock) {
- if (mLogger == null || !config.equals(mLoggerConfig)) {
- mLoggerConfig = config;
- mLogger = new Logger(config) {
- @Override
- public void writeEvent(SelectionEvent event) {
- try {
- mManagerService.onSelectionEvent(mSessionId, event);
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Error reporting selection event.", e);
- }
- }
- };
- }
- }
- return mLogger;
- }
-
- @Override
public void destroy() {
try {
if (mSessionId != null) {
diff --git a/core/java/android/view/textclassifier/TextClassificationSession.java b/core/java/android/view/textclassifier/TextClassificationSession.java
index e8e300a..4c64198 100644
--- a/core/java/android/view/textclassifier/TextClassificationSession.java
+++ b/core/java/android/view/textclassifier/TextClassificationSession.java
@@ -17,7 +17,6 @@
package android.view.textclassifier;
import android.annotation.WorkerThread;
-import android.view.textclassifier.DefaultLogger.SignatureParser;
import android.view.textclassifier.SelectionEvent.InvocationMethod;
import com.android.internal.util.Preconditions;
@@ -222,7 +221,8 @@
}
private static boolean isPlatformLocalTextClassifierSmartSelection(String signature) {
- return DefaultLogger.CLASSIFIER_ID.equals(SignatureParser.getClassifierId(signature));
+ return SelectionSessionLogger.CLASSIFIER_ID.equals(
+ SelectionSessionLogger.SignatureParser.getClassifierId(signature));
}
}
}
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index f048d29..da47bcb 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -359,18 +359,6 @@
}
/**
- * Returns a helper for logging TextClassifier related events.
- *
- * @param config logger configuration
- * @hide
- */
- @WorkerThread
- default Logger getLogger(@NonNull Logger.Config config) {
- Preconditions.checkNotNull(config);
- return Logger.DISABLED;
- }
-
- /**
* Reports a selection event.
*
* <strong>NOTE: </strong>If a TextClassifier has been destroyed, calls to this method should
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 7e3748a..2213355 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -94,11 +94,7 @@
private final Object mLoggerLock = new Object();
@GuardedBy("mLoggerLock") // Do not access outside this lock.
- private Logger.Config mLoggerConfig;
- @GuardedBy("mLoggerLock") // Do not access outside this lock.
- private Logger mLogger;
- @GuardedBy("mLoggerLock") // Do not access outside this lock.
- private Logger mLogger2; // This is the new logger. Will replace mLogger.
+ private SelectionSessionLogger mSessionLogger;
private final TextClassificationConstants mSettings;
@@ -283,28 +279,14 @@
}
}
- /** @inheritDoc */
- @Override
- public Logger getLogger(@NonNull Logger.Config config) {
- Preconditions.checkNotNull(config);
- synchronized (mLoggerLock) {
- if (mLogger == null || !config.equals(mLoggerConfig)) {
- mLoggerConfig = config;
- mLogger = new DefaultLogger(config);
- }
- }
- return mLogger;
- }
-
@Override
public void onSelectionEvent(SelectionEvent event) {
Preconditions.checkNotNull(event);
synchronized (mLoggerLock) {
- if (mLogger2 == null) {
- mLogger2 = new DefaultLogger(
- new Logger.Config(mContext, WIDGET_TYPE_UNKNOWN, null));
+ if (mSessionLogger == null) {
+ mSessionLogger = new SelectionSessionLogger();
}
- mLogger2.writeEvent(event);
+ mSessionLogger.writeEvent(event);
}
}
@@ -331,7 +313,7 @@
private String createId(String text, int start, int end) {
synchronized (mLock) {
- return DefaultLogger.createId(text, start, end, mContext, mModel.getVersion(),
+ return SelectionSessionLogger.createId(text, start, end, mContext, mModel.getVersion(),
mModel.getSupportedLocales());
}
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 9946726..6af678b 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -6031,7 +6031,9 @@
mSwitchedLines = false;
final int selectionStart = mTextView.getSelectionStart();
final int selectionEnd = mTextView.getSelectionEnd();
- if (selectionStart > selectionEnd) {
+ if (selectionStart < 0 || selectionEnd < 0) {
+ Selection.removeSelection((Spannable) mTextView.getText());
+ } else if (selectionStart > selectionEnd) {
Selection.setSelection((Spannable) mTextView.getText(),
selectionEnd, selectionStart);
}
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 4b951fa..1372987 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -817,8 +817,6 @@
if (mScaleType != scaleType) {
mScaleType = scaleType;
- setWillNotCacheDrawing(mScaleType == ScaleType.CENTER);
-
requestLayout();
invalidate();
}
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index b3327a7..468abdc 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -33,9 +33,9 @@
import android.text.TextUtils;
import android.util.Log;
import android.view.ActionMode;
-import android.view.textclassifier.Logger;
import android.view.textclassifier.SelectionEvent;
import android.view.textclassifier.SelectionEvent.InvocationMethod;
+import android.view.textclassifier.SelectionSessionLogger;
import android.view.textclassifier.TextClassification;
import android.view.textclassifier.TextClassificationConstants;
import android.view.textclassifier.TextClassificationManager;
@@ -663,7 +663,6 @@
private static final String LOG_TAG = "SelectionMetricsLogger";
private static final Pattern PATTERN_WHITESPACE = Pattern.compile("\\s+");
- private final Logger mLogger;
private final boolean mEditTextLogger;
private final BreakIterator mTokenIterator;
@@ -673,10 +672,8 @@
SelectionMetricsLogger(TextView textView) {
Preconditions.checkNotNull(textView);
- mLogger = textView.getTextClassifier().getLogger(
- new Logger.Config(textView.getContext(), getWidetType(textView), null));
mEditTextLogger = textView.isTextEditable();
- mTokenIterator = mLogger.getTokenIterator(textView.getTextLocale());
+ mTokenIterator = SelectionSessionLogger.getTokenIterator(textView.getTextLocale());
}
@TextClassifier.WidgetType
@@ -702,8 +699,6 @@
}
mTokenIterator.setText(mText);
mStartIndex = index;
- mLogger.logSelectionStartedEvent(invocationMethod, 0);
- // TODO: Remove the above legacy logging.
mClassificationSession = classificationSession;
mClassificationSession.onSelectionEvent(
SelectionEvent.createSelectionStartedEvent(invocationMethod, 0));
@@ -720,27 +715,18 @@
Preconditions.checkArgumentInRange(end, start, mText.length(), "end");
int[] wordIndices = getWordDelta(start, end);
if (selection != null) {
- mLogger.logSelectionModifiedEvent(
- wordIndices[0], wordIndices[1], selection);
- // TODO: Remove the above legacy logging.
if (mClassificationSession != null) {
mClassificationSession.onSelectionEvent(
SelectionEvent.createSelectionModifiedEvent(
wordIndices[0], wordIndices[1], selection));
}
} else if (classification != null) {
- mLogger.logSelectionModifiedEvent(
- wordIndices[0], wordIndices[1], classification);
- // TODO: Remove the above legacy logging.
if (mClassificationSession != null) {
mClassificationSession.onSelectionEvent(
SelectionEvent.createSelectionModifiedEvent(
wordIndices[0], wordIndices[1], classification));
}
} else {
- mLogger.logSelectionModifiedEvent(
- wordIndices[0], wordIndices[1]);
- // TODO: Remove the above legacy logging.
if (mClassificationSession != null) {
mClassificationSession.onSelectionEvent(
SelectionEvent.createSelectionModifiedEvent(
@@ -762,18 +748,12 @@
Preconditions.checkArgumentInRange(end, start, mText.length(), "end");
int[] wordIndices = getWordDelta(start, end);
if (classification != null) {
- mLogger.logSelectionActionEvent(
- wordIndices[0], wordIndices[1], action, classification);
- // TODO: Remove the above legacy logging.
if (mClassificationSession != null) {
mClassificationSession.onSelectionEvent(
SelectionEvent.createSelectionActionEvent(
wordIndices[0], wordIndices[1], action, classification));
}
} else {
- mLogger.logSelectionActionEvent(
- wordIndices[0], wordIndices[1], action);
- // TODO: Remove the above legacy logging.
if (mClassificationSession != null) {
mClassificationSession.onSelectionEvent(
SelectionEvent.createSelectionActionEvent(
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 11db6b6..fae6db5d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9380,7 +9380,7 @@
final int selectionStart = getSelectionStart();
final int selectionEnd = getSelectionEnd();
- return selectionStart >= 0 && selectionStart != selectionEnd;
+ return selectionStart >= 0 && selectionEnd > 0 && selectionStart != selectionEnd;
}
String getSelectedText() {
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index 1e5bd18..b49aace 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -657,7 +657,7 @@
* {@link #removeHiddenBatterySippers(List)}.
*/
private void addAmbientDisplayUsage() {
- long ambientDisplayMs = mStats.getScreenDozeTime(mRawRealtimeUs, mStatsType);
+ long ambientDisplayMs = mStats.getScreenDozeTime(mRawRealtimeUs, mStatsType) / 1000;
double power = mPowerProfile.getAveragePower(PowerProfile.POWER_AMBIENT_DISPLAY)
* ambientDisplayMs / (60 * 60 * 1000);
if (power > 0) {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index b0f68cd..3f58afa 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -327,6 +327,11 @@
transaction->setAnimationTransaction();
}
+static void nativeSetEarlyWakeup(JNIEnv* env, jclass clazz, jlong transactionObj) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->setEarlyWakeup();
+}
+
static void nativeSetLayer(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jint zorder) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -934,6 +939,8 @@
(void*)nativeMergeTransaction },
{"nativeSetAnimationTransaction", "(J)V",
(void*)nativeSetAnimationTransaction },
+ {"nativeSetEarlyWakeup", "(J)V",
+ (void*)nativeSetEarlyWakeup },
{"nativeSetLayer", "(JJI)V",
(void*)nativeSetLayer },
{"nativeSetRelativeLayer", "(JJLandroid/os/IBinder;I)V",
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 2a7c256..ab15d4f 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -118,17 +118,17 @@
// Stack dumps
optional android.os.BackTraceProto native_traces = 1200 [
- (section).type = SECTION_NONE,
+ (section).type = SECTION_TOMBSTONE,
(section).args = "native"
];
optional android.os.BackTraceProto hal_traces = 1201 [
- (section).type = SECTION_NONE,
+ (section).type = SECTION_TOMBSTONE,
(section).args = "hal"
];
optional android.os.BackTraceProto java_traces = 1202 [
- (section).type = SECTION_NONE,
+ (section).type = SECTION_TOMBSTONE,
(section).args = "java"
];
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index b1936b9..e27458f 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -72,6 +72,7 @@
Settings.System.NOTIFICATION_SOUND_CACHE, // internal cache
Settings.System.POINTER_LOCATION, // backup candidate?
Settings.System.RINGTONE_CACHE, // internal cache
+ Settings.System.SCREEN_BRIGHTNESS, // removed in P
Settings.System.SETUP_WIZARD_HAS_RUN, // Only used by SuW
Settings.System.SHOW_GTALK_SERVICE_STATUS, // candidate for backup?
Settings.System.SHOW_TOUCHES, // bug?
@@ -411,6 +412,7 @@
Settings.Global.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
Settings.Global.UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD,
Settings.Global.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD,
+ Settings.Global.UNGAZE_SLEEP_ENABLED,
Settings.Global.UNLOCK_SOUND,
Settings.Global.USE_GOOGLE_MAIL,
Settings.Global.VT_IMS_ENABLED,
diff --git a/core/tests/coretests/src/android/text/SpannableTest.java b/core/tests/coretests/src/android/text/SpannableTest.java
index 307ac62..f368428 100644
--- a/core/tests/coretests/src/android/text/SpannableTest.java
+++ b/core/tests/coretests/src/android/text/SpannableTest.java
@@ -16,6 +16,8 @@
package android.text;
+import static org.junit.Assert.assertEquals;
+
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -24,6 +26,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.concurrent.CountDownLatch;
+
@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -53,4 +57,34 @@
spans = spannable.getSpans(2, 2, Object.class);
MoreAsserts.assertEquals(new Object[]{unemptySpan}, spans);
}
+
+ @Test
+ public void testRemoveSpanWithIntermediateFlag() {
+ Spannable spannable = newSpannableWithText("abcdef");
+ Object emptySpan = new Object();
+ spannable.setSpan(emptySpan, 1, 1, 0);
+ Object unemptySpan = new Object();
+ spannable.setSpan(unemptySpan, 1, 2, 0);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ SpanWatcher watcher = new SpanWatcher() {
+ @Override
+ public void onSpanAdded(Spannable text, Object what, int start, int end) {}
+
+ @Override
+ public void onSpanRemoved(Spannable text, Object what, int start, int end) {
+ latch.countDown();
+ }
+
+ @Override
+ public void onSpanChanged(Spannable text, Object what, int ostart, int oend, int nstart,
+ int nend) {}
+ };
+ spannable.setSpan(watcher, 0, 2, 0);
+
+ spannable.removeSpan(emptySpan, Spanned.SPAN_INTERMEDIATE);
+ assertEquals(1, latch.getCount());
+ spannable.removeSpan(unemptySpan);
+ assertEquals(0, latch.getCount());
+ }
}
diff --git a/core/tests/coretests/src/android/view/textclassifier/SelectionEventTest.java b/core/tests/coretests/src/android/view/textclassifier/SelectionEventTest.java
index 861a43a..3e4c85f 100644
--- a/core/tests/coretests/src/android/view/textclassifier/SelectionEventTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/SelectionEventTest.java
@@ -19,7 +19,6 @@
import static org.junit.Assert.assertEquals;
import android.os.Parcel;
-import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -32,19 +31,8 @@
@Test
public void testParcel() {
- final SelectionEvent[] captured = new SelectionEvent[1];
- final Logger logger = new Logger(
- new Logger.Config(
- InstrumentationRegistry.getTargetContext(),
- TextClassifier.WIDGET_TYPE_TEXTVIEW,
- null)) {
- @Override
- public void writeEvent(SelectionEvent event) {
- captured[0] = event;
- }
- };
- logger.logSelectionStartedEvent(SelectionEvent.INVOCATION_MANUAL, 0);
- final SelectionEvent event = captured[0];
+ final SelectionEvent event = SelectionEvent.createSelectionStartedEvent(
+ SelectionEvent.INVOCATION_MANUAL, 0);
final Parcel parcel = Parcel.obtain();
event.writeToParcel(parcel, event.describeContents());
parcel.setDataPosition(0);
diff --git a/libs/hwui/ProfileData.cpp b/libs/hwui/ProfileData.cpp
index f9cf549..1696661 100644
--- a/libs/hwui/ProfileData.cpp
+++ b/libs/hwui/ProfileData.cpp
@@ -104,7 +104,8 @@
dprintf(fd, "\nStats since: %" PRIu64 "ns", mStatStartTime);
dprintf(fd, "\nTotal frames rendered: %u", mTotalFrameCount);
dprintf(fd, "\nJanky frames: %u (%.2f%%)", mJankFrameCount,
- (float)mJankFrameCount / (float)mTotalFrameCount * 100.0f);
+ mTotalFrameCount == 0 ? 0.0f :
+ (float)mJankFrameCount / (float)mTotalFrameCount * 100.0f);
dprintf(fd, "\n50th percentile: %ums", findPercentile(50));
dprintf(fd, "\n90th percentile: %ums", findPercentile(90));
dprintf(fd, "\n95th percentile: %ums", findPercentile(95));
diff --git a/media/java/android/media/AudioFocusRequest.java b/media/java/android/media/AudioFocusRequest.java
index 7104dad..fe89b89 100644
--- a/media/java/android/media/AudioFocusRequest.java
+++ b/media/java/android/media/AudioFocusRequest.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.media.AudioManager.OnAudioFocusChangeListener;
import android.os.Bundle;
import android.os.Handler;
@@ -262,6 +263,7 @@
* Returns the focus change listener set for this {@code AudioFocusRequest}.
* @return null if no {@link AudioManager.OnAudioFocusChangeListener} was set.
*/
+ @TestApi
public @Nullable OnAudioFocusChangeListener getOnAudioFocusChangeListener() {
return mFocusListener;
}
diff --git a/media/java/android/media/AudioPresentation.java b/media/java/android/media/AudioPresentation.java
index e39cb7d..ce71436 100644
--- a/media/java/android/media/AudioPresentation.java
+++ b/media/java/android/media/AudioPresentation.java
@@ -18,8 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-
-import com.android.internal.annotations.VisibleForTesting;
+import android.annotation.TestApi;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -94,7 +93,7 @@
/**
* @hide
*/
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ @TestApi
public AudioPresentation(int presentationId,
int programId,
@NonNull Map<String, String> labels,
@@ -119,7 +118,7 @@
* decoder. Presentation id is typically sequential, but does not have to be.
* @hide
*/
- @VisibleForTesting
+ @TestApi
public int getPresentationId() {
return mPresentationId;
}
@@ -129,7 +128,7 @@
* Program id can be used to further uniquely identify the presentation to a decoder.
* @hide
*/
- @VisibleForTesting
+ @TestApi
public int getProgramId() {
return mProgramId;
}
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 0c617ba..a181ee2 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s-ৰ মাধ্যমেদি সংযোগ কৰা হৈছে"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$sৰ মাধ্যমেৰে উপলব্ধ"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"সংযোজিত, ইণ্টাৰনেট নাই"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"ইণ্টাৰনেট সংযোগ নাই"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"ছাইন ইন কৰা দৰকাৰী"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"একচেছ পইণ্ট কিছু সময়ৰ বাবে পূৰ্ণ হৈ আছে"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$sৰ যোগেৰে সংযোজিত"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$sৰ মাধ্যমেৰে উপলব্ধ"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"সংযোগ কৰা হ\'ল (ফ\'ন নাই), বেটাৰিৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"সংযোগ কৰা হ\'ল (মিডিয়া নাই), বেটাৰিৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"সংযোগ কৰা হ\'ল (কোনো ফ\'ন বা মিডিয়া নাই), বেটাৰিৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"সক্ৰিয়, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰি"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰি"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"সক্ৰিয়"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"মিডিয়াৰ অডিঅ’"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ফ\'ন কলসমূহ"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ফাইল স্থানান্তৰণ"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"হেডফ\'ন"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"ইনপুট সম্পৰ্কীয় বাহ্য় ডিভাইচ"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"ব্লুটুথ"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"বাওঁফালৰ শ্ৰৱণ যন্ত্ৰটো যোৰ পতোৱা হৈছে…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"সোঁফালৰ শ্ৰৱণ যন্ত্ৰটো যোৰ পতোৱা হৈছে…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰি বাকী আছে"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"সোঁ - বেটাৰি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"ৱাই-ফাই অফহৈ আছে।"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"ৱাইফাই সংযোগ বিচ্ছিন্ন হৈ আছে।"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"ৱাই-ফাই এদাল দণ্ড।"</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"স্বয়ংক্ৰিয়"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"ব্যক্তিগত ডিএনএছ প্ৰদানকাৰীৰ হোষ্টনাম"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ডিএনএছ সেৱা যোগানকাৰীৰ হ\'ষ্টনাম দিয়ক"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"সংযোগ কৰিব পৰা নগ\'ল"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"বেতাঁৰ ডিছপ্লে প্ৰমাণপত্ৰৰ বাবে বিকল্পসমূহ দেখুৱাওক"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ৱাই-ফাই লগিঙৰ মাত্ৰা বঢ়াওক, Wi‑Fi পিকাৰত প্ৰতি SSID RSSI দেখুৱাওক"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"ৱাই-ফাই নেটৱৰ্কৰ লগত সংযোগ কৰি থকাৰ সময়ত MAC ঠিকনা যাদৃচ্ছিক কৰক"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"নিৰিখ-নিৰ্দিষ্ট"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"নিৰিখ অনিৰ্দিষ্ট"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"লগাৰৰ বাফাৰৰ আকাৰ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"প্ৰতিটো লগ বাফাৰত ল\'গাৰৰ আকাৰ বাছনি কৰক"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"লগাৰৰ স্থায়ী সঞ্চয়াগাৰৰ বস্তুবোৰ মচিবনে?"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index faa7eb0..499a2fb 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -114,8 +114,8 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Навушнікі"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Перыферыйная прылада ўводу"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Спалучаецца левы навушнік…"</string>
- <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Спалучаецца правы навушнік…"</string>
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Спалучаецца левы слыхавы апарат…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Спалучаецца правы слыхавы апарат…"</string>
<string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Левы – узровень зараду <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Правы – узровень зараду <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi выключаны."</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 7f3c954..6b37300 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s মাধ্যমে সংযুক্ত হয়েছে"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s এর মাধ্যমে উপলব্ধ"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"সংযুক্ত, ইন্টারনেট নেই"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"ইন্টারনেট কানেকশন নেই"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"সাইন-ইন করা দরকার"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"এই মুহূর্তে অ্যাক্সেস পয়েন্টের কোনও কানেকশন ফাঁকা নেই"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s এর মাধ্যমে সংযুক্ত হয়েছে"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s এর মাধ্যমে পাওয়া যাচ্ছে"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"কানেক্ট করা আছে (ফোনের অডিও ছাড়া), ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"কানেক্ট করা আছে (মিডিয়ার অডিও ছাড়া), ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"কানেক্ট করা আছে (ফোনের বা মিডিয়ার অডিও ছাড়া), ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"চালু আছে, চার্জ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"চার্জ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"চালু আছে"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"মিডিয়া অডিও"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ফোন কল"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ফাইল স্থানান্তর"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"হেডফোন"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"পেরিফেরাল ইনপুট"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"ব্লুটুথ"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"বাঁদিকের হিয়ারিং এডটি পেয়ার করা হচ্ছে..."</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"ডানদিকের হিয়ারিং এড পেয়ার করা হচ্ছে…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> চার্জ বাকি আছে"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"ডানদিকের - চার্জ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"ওয়াই ফাই বন্ধ৷"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"ওয়াই ফাই এর সংযোগ বিচ্ছিন্ন হয়েছে৷"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"ওয়াই ফাই এ একটি দণ্ড৷"</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"অটোমেটিক"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"ব্যক্তিগত ডিএনএস প্রদানকারীর হোস্টনেম"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ডিএনএস প্রদানকারীর হোস্টনেম লিখুন"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"কানেক্ট করা যায়নি"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ওয়্যারলেস প্রদর্শন সার্টিফিকেশন জন্য বিকল্পগুলি দেখান"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ওয়াই-ফাই লগিং স্তর বাড়ান, ওয়াই-ফাই চয়নকারীতে SSID RSSI অনুযায়ী দেখান"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"ওয়াই-ফাই নেটওয়ার্কে সংযুক্ত করার সময় MAC অ্যাড্রেস র্যান্ডমাইজ করুন"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"পরিমাপ করা"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"পরিমাপ করা নয়"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"লগার বাফারের আকারগুলি"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"লগ বাফার প্রতি অপেক্ষাকৃত বড় আকারগুলির বেছে নিন"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"লগারের স্টোরেজ সাফ করবেন?"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index a5b92de..2909265 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Connectada mitjançant %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Disponible mitjançant %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Connectada, sense Internet"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Sense connexió a Internet"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Cal iniciar la sessió"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"El punt d\'accés està temporalment ple"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Connectat mitjançant %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Disponible mitjançant %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat (sense accés al telèfon), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat (sense accés al contingut multimèdia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat (sense accés al telèfon ni al contingut multimèdia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Actiu, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Actiu"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Àudio multimèdia"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Trucades telefòniques"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferència del fitxer"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Auricular"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Perifèric d\'entrada"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"S\'està vinculant l\'audiòfon esquerre…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"S\'està vinculant l\'audiòfon dret…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Esquerre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Dret: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi desactivada."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi desconnectada."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Senyal Wi-Fi: una barra."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automàtic"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Nom d\'amfitrió del proveïdor de DNS privat"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introdueix el nom d\'amfitrió del proveïdor de DNS"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"No s\'ha pogut connectar"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra les opcions de certificació de pantalla sense fil"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Augmenta nivell de registre Wi‑Fi i mostra\'l per SSID RSSI al Selector de Wi‑Fi"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Aleatoritza l\'adreça MAC quan estiguis connectat a una xarxa Wi-Fi"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Amb límit de dades"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Sense límit de dades"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Mides memòria intermèdia Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Mida Logger per memòria intermèdia"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Vols esborrar l\'emmagatzematge persistent del registrador?"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 8c353f4..f3c7323 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -65,9 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen telefon) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen medier) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen telefon eller medier) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktiv, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktivt, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
<string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
- <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktiv"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktivt"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medielyd"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonopkald"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Filoverførsel"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 3d3c66e..c518415 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -241,8 +241,8 @@
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones para la certificación de la pantalla inalámbrica"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar el nivel de registro de Wi-Fi, mostrar por SSID RSSI en el selector Wi-Fi"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Ordenar las direcciones MAC de forma aleatoria al conectarse a redes Wi‑Fi"</string>
- <string name="wifi_metered_label" msgid="4514924227256839725">"Medido"</string>
- <string name="wifi_unmetered_label" msgid="6124098729457992931">"No medido"</string>
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Medida"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"No medida"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de registrador"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Elige el tamaño del Logger por búfer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"¿Borrar almacenamiento continuo del registrador?"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 6acd2ca..4919aa9 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s દ્વારા કનેક્ટ થયેલ"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s દ્વારા ઉપલબ્ધ"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"કનેક્ટ કર્યું, કોઈ ઇન્ટરનેટ નથી"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"ઇન્ટરનેટ ઍક્સેસ નથી"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"સાઇન ઇન આવશ્યક"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ઍક્સેસ પૉઇન્ટ અસ્થાયીરૂપે ભરાયેલ છે"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s દ્વારા કનેક્ટ થયેલ"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s દ્વારા ઉપલબ્ધ"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ ફોન નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ મીડિયા નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ ફોન અથવા મીડિયા નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"સક્રિય, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"સક્રિય"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"મીડિયા ઑડિઓ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ફોન કૉલ"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ફાઇલ સ્થાનાંતરણ"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"હેડફોન"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"ઇનપુટ પેરિફેરલ"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"બ્લૂટૂથ"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"ડાબી બાજુના શ્રવણ યંત્ર સાથે જોડાણ કરી રહ્યાં છીએ…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"જમણી બાજુના શ્રવણ યંત્ર સાથે જોડાણ કરી રહ્યાં છીએ…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"ડાબે - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"જમણી બાજુની - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wifi બંધ."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wifi ડિસ્કનેક્ટ થયું."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wifi એક બાર."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"આપમેળે"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"ખાનગી DNS પ્રદાતા હોસ્ટનું નામ"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS પ્રદાતાના હોસ્ટનું નામ દાખલ કરો"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"કનેક્ટ કરી શકાયું નથી"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"વાયરલેસ ડિસ્પ્લે પ્રમાણપત્ર માટેના વિકલ્પો બતાવો"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"વાઇ-ફાઇ લોગિંગ સ્તર વધારો, વાઇ-ફાઇ પીકરમાં SSID RSSI દીઠ બતાવો"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"વાઇ-ફાઇ નેટવર્ક સાથે જ્યારે કનેક્ટ કરી રહ્યાં હોય ત્યારે MAC ઍડ્રેસને રેન્ડમાઇઝ કરો"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"મીટર કરેલ"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"મીટર ન કરેલ"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"લોગર બફર કદ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"લૉગ દીઠ લૉગર કદ બફર પસંદ કરો"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"લૉગર નિરંતર સ્ટોરેજ સાફ કરીએ?"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 9b5c572..f15cdd0 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s के द्वारा उपलब्ध"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s के द्वारा उपलब्ध"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"कनेक्ट हो गया है, लेकिन इंटरनेट नहीं है"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"इंटरनेट कनेक्शन नहीं है"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"साइन इन करना ज़रूरी है"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"एक्सेस प्वाइंट फ़िलहाल भरा हुआ है"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s के ज़रिए कनेक्ट"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s के ज़रिए उपलब्ध"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"जुड़ गया (फ़ोन के ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"जुड़ गया (मीडिया ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"जुड़ गया (फ़ोन या मीडिया ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"चालू, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"चालू"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"मीडिया ऑडियो"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"फ़ोन कॉल"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"फ़ाइल स्थानांतरण"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"हेडफ़ोन"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"इनपुट पेरिफ़ेरल"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"ब्लूटूथ"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"सुनने में मददगार बाईं ओर का डिवाइस जोड़ा जा रहा है…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"सुनने में मददगार दाईं ओर का डिवाइस जोड़ा जा रहा है…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"बाईं ओर का डिवाइस - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"दाईं ओर का डिवाइस - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"वाई-फ़ाई बंद है."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"वाई-फ़ाई डिसकनेक्ट है."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"वाई-फ़ाई का एक बार है."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"अपने आप"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"निजी DNS सेवा देने वाले का होस्टनाम"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS सेवा देने वाले का होस्टनाम डालें"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"कनेक्ट नहीं हो सका"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस दिखाई देने के लिए प्रमाणन विकल्प दिखाएं"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"वाई-फ़ाई प्रवेश स्तर बढ़ाएं, वाई-फ़ाई पिकर में प्रति SSID RSSI दिखाएं"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"वाई-फ़ाई से जुड़ते समय अलग-अलग एमएसी पते इस्तेमाल करें"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"डेटा इस्तेमाल करने की सीमा तय की गई है"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"डेटा इस्तेमाल करने की सीमा तय नहीं की गई है"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"लॉगर बफ़र आकार"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"प्रति लॉग बफ़र लॉगर आकार चुनें"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"लॉगर सतत मेमोरी साफ़ करें?"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index eb611ac..0150f32 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -65,7 +65,7 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Terhubung (tanpa ponsel), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Terhubung (tanpa media), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Terhubung (tanpa ponsel atau media), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktif, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterai"</string>
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktif, baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level" msgid="1447164613319663655">"Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktif"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio media"</string>
@@ -116,8 +116,8 @@
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
<string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Menyambungkan alat bantu dengar sebelah kiri…"</string>
<string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Menyambungkan alat bantu dengar sebelah kanan…"</string>
- <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Kiri - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterai"</string>
- <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Kanan - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterai"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Kiri - baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Kanan - baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi tidak aktif."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi tidak tersambung."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi satu baris."</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 38251b3..9eca2b2 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -65,7 +65,7 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (telefono escluso), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (contenuti multimediali esclusi), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (telefono o contenuti multimediali esclusi), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Attivo, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria"</string>
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Attivo - Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level" msgid="1447164613319663655">"Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Attivo"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio multimediale"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index fa29adc..9547d90 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -114,8 +114,8 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Слушалка"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Периферен влез"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Се спарува лев апарат за слушање…"</string>
- <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Се спарува десен апарат за слушање…"</string>
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Се спарува лево слушно помагало…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Се спарува десно слушно помагало…"</string>
<string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Лево - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија"</string>
<string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Десно - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi е исклучено."</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index e3f996a..22ea56c 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -114,7 +114,7 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"နားကြပ်"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"ချိတ်ဆက်အသုံးပြုရသည့် စက်ပစ္စည်းများ"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"ဘလူးတုသ်"</string>
- <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"ဘယ်ဘက် နားကြီးကိရိယာကို တွဲချိတ်နေသည်…"</string>
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"ဘယ်ဘက် နားကြားကိရိယာကို တွဲချိတ်နေသည်…"</string>
<string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"ညာဘက် နားကြားကိရိယာကို တွဲချိတ်နေသည်…"</string>
<string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"ဘယ်ဘက် − ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"ညာဘက် − ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -241,8 +241,8 @@
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ကြိုးမဲ့ အခင်းအကျင်း အသိအမှတ်ပြုလက်မှတ်အတွက် ရွေးချယ်စရာများပြရန်"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi မှတ်တမ်းတင်ခြင်း နှုန်းအားမြင့်ကာ၊ Wi‑Fi ရွေးရာတွင် SSID RSSI ဖြင့်ပြပါ"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi‑Fi ကွန်ရက်များသို့ ချိတ်ဆက်သည့်အခါ MAC လိပ်စာ ကျပန်းပြုလုပ်ခြင်း"</string>
- <string name="wifi_metered_label" msgid="4514924227256839725">"မိမိအသုံးပြုမှုအလိုက် ကောက်ခံထားသည်"</string>
- <string name="wifi_unmetered_label" msgid="6124098729457992931">"မိမိအသုံးပြုမှုအလိုက် ကောက်ခံခြင်းမရှိပါ"</string>
+ <string name="wifi_metered_label" msgid="4514924227256839725">"အခမဲ့ မဟုတ်ပါ"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"အခမဲ့"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"လော့ဂါး ဘာဖား ဆိုက်များ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"လော့ ဘာဖားတွက် လော့ဂါးဆိုက် ရွေး"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"မှတ်တမ်းထိန်းသိမ်းပေးသည့် သိုလှောင်ခန်းကို ရှင်းလင်းမလား။"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index f6352c06..434823f 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -116,8 +116,8 @@
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
<string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Se asociază aparatul auditiv stâng…"</string>
<string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Se asociază aparatul auditiv drept…"</string>
- <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Stâng - baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Drept - baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Stânga – baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Dreapta – baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi dezactivat."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi deconectat."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Semnal Wi-Fi: o bară."</string>
@@ -241,8 +241,8 @@
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afișați opțiunile pentru certificarea Ecran wireless"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Măriți niv. de înr. prin Wi‑Fi, afișați în fcț. de SSID RSSI în Selectorul Wi‑Fi"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Afișează aleatoriu adresa MAC când te conectezi la rețele Wi‑Fi"</string>
- <string name="wifi_metered_label" msgid="4514924227256839725">"Contorizat"</string>
- <string name="wifi_unmetered_label" msgid="6124098729457992931">"Necontorizat"</string>
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Contorizată"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Necontorizată"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Dimensiunile tamponului jurnalului"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Dimensiuni jurnal / tampon jurnal"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Ștergeți stocarea permanentă a jurnalului?"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index fd2f1ea..8162a76 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"منسلک بذریعہ %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"دستیاب بذریعہ %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"منسلک، انٹرنیٹ نہیں ہے"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"انٹرنیٹ نہیں ہے"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"سائن ان درکار ہے"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"رسائی پوائنٹ عارضی طور پر فُل ہے"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"منسلک بذریعہ %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"دستیاب بذریعہ %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"منسلک ہے (فون کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"منسلک ہے (میڈیا کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"منسلک ہے (فون یا میڈیا کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"فعال، <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"فعال"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"میڈيا آڈیو"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"فون کالز"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"فائل کی منتقلی"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"ہیڈ فون"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"ان پٹ پیریفرل"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"بلوٹوتھ"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"بائيں جانب کے سماعتی آلہ کا جوڑا بنایا جا رہا ہے…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"دائیں جانب کے سماعتی آلہ کا جوڑا بنایا جا رہا ہے…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"بائيں - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"دائيں - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wifi آف ہے۔"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wifi غیر منسلک ہو گیا۔"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wifi ایک بار۔"</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"خودکار"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"نجی DNS فراہم کنندہ میزبان کا نام"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS فراہم کنندہ کے میزبان کا نام درج کریں"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"منسلک نہیں ہو سکا"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"وائرلیس ڈسپلے سرٹیفیکیشن کیلئے اختیارات دکھائیں"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi لاگنگ لیول میں اضافہ کریں، Wi‑Fi منتخب کنندہ میں فی SSID RSSI دکھائیں"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi-Fi نیٹ ورکس سے منسلک کرتے وقت MAC پتے کو غیر مرتب کریں"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"میٹرڈ"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"غیر میٹر شدہ"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"لاگر بفر کے سائز"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"فی لاگ بفر لاگر کے سائز منتخب کریں"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"لاگر مستقل اسٹوریج صاف کریں؟"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 6c068ff..dc2ecea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -631,7 +631,7 @@
}
HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile();
if (hearingAidProfile != null) {
- mIsActiveDeviceHearingAid = hearingAidProfile.isActiveDevice(mDevice);
+ mIsActiveDeviceHearingAid = hearingAidProfile.getActiveDevices().contains(mDevice);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index 920500f..6c5ecbf 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -136,13 +136,12 @@
public boolean setActiveDevice(BluetoothDevice device) {
if (mService == null) return false;
- mService.setActiveDevice(device);
- return true;
+ return mService.setActiveDevice(device);
}
- public boolean isActiveDevice(BluetoothDevice device) {
- if (mService == null) return false;
- return mService.isActiveDevice(device);
+ public List<BluetoothDevice> getActiveDevices() {
+ if (mService == null) return new ArrayList<>();
+ return mService.getActiveDevices();
}
public boolean isPreferred(BluetoothDevice device) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
new file mode 100644
index 0000000..941964a
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
@@ -0,0 +1,200 @@
+/*
+ * 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.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHidDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * HidProfile handles Bluetooth HID profile.
+ */
+public class HidDeviceProfile implements LocalBluetoothProfile {
+ private static final String TAG = "HidDeviceProfile";
+ // Order of this profile in device profiles list
+ private static final int ORDINAL = 18;
+ // HID Device Profile is always preferred.
+ private static final int PREFERRED_VALUE = -1;
+ private static final boolean DEBUG = true;
+
+ private final LocalBluetoothAdapter mLocalAdapter;
+ private final CachedBluetoothDeviceManager mDeviceManager;
+ private final LocalBluetoothProfileManager mProfileManager;
+ static final String NAME = "HID DEVICE";
+
+ private BluetoothHidDevice mService;
+ private boolean mIsProfileReady;
+
+ HidDeviceProfile(Context context, LocalBluetoothAdapter adapter,
+ CachedBluetoothDeviceManager deviceManager,
+ LocalBluetoothProfileManager profileManager) {
+ mLocalAdapter = adapter;
+ mDeviceManager = deviceManager;
+ mProfileManager = profileManager;
+ adapter.getProfileProxy(context, new HidDeviceServiceListener(),
+ BluetoothProfile.HID_DEVICE);
+ }
+
+ // These callbacks run on the main thread.
+ private final class HidDeviceServiceListener
+ implements BluetoothProfile.ServiceListener {
+
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (DEBUG) {
+ Log.d(TAG,"Bluetooth service connected :-)");
+ }
+ mService = (BluetoothHidDevice) proxy;
+ // We just bound to the service, so refresh the UI for any connected HID devices.
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ for (BluetoothDevice nextDevice : deviceList) {
+ CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+ // we may add a new device here, but generally this should not happen
+ if (device == null) {
+ Log.w(TAG, "HidProfile found new device: " + nextDevice);
+ device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+ }
+ Log.d(TAG, "Connection status changed: " + device);
+ device.onProfileStateChanged(HidDeviceProfile.this,
+ BluetoothProfile.STATE_CONNECTED);
+ device.refresh();
+ }
+ mIsProfileReady = true;
+ }
+
+ public void onServiceDisconnected(int profile) {
+ if (DEBUG) {
+ Log.d(TAG, "Bluetooth service disconnected");
+ }
+ mIsProfileReady = false;
+ }
+ }
+
+ @Override
+ public boolean isProfileReady() {
+ return mIsProfileReady;
+ }
+
+ @Override
+ public boolean isConnectable() {
+ return true;
+ }
+
+ @Override
+ public boolean isAutoConnectable() {
+ return false;
+ }
+
+ @Override
+ public boolean connect(BluetoothDevice device) {
+ return false;
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device) {
+ if (mService == null) {
+ return false;
+ }
+ return mService.disconnect(device);
+ }
+
+ @Override
+ public int getConnectionStatus(BluetoothDevice device) {
+ if (mService == null) {
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+
+ return !deviceList.isEmpty() && deviceList.contains(device)
+ ? mService.getConnectionState(device)
+ : BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ @Override
+ public boolean isPreferred(BluetoothDevice device) {
+ return getConnectionStatus(device) != BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ @Override
+ public int getPreferred(BluetoothDevice device) {
+ return PREFERRED_VALUE;
+ }
+
+ @Override
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ // if set preferred to false, then disconnect to the current device
+ if (!preferred) {
+ mService.disconnect(device);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return NAME;
+ }
+
+ @Override
+ public int getOrdinal() {
+ return ORDINAL;
+ }
+
+ @Override
+ public int getNameResource(BluetoothDevice device) {
+ return R.string.bluetooth_profile_hid;
+ }
+
+ @Override
+ public int getSummaryResourceForDevice(BluetoothDevice device) {
+ final int state = getConnectionStatus(device);
+ switch (state) {
+ case BluetoothProfile.STATE_DISCONNECTED:
+ return R.string.bluetooth_hid_profile_summary_use_for;
+ case BluetoothProfile.STATE_CONNECTED:
+ return R.string.bluetooth_hid_profile_summary_connected;
+ default:
+ return Utils.getConnectionStateSummary(state);
+ }
+ }
+
+ @Override
+ public int getDrawableResource(BluetoothClass btClass) {
+ return R.drawable.ic_bt_misc_hid;
+ }
+
+ protected void finalize() {
+ if (DEBUG) {
+ Log.d(TAG, "finalize()");
+ }
+ if (mService != null) {
+ try {
+ BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.HID_DEVICE,
+ mService);
+ mService = null;
+ } catch (Throwable t) {
+ Log.w(TAG, "Error cleaning up HID proxy", t);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
index 213002f..93c4017 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
@@ -48,7 +48,7 @@
private static final int ORDINAL = 3;
// These callbacks run on the main thread.
- private final class InputDeviceServiceListener
+ private final class HidHostServiceListener
implements BluetoothProfile.ServiceListener {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
@@ -86,7 +86,7 @@
mLocalAdapter = adapter;
mDeviceManager = deviceManager;
mProfileManager = profileManager;
- adapter.getProfileProxy(context, new InputDeviceServiceListener(),
+ adapter.getProfileProxy(context, new HidHostServiceListener(),
BluetoothProfile.HID_HOST);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 00ee575..6413aab 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -22,6 +22,7 @@
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothHidDevice;
import android.bluetooth.BluetoothHidHost;
import android.bluetooth.BluetoothMap;
import android.bluetooth.BluetoothMapClient;
@@ -86,6 +87,7 @@
private MapProfile mMapProfile;
private MapClientProfile mMapClientProfile;
private final HidProfile mHidProfile;
+ private HidDeviceProfile mHidDeviceProfile;
private OppProfile mOppProfile;
private final PanProfile mPanProfile;
private PbapClientProfile mPbapClientProfile;
@@ -123,7 +125,7 @@
updateLocalProfiles(uuids);
}
- // Always add HID and PAN profiles
+ // Always add HID host, HID device, and PAN profiles
mHidProfile = new HidProfile(context, mLocalAdapter, mDeviceManager, this);
addProfile(mHidProfile, HidProfile.NAME,
BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED);
@@ -132,6 +134,10 @@
addPanProfile(mPanProfile, PanProfile.NAME,
BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
+ mHidDeviceProfile = new HidDeviceProfile(context, mLocalAdapter, mDeviceManager, this);
+ addProfile(mHidDeviceProfile, HidDeviceProfile.NAME,
+ BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED);
+
if(DEBUG) Log.d(TAG, "Adding local MAP profile");
if (mUseMapClient) {
mMapClientProfile = new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
@@ -547,6 +553,12 @@
removedProfiles.remove(mHidProfile);
}
+ if (mHidProfile != null && mHidDeviceProfile.getConnectionStatus(device)
+ != BluetoothProfile.STATE_DISCONNECTED) {
+ profiles.add(mHidDeviceProfile);
+ removedProfiles.remove(mHidDeviceProfile);
+ }
+
if(isPanNapConnected)
if(DEBUG) Log.d(TAG, "Valid PAN-NAP connection exists.");
if ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.NAP) &&
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 9347674..547cd9a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -41,8 +41,9 @@
private final WifiManager mWifiManager;
private final NetworkScoreManager mNetworkScoreManager;
private final ConnectivityManager mConnectivityManager;
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
private final WifiNetworkScoreCache.CacheListener mCacheListener =
- new WifiNetworkScoreCache.CacheListener(new Handler(Looper.getMainLooper())) {
+ new WifiNetworkScoreCache.CacheListener(mHandler) {
@Override
public void networkCacheUpdated(List<ScoredNetwork> updatedNetworks) {
updateStatusLabel();
@@ -89,7 +90,8 @@
mNetworkScoreManager.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
mWifiNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK);
mWifiNetworkScoreCache.registerListener(mCacheListener);
- mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
+ mConnectivityManager.registerNetworkCallback(
+ mNetworkRequest, mNetworkCallback, mHandler);
} else {
mNetworkScoreManager.unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI,
mWifiNetworkScoreCache);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index a128b54..d8f0886 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -313,7 +313,8 @@
mContext.registerReceiver(mReceiver, mFilter, null /* permission */, mWorkHandler);
// NetworkCallback objects cannot be reused. http://b/20701525 .
mNetworkCallback = new WifiTrackerNetworkCallback();
- mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
+ mConnectivityManager.registerNetworkCallback(
+ mNetworkRequest, mNetworkCallback, mWorkHandler);
mRegistered = true;
}
}
@@ -788,7 +789,7 @@
// We don't send a NetworkInfo object along with this message, because even if we
// fetch one from ConnectivityManager, it might be older than the most recent
// NetworkInfo message we got via a WIFI_STATE_CHANGED broadcast.
- mWorkHandler.post(() -> updateNetworkInfo(null));
+ updateNetworkInfo(null);
}
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index ad422d8..4c98bb8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -144,10 +144,7 @@
}
try {
- if (Settings.System.SCREEN_BRIGHTNESS.equals(name)) {
- setBrightness(Integer.parseInt(value));
- // fall through to the ordinary write to settings
- } else if (Settings.System.SOUND_EFFECTS_ENABLED.equals(name)) {
+ if (Settings.System.SOUND_EFFECTS_ENABLED.equals(name)) {
setSoundEffects(Integer.parseInt(value) == 1);
// fall through to the ordinary write to settings
} else if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
@@ -305,10 +302,6 @@
}
}
- private void setBrightness(int brightness) {
- mContext.getSystemService(DisplayManager.class).setTemporaryBrightness(brightness);
- }
-
/* package */ byte[] getLocaleData() {
Configuration conf = mContext.getResources().getConfiguration();
return conf.getLocales().toLanguageTags().getBytes();
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
index 0ee40d7..67f68d3 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
@@ -15,40 +15,32 @@
limitations under the License.
-->
+
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:clipChildren="false"
android:alpha="0"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/car_fullscreen_user_pod_height"
- android:layout_gravity="center_horizontal|bottom" >
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:gravity="fill_horizontal"
+ android:layout_marginTop="@dimen/car_padding_5"
+ android:layout_marginStart="@dimen/car_padding_4">
<ImageView android:id="@+id/user_avatar"
android:layout_centerHorizontal="true"
- android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_image_top"
android:layout_width="@dimen/car_fullscreen_user_pod_image_avatar_width"
android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height"
- android:layout_above="@id/user_name" />
+ />
<TextView android:id="@+id/user_name"
- android:layout_width="@dimen/car_fullscreen_user_pod_width"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_name_top"
- android:layout_marginBottom="@dimen/car_fullscreen_user_pod_margin_name_bottom"
- android:textSize="@dimen/car_fullscreen_user_pod_name_text_size"
+ android:layout_marginTop="@dimen/car_padding_4"
+ android:textSize="@dimen/car_body1_size"
android:textColor="@color/qs_user_detail_name"
android:ellipsize="end"
android:singleLine="true"
- android:gravity="center_horizontal"
- android:layout_above="@id/device_name" />
+ android:gravity="center"
+ android:layout_below="@id/user_avatar"/>
- <TextView android:id="@+id/device_name"
- android:layout_width="@dimen/car_fullscreen_user_pod_width"
- android:layout_height="wrap_content"
- android:textSize="@dimen/car_fullscreen_user_pod_device_text_size"
- android:textColor="@color/qs_user_detail_name"
- android:ellipsize="end"
- android:singleLine="true"
- android:gravity="center_horizontal"
- android:layout_alignParentBottom="true" />
</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml
deleted file mode 100644
index d666a20..0000000
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- 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.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:clipChildren="false"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center" >
-
- <!-- car_fullscreen_user_pods will be dynamically added here. -->
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
index bfabe52..22452b7 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
@@ -39,27 +39,34 @@
android:theme="@android:style/Theme"
android:layout_alignParentTop="true"/>
- <com.android.systemui.statusbar.car.UserGridView
- android:id="@+id/user_grid"
+ <RelativeLayout
+ android:id="@+id/fullscreen_user_switcher_container"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/car_margin"
- android:layout_marginRight="@dimen/car_margin"
- android:layout_centerInParent="true"/>
+ android:layout_height="match_parent"
+ android:layout_marginStart="@dimen/car_margin"
+ android:layout_marginEnd="@dimen/car_margin">
- <com.android.systemui.statusbar.car.PageIndicator
- android:id="@+id/user_switcher_page_indicator"
- android:layout_width="match_parent"
- android:layout_height="@dimen/car_page_indicator_dot_diameter"
- android:layout_below="@+id/user_grid" />
+ <RelativeLayout
+ android:id="@+id/fullscreen_user_switcher_container_inner"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginEnd="@dimen/car_padding_4">
- <Button
- android:id="@+id/start_driving"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/car_start_driving_height"
- android:text="@string/start_driving"
- style="@style/CarUserSwitcher.StartDrivingButton"
- android:layout_alignParentBottom="true"
- android:layout_centerHorizontal="true" />
+ <com.android.systemui.statusbar.car.UserGridRecyclerView
+ android:id="@+id/user_grid"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/header"
+ android:scrollbars="vertical"
+ android:scrollbarFadeDuration="0"
+ android:verticalScrollbarPosition="left"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:layout_alignParentRight="true"/>
+
+ </RelativeLayout>
+
+ </RelativeLayout>
+
</RelativeLayout>
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/car_qs_panel.xml b/packages/SystemUI/res/layout/car_qs_panel.xml
index 447970c..c01bbce 100644
--- a/packages/SystemUI/res/layout/car_qs_panel.xml
+++ b/packages/SystemUI/res/layout/car_qs_panel.xml
@@ -30,27 +30,29 @@
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/user_switcher_container"
+ android:layout_marginStart="@dimen/car_margin"
+ android:layout_marginEnd="@dimen/car_margin"
android:clipChildren="false"
android:layout_width="match_parent"
- android:layout_height="@dimen/car_user_switcher_container_height"
- android:layout_gravity="center_horizontal" >
+ android:layout_height="@dimen/car_user_switcher_container_height">
- <com.android.systemui.statusbar.car.UserGridView
- android:id="@+id/user_grid"
- android:clipChildren="false"
+ <RelativeLayout
+ android:id="@+id/fullscreen_user_switcher_container_inner"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/car_margin"
- android:layout_marginRight="@dimen/car_margin"
- android:layout_above="@id/user_switcher_page_indicator" />
+ android:layout_height="match_parent"
+ android:layout_marginEnd="@dimen/car_padding_4">
- <com.android.systemui.statusbar.car.PageIndicator
- android:id="@+id/user_switcher_page_indicator"
- android:layout_width="match_parent"
- android:layout_height="@dimen/car_page_indicator_dot_diameter"
- android:layout_marginBottom="@dimen/car_page_indicator_margin_bottom"
- android:alpha="0"
- android:layout_alignParentBottom="true" />
+ <com.android.systemui.statusbar.car.UserGridRecyclerView
+ android:id="@+id/user_grid"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scrollbars="vertical"
+ android:verticalScrollbarPosition="left"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:layout_alignParentRight="true"
+ android:scrollbarFadeDuration="0"/>
+ </RelativeLayout>
</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml
index 79e54aa..d72021e 100644
--- a/packages/SystemUI/res/layout/navigation_layout.xml
+++ b/packages/SystemUI/res/layout/navigation_layout.xml
@@ -27,13 +27,16 @@
<com.android.systemui.statusbar.phone.NearestTouchFrame
android:id="@+id/nav_buttons"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false">
<LinearLayout
android:id="@+id/ends_group"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
+ android:clipToPadding="false"
android:clipChildren="false" />
<LinearLayout
@@ -43,6 +46,7 @@
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal"
+ android:clipToPadding="false"
android:clipChildren="false" />
</com.android.systemui.statusbar.phone.NearestTouchFrame>
diff --git a/packages/SystemUI/res/values/attrs_car.xml b/packages/SystemUI/res/values/attrs_car.xml
index 5e4bd79..335ae44 100644
--- a/packages/SystemUI/res/values/attrs_car.xml
+++ b/packages/SystemUI/res/values/attrs_car.xml
@@ -19,6 +19,8 @@
<declare-styleable name="CarFacetButton">
<!-- icon to be rendered (drawable) -->
<attr name="icon" format="reference"/>
+ <!-- icon to be rendered when in selected state -->
+ <attr name="selectedIcon" format="reference"/>
<!-- intent to start when button is click -->
<attr name="intent" format="string"/>
<!-- intent to start when a long press has happened -->
@@ -45,6 +47,12 @@
<attr name="longIntent" format="string"/>
<!-- start the intent as a broad cast instead of an activity if true-->
<attr name="broadcast" format="boolean"/>
+ <!-- Alpha value to used when in selected state. Defaults 1f -->
+ <attr name="selectedAlpha" format="float" />
+ <!-- Alpha value to used when in un-selected state. Defaults 0.7f -->
+ <attr name="unselectedAlpha" format="float" />
+ <!-- icon to be rendered when in selected state -->
+ <attr name="selectedIcon" format="reference"/>
</declare-styleable>
<!-- Custom attributes to configure hvac values -->
diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/SystemUI/res/values/dimens_car.xml
index 6caed61..2b91891 100644
--- a/packages/SystemUI/res/values/dimens_car.xml
+++ b/packages/SystemUI/res/values/dimens_car.xml
@@ -17,18 +17,14 @@
-->
<resources>
<dimen name="car_margin">148dp</dimen>
+ <dimen name="car_margin_standard">112dp</dimen>
- <dimen name="car_fullscreen_user_pod_margin_image_top">24dp</dimen>
- <dimen name="car_fullscreen_user_pod_margin_name_top">24dp</dimen>
- <dimen name="car_fullscreen_user_pod_margin_name_bottom">20dp</dimen>
- <dimen name="car_fullscreen_user_pod_margin_between">24dp</dimen>
- <dimen name="car_fullscreen_user_pod_icon_text_size">96dp</dimen>
- <dimen name="car_fullscreen_user_pod_image_avatar_width">192dp</dimen>
- <dimen name="car_fullscreen_user_pod_image_avatar_height">192dp</dimen>
- <dimen name="car_fullscreen_user_pod_width">264dp</dimen>
+ <!-- TODO replace with car support lib sizes when available -->
+ <dimen name="car_fullscreen_user_pod_icon_text_size">32sp</dimen>
+ <dimen name="car_fullscreen_user_pod_width">243dp</dimen>
<dimen name="car_fullscreen_user_pod_height">356dp</dimen>
- <dimen name="car_fullscreen_user_pod_name_text_size">40sp</dimen> <!-- B1 -->
- <dimen name="car_fullscreen_user_pod_device_text_size">@dimen/car_body2_size</dimen>
+ <dimen name="car_fullscreen_user_pod_image_avatar_width">96dp</dimen>
+ <dimen name="car_fullscreen_user_pod_image_avatar_height">96dp</dimen>
<dimen name="car_navigation_button_width">64dp</dimen>
<dimen name="car_navigation_bar_width">760dp</dimen>
diff --git a/packages/SystemUI/res/values/integers_car.xml b/packages/SystemUI/res/values/integers_car.xml
index a462576..7513fd4 100644
--- a/packages/SystemUI/res/values/integers_car.xml
+++ b/packages/SystemUI/res/values/integers_car.xml
@@ -17,4 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<integer name="car_user_switcher_anim_cascade_delay_ms">27</integer>
+ <!-- Full screen user switcher column number TODO: move to support library-->
+ <integer name="user_fullscreen_switcher_num_col">3</integer>
</resources>
diff --git a/packages/SystemUI/res/values/strings_car.xml b/packages/SystemUI/res/values/strings_car.xml
index 658eb4f..0b57ff8 100644
--- a/packages/SystemUI/res/values/strings_car.xml
+++ b/packages/SystemUI/res/values/strings_car.xml
@@ -17,6 +17,10 @@
*/
-->
<resources>
- <string name="unknown_user_label">Unknown</string>
- <string name="start_driving">Start Driving</string>
+ <!-- Name of Guest Profile. [CHAR LIMIT=30] -->
+ <string name="car_guest">Guest</string>
+ <!-- Name of Add User Profile. [CHAR LIMIT=30] -->
+ <string name="car_add_user">Add User</string>
+ <!-- Default name of the new user created. [CHAR LIMIT=30] -->
+ <string name="car_new_user">New User</string>
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
index c82c519..9975c41 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
@@ -101,6 +101,11 @@
return this;
}
+ public TransactionCompat setEarlyWakeup() {
+ mTransaction.setEarlyWakeup();
+ return this;
+ }
+
public TransactionCompat setColor(SurfaceControlCompat surfaceControl, float[] color) {
mTransaction.setColor(surfaceControl.mSurfaceControl, color);
return this;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
index 23d3ebbb..24b5a34 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
@@ -29,7 +29,6 @@
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.qs.QSFooter;
import com.android.systemui.qs.QSPanel;
-import com.android.systemui.statusbar.car.UserGridView;
import com.android.systemui.statusbar.phone.MultiUserSwitch;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.UserInfoController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
index 0ee6d1f..da21aa5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
@@ -20,21 +20,20 @@
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Fragment;
+import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
+import android.support.v7.widget.GridLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSFooter;
-import com.android.systemui.statusbar.car.PageIndicator;
-import com.android.systemui.statusbar.car.UserGridView;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.car.UserGridRecyclerView;
import java.util.ArrayList;
import java.util.List;
@@ -45,14 +44,12 @@
* status bar, and a static row with access to the user switcher and settings.
*/
public class CarQSFragment extends Fragment implements QS {
- private ViewGroup mPanel;
private View mHeader;
private View mUserSwitcherContainer;
private CarQSFooter mFooter;
private View mFooterUserName;
private View mFooterExpandIcon;
- private UserGridView mUserGridView;
- private PageIndicator mPageIndicator;
+ private UserGridRecyclerView mUserGridView;
private AnimatorSet mAnimatorSet;
private UserSwitchCallback mUserSwitchCallback;
@@ -65,7 +62,6 @@
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- mPanel = (ViewGroup) view;
mHeader = view.findViewById(R.id.header);
mFooter = view.findViewById(R.id.qs_footer);
mFooterUserName = mFooter.findViewById(R.id.user_name);
@@ -75,16 +71,15 @@
updateUserSwitcherHeight(0);
- mUserGridView = view.findViewById(R.id.user_grid);
- mUserGridView.init(null, Dependency.get(UserSwitcherController.class),
- false /* overrideAlpha */);
-
- mPageIndicator = view.findViewById(R.id.user_switcher_page_indicator);
- mPageIndicator.setupWithViewPager(mUserGridView);
+ Context context = getContext();
+ mUserGridView = mUserSwitcherContainer.findViewById(R.id.user_grid);
+ GridLayoutManager layoutManager = new GridLayoutManager(context,
+ context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col));
+ mUserGridView.setLayoutManager(layoutManager);
+ mUserGridView.buildAdapter();
mUserSwitchCallback = new UserSwitchCallback();
mFooter.setUserSwitchCallback(mUserSwitchCallback);
- mUserGridView.setUserSwitchCallback(mUserSwitchCallback);
}
@Override
@@ -111,13 +106,11 @@
@Override
public void setHeaderListening(boolean listening) {
mFooter.setListening(listening);
- mUserGridView.setListening(listening);
}
@Override
public void setListening(boolean listening) {
mFooter.setListening(listening);
- mUserGridView.setListening(listening);
}
@Override
@@ -219,24 +212,6 @@
mShowing = false;
animateHeightChange(false /* opening */);
}
-
- public void resetShowing() {
- if (mShowing) {
- for (int i = 0; i < mUserGridView.getChildCount(); i++) {
- ViewGroup podContainer = (ViewGroup) mUserGridView.getChildAt(i);
- // Need to bring the last child to the front to maintain the order in the pod
- // container. Why? ¯\_(ツ)_/¯
- if (podContainer.getChildCount() > 0) {
- podContainer.getChildAt(podContainer.getChildCount() - 1).bringToFront();
- }
- // The alpha values are default to 0, so if the pods have been refreshed, they
- // need to be set to 1 when showing.
- for (int j = 0; j < podContainer.getChildCount(); j++) {
- podContainer.getChildAt(j).setAlpha(1f);
- }
- }
- }
- }
}
private void updateUserSwitcherHeight(int height) {
@@ -260,27 +235,6 @@
});
allAnimators.add(heightAnimator);
- // The user grid contains pod containers that each contain a number of pods. Animate
- // all pods to avoid any discrepancy/race conditions with possible changes during the
- // animation.
- int cascadeDelay = getResources().getInteger(
- R.integer.car_user_switcher_anim_cascade_delay_ms);
- for (int i = 0; i < mUserGridView.getChildCount(); i++) {
- ViewGroup podContainer = (ViewGroup) mUserGridView.getChildAt(i);
- for (int j = 0; j < podContainer.getChildCount(); j++) {
- View pod = podContainer.getChildAt(j);
- Animator podAnimator = AnimatorInflater.loadAnimator(getContext(),
- opening ? R.anim.car_user_switcher_open_pod_animation
- : R.anim.car_user_switcher_close_pod_animation);
- // Add the cascading delay between pods
- if (opening) {
- podAnimator.setStartDelay(podAnimator.getStartDelay() + j * cascadeDelay);
- }
- podAnimator.setTarget(pod);
- allAnimators.add(podAnimator);
- }
- }
-
Animator nameAnimator = AnimatorInflater.loadAnimator(getContext(),
opening ? R.anim.car_user_switcher_open_name_animation
: R.anim.car_user_switcher_close_name_animation);
@@ -293,12 +247,6 @@
iconAnimator.setTarget(mFooterExpandIcon);
allAnimators.add(iconAnimator);
- Animator pageAnimator = AnimatorInflater.loadAnimator(getContext(),
- opening ? R.anim.car_user_switcher_open_pages_animation
- : R.anim.car_user_switcher_close_pages_animation);
- pageAnimator.setTarget(mPageIndicator);
- allAnimators.add(pageAnimator);
-
mAnimatorSet = new AnimatorSet();
mAnimatorSet.addListener(new AnimatorListenerAdapter() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 852239a..abc261e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -172,6 +172,14 @@
}
}
+ if (mediaNotification != null) {
+ mMediaNotificationKey = mediaNotification.notification.getKey();
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key="
+ + mMediaNotificationKey + " controller=" + mMediaController);
+ }
+ }
+
if (controller != null && !sameSessions(mMediaController, controller)) {
// We have a new media session
clearCurrentMediaNotification();
@@ -183,13 +191,6 @@
+ mMediaMetadata);
}
- if (mediaNotification != null) {
- mMediaNotificationKey = mediaNotification.notification.getKey();
- if (DEBUG_MEDIA) {
- Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key="
- + mMediaNotificationKey + " controller=" + mMediaController);
- }
- }
metaDataChanged = true;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
index 5f3e2e3..7285db6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
@@ -42,6 +42,11 @@
/** App packages that are allowed to be used with this widget */
private String[] mFacetPackages;
private int mIconResourceId;
+ /**
+ * If defined in the xml this will be the icon that's rendered when the button is marked as
+ * selected
+ */
+ private int mSelectedIconResourceId;
private boolean mUseMoreIcon = true;
private float mSelectedAlpha = 1f;
private float mUnselectedAlpha = 1f;
@@ -112,10 +117,9 @@
mIcon.setClickable(false);
mIcon.setAlpha(mUnselectedAlpha);
mIconResourceId = styledAttributes.getResourceId(R.styleable.CarFacetButton_icon, 0);
- if (mIconResourceId == 0) {
- throw new RuntimeException("specified icon resource was not found and is required");
- }
mIcon.setImageResource(mIconResourceId);
+ mSelectedIconResourceId = styledAttributes.getResourceId(
+ R.styleable.CarFacetButton_selectedIcon, mIconResourceId);
mMoreIcon = findViewById(R.id.car_nav_button_more_icon);
mMoreIcon.setClickable(false);
@@ -161,22 +165,10 @@
*/
public void setSelected(boolean selected, boolean showMoreIcon) {
mSelected = selected;
- if (selected) {
- if (mUseMoreIcon) {
- mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : GONE);
- }
- mIcon.setAlpha(mSelectedAlpha);
- } else {
- mMoreIcon.setVisibility(GONE);
- mIcon.setAlpha(mUnselectedAlpha);
- }
- }
-
- public void setIcon(Drawable d) {
- if (d != null) {
- mIcon.setImageDrawable(d);
- } else {
- mIcon.setImageResource(mIconResourceId);
+ mIcon.setAlpha(mSelected ? mSelectedAlpha : mUnselectedAlpha);
+ mIcon.setImageResource(mSelected ? mSelectedIconResourceId : mIconResourceId);
+ if (mUseMoreIcon) {
+ mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : GONE);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
index e73b173..b2cef16 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
@@ -25,7 +25,9 @@
import android.widget.TextView;
import com.android.keyguard.AlphaOptimizedImageButton;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
/**
* A custom navigation bar for the automotive use case.
@@ -52,6 +54,17 @@
if (mNotificationsButton != null) {
mNotificationsButton.setOnClickListener(this::onNotificationsClick);
}
+ View mStatusIcons = findViewById(R.id.statusIcons);
+ if (mStatusIcons != null) {
+ // Attach the controllers for Status icons such as wifi and bluetooth if the standard
+ // container is in the view.
+ StatusBarIconController.DarkIconManager mDarkIconManager =
+ new StatusBarIconController.DarkIconManager(
+ mStatusIcons.findViewById(R.id.statusIcons));
+ mDarkIconManager.setShouldLog(true);
+ Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
+ }
+
}
void setStatusBar(CarStatusBar carStatusBar) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
index 0cdaec1..e248db4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
@@ -4,6 +4,7 @@
import android.content.Intent;
import android.content.res.TypedArray;
import android.util.AttributeSet;
+import android.util.Log;
import android.widget.ImageView;
import com.android.systemui.R;
@@ -17,23 +18,34 @@
*/
public class CarNavigationButton extends com.android.keyguard.AlphaOptimizedImageButton {
- private static final float SELECTED_ALPHA = 1;
- private static final float UNSELECTED_ALPHA = 0.7f;
-
+ private static final String TAG = "CarNavigationButton";
private Context mContext;
- private String mIntent = null;
- private String mLongIntent = null;
- private boolean mBroadcastIntent = false;
+ private String mIntent;
+ private String mLongIntent;
+ private boolean mBroadcastIntent;
private boolean mSelected = false;
+ private float mSelectedAlpha;
+ private float mUnselectedAlpha;
+ private int mSelectedIconResourceId;
+ private int mIconResourceId;
public CarNavigationButton(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
- TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarNavigationButton);
+ TypedArray typedArray = context.obtainStyledAttributes(
+ attrs, R.styleable.CarNavigationButton);
mIntent = typedArray.getString(R.styleable.CarNavigationButton_intent);
mLongIntent = typedArray.getString(R.styleable.CarNavigationButton_longIntent);
mBroadcastIntent = typedArray.getBoolean(R.styleable.CarNavigationButton_broadcast, false);
+ mSelectedAlpha = typedArray.getFloat(
+ R.styleable.CarNavigationButton_selectedAlpha, mSelectedAlpha);
+ mUnselectedAlpha = typedArray.getFloat(
+ R.styleable.CarNavigationButton_unselectedAlpha, mUnselectedAlpha);
+ mIconResourceId = typedArray.getResourceId(
+ com.android.internal.R.styleable.ImageView_src, 0);
+ mSelectedIconResourceId = typedArray.getResourceId(
+ R.styleable.CarNavigationButton_selectedIcon, mIconResourceId);
}
@@ -45,17 +57,20 @@
public void onFinishInflate() {
super.onFinishInflate();
setScaleType(ImageView.ScaleType.CENTER);
- setAlpha(UNSELECTED_ALPHA);
+ setAlpha(mUnselectedAlpha);
try {
if (mIntent != null) {
final Intent intent = Intent.parseUri(mIntent, Intent.URI_INTENT_SCHEME);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
setOnClickListener(v -> {
- if (mBroadcastIntent) {
- mContext.sendBroadcast(intent);
- return;
+ try {
+ if (mBroadcastIntent) {
+ mContext.sendBroadcast(intent);
+ return;
+ }
+ mContext.startActivity(intent);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to launch intent", e);
}
- mContext.startActivity(intent);
});
}
} catch (URISyntaxException e) {
@@ -65,9 +80,13 @@
try {
if (mLongIntent != null) {
final Intent intent = Intent.parseUri(mLongIntent, Intent.URI_INTENT_SCHEME);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
setOnLongClickListener(v -> {
- mContext.startActivity(intent);
+ try {
+ mContext.startActivity(intent);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to launch intent", e);
+ }
+ // consume event either way
return true;
});
}
@@ -82,6 +101,7 @@
public void setSelected(boolean selected) {
super.setSelected(selected);
mSelected = selected;
- setAlpha(mSelected ? SELECTED_ALPHA : UNSELECTED_ALPHA);
+ setAlpha(mSelected ? mSelectedAlpha : mUnselectedAlpha);
+ setImageResource(mSelected ? mSelectedIconResourceId : mIconResourceId);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 3fb1137..008794c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -418,8 +418,7 @@
Dependency.get(UserSwitcherController.class);
if (userSwitcherController.useFullscreenUserSwitcher()) {
mFullscreenUserSwitcher = new FullscreenUserSwitcher(this,
- userSwitcherController,
- mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub));
+ mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub), mContext);
} else {
super.createUserSwitcher();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index bc353f2..fb525f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -18,14 +18,15 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.content.res.Resources;
+import android.content.Context;
import android.view.View;
import android.view.ViewStub;
import android.widget.ProgressBar;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
/**
* Manages the fullscreen user switcher.
@@ -33,36 +34,25 @@
public class FullscreenUserSwitcher {
private final View mContainer;
private final View mParent;
- private final UserGridView mUserGridView;
- private final UserSwitcherController mUserSwitcherController;
+ private final UserGridRecyclerView mUserGridView;
private final ProgressBar mSwitchingUsers;
private final int mShortAnimDuration;
private boolean mShowing;
- public FullscreenUserSwitcher(StatusBar statusBar,
- UserSwitcherController userSwitcherController,
- ViewStub containerStub) {
- mUserSwitcherController = userSwitcherController;
+ public FullscreenUserSwitcher(StatusBar statusBar, ViewStub containerStub, Context context) {
mParent = containerStub.inflate();
mContainer = mParent.findViewById(R.id.container);
mUserGridView = mContainer.findViewById(R.id.user_grid);
- mUserGridView.init(statusBar, mUserSwitcherController, true /* overrideAlpha */);
- mUserGridView.setUserSelectionListener(record -> {
- if (!record.isCurrent) {
- toggleSwitchInProgress(true);
- }
- });
+ mUserGridView.setStatusBar(statusBar);
+ GridLayoutManager layoutManager = new GridLayoutManager(context,
+ context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col));
+ mUserGridView.setLayoutManager(layoutManager);
+ mUserGridView.buildAdapter();
+ mUserGridView.setUserSelectionListener(record -> toggleSwitchInProgress(true));
- PageIndicator pageIndicator = mContainer.findViewById(R.id.user_switcher_page_indicator);
- pageIndicator.setupWithViewPager(mUserGridView);
-
- Resources res = mContainer.getResources();
- mShortAnimDuration = res.getInteger(android.R.integer.config_shortAnimTime);
-
- mContainer.findViewById(R.id.start_driving).setOnClickListener(v -> {
- automaticallySelectUser();
- });
+ mShortAnimDuration = mContainer.getResources()
+ .getInteger(android.R.integer.config_shortAnimTime);
mSwitchingUsers = mParent.findViewById(R.id.switching_users);
}
@@ -115,10 +105,4 @@
toggleSwitchInProgress(false);
mParent.setVisibility(View.GONE);
}
-
- private void automaticallySelectUser() {
- // TODO: Switch according to some policy. This implementation just tries to drop the
- // keyguard for the current user.
- mUserGridView.showOfflineAuthUi();
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
new file mode 100644
index 0000000..e09a360
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.car;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.drawable.GradientDrawable;
+import android.os.AsyncTask;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.settingslib.users.UserManagerHelper;
+import com.android.systemui.R;
+import com.android.systemui.qs.car.CarQSFragment;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Displays a GridLayout with icons for the users in the system to allow switching between users.
+ * One of the uses of this is for the lock screen in auto.
+ */
+public class UserGridRecyclerView extends RecyclerView implements
+ UserManagerHelper.OnUsersUpdateListener {
+
+ private StatusBar mStatusBar;
+ private UserSelectionListener mUserSelectionListener;
+ private UserAdapter mAdapter;
+ private UserManagerHelper mUserManagerHelper;
+ private Context mContext;
+
+ public UserGridRecyclerView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ super.setHasFixedSize(true);
+ mContext = context;
+ mUserManagerHelper = new UserManagerHelper(mContext);
+ }
+
+ /**
+ * Register listener for any update to the users
+ */
+ @Override
+ public void onFinishInflate() {
+ mUserManagerHelper.registerOnUsersUpdateListener(this);
+ }
+
+ /**
+ * Unregisters listener checking for any change to the users
+ */
+ @Override
+ public void onDetachedFromWindow() {
+ mUserManagerHelper.unregisterOnUsersUpdateListener();
+ }
+
+ /**
+ * Initializes the adapter that populates the grid layout
+ *
+ * @return the adapter
+ */
+ public void buildAdapter() {
+ List<UserRecord> userRecords = createUserRecords(mUserManagerHelper
+ .getAllUsers());
+ mAdapter = new UserAdapter(mContext, userRecords);
+ super.setAdapter(mAdapter);
+ }
+
+ public void setStatusBar(@Nullable StatusBar statusBar) {
+ mStatusBar = statusBar;
+ }
+
+ private List<UserRecord> createUserRecords(List<UserInfo> userInfoList) {
+ List<UserRecord> userRecords = new ArrayList<>();
+ for (UserInfo userInfo : userInfoList) {
+ boolean isCurrent = false;
+ if (ActivityManager.getCurrentUser() == userInfo.id) {
+ isCurrent = true;
+ }
+ UserRecord record = new UserRecord(userInfo, false /* isGuest */,
+ false /* isAddUser */, isCurrent);
+ userRecords.add(record);
+ }
+
+ // Add guest user record if the current user is not a guest
+ if (!mUserManagerHelper.isGuestUser()) {
+ userRecords.add(addGuestUserRecord());
+ }
+
+ // Add add user record if the current user can add users
+ if (mUserManagerHelper.canAddUsers()) {
+ userRecords.add(addUserRecord());
+ }
+
+ return userRecords;
+ }
+
+ /**
+ * Create guest user record
+ */
+ private UserRecord addGuestUserRecord() {
+ UserInfo userInfo = new UserInfo();
+ userInfo.name = mContext.getString(R.string.car_guest);
+ return new UserRecord(userInfo, true /* isGuest */,
+ false /* isAddUser */, false /* isCurrent */);
+ }
+
+ /**
+ * Create add user record
+ */
+ private UserRecord addUserRecord() {
+ UserInfo userInfo = new UserInfo();
+ userInfo.name = mContext.getString(R.string.car_add_user);
+ return new UserRecord(userInfo, false /* isGuest */,
+ true /* isAddUser */, false /* isCurrent */);
+ }
+
+ public void onUserSwitched(int newUserId) {
+ // Bring up security view after user switch is completed.
+ post(this::showOfflineAuthUi);
+ }
+
+ public void setUserSelectionListener(UserSelectionListener userSelectionListener) {
+ mUserSelectionListener = userSelectionListener;
+ }
+
+ void showOfflineAuthUi() {
+ // TODO: Show keyguard UI in-place.
+ if (mStatusBar != null) {
+ mStatusBar.executeRunnableDismissingKeyguard(null/* runnable */, null /* cancelAction */,
+ true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */);
+ }
+ }
+
+ @Override
+ public void onUsersUpdate() {
+ mAdapter.clearUsers();
+ mAdapter.updateUsers(createUserRecords(mUserManagerHelper.getAllUsers()));
+ mAdapter.notifyDataSetChanged();
+ }
+
+ /**
+ * Adapter to populate the grid layout with the available user profiles
+ */
+ public final class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserAdapterViewHolder> {
+
+ private final Context mContext;
+ private List<UserRecord> mUsers;
+ private final int mPodImageAvatarWidth;
+ private final int mPodImageAvatarHeight;
+ private final Resources mRes;
+ private final String mGuestName;
+ private final String mNewUserName;
+
+ public UserAdapter(Context context, List<UserRecord> users) {
+ mRes = context.getResources();
+ mContext = context;
+ updateUsers(users);
+ mPodImageAvatarWidth = mRes.getDimensionPixelSize(
+ R.dimen.car_fullscreen_user_pod_image_avatar_width);
+ mPodImageAvatarHeight = mRes.getDimensionPixelSize(
+ R.dimen.car_fullscreen_user_pod_image_avatar_height);
+ mGuestName = mRes.getString(R.string.car_guest);
+ mNewUserName = mRes.getString(R.string.car_new_user);
+ }
+
+ public void clearUsers() {
+ mUsers.clear();
+ }
+
+ public void updateUsers(List<UserRecord> users) {
+ mUsers = users;
+ }
+
+ @Override
+ public UserAdapterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(mContext)
+ .inflate(R.layout.car_fullscreen_user_pod, parent, false);
+ view.setAlpha(1f);
+ view.bringToFront();
+ return new UserAdapterViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(UserAdapterViewHolder holder, int position) {
+ UserRecord userRecord = mUsers.get(position);
+ holder.mUserAvatarImageView.setImageBitmap(getDefaultUserIcon(userRecord));
+ holder.mUserNameTextView.setText(userRecord.mInfo.name);
+ holder.mView.setOnClickListener(v -> {
+ if (userRecord == null) {
+ return;
+ }
+
+ // Notify the listener which user was selected
+ if (mUserSelectionListener != null) {
+ mUserSelectionListener.onUserSelected(userRecord);
+ }
+
+ // If the user selects Guest, switch to Guest profile
+ if (userRecord.mIsGuest) {
+ mUserManagerHelper.switchToGuest(mGuestName);
+ return;
+ }
+
+ // If the user wants to add a user, start task to add new user
+ if (userRecord.mIsAddUser) {
+ new AddNewUserTask().execute(mNewUserName);
+ return;
+ }
+
+ // If the user doesn't want to be a guest or add a user, switch to the user selected
+ mUserManagerHelper.switchToUser(userRecord.mInfo);
+ });
+
+ }
+
+ private class AddNewUserTask extends AsyncTask<String, Void, UserInfo> {
+
+ @Override
+ protected UserInfo doInBackground(String... userNames) {
+ return mUserManagerHelper.createNewUser(userNames[0]);
+ }
+
+ @Override
+ protected void onPreExecute() {
+ }
+
+ @Override
+ protected void onPostExecute(UserInfo user) {
+ if (user != null) {
+ mUserManagerHelper.switchToUser(user);
+ }
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return mUsers.size();
+ }
+
+ /**
+ * Returns the default user icon. This icon is a circle with a letter in it. The letter is
+ * the first character in the username.
+ *
+ * @param record the profile of the user for which the icon should be created
+ */
+ private Bitmap getDefaultUserIcon(UserRecord record) {
+ CharSequence displayText;
+ boolean isAddUserText = false;
+ if (record.mIsAddUser) {
+ displayText = "+";
+ isAddUserText = true;
+ } else {
+ displayText = record.mInfo.name.subSequence(0, 1);
+ }
+ Bitmap out = Bitmap.createBitmap(mPodImageAvatarWidth, mPodImageAvatarHeight,
+ Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(out);
+
+ // Draw the circle background.
+ GradientDrawable shape = new GradientDrawable();
+ shape.setShape(GradientDrawable.RADIAL_GRADIENT);
+ shape.setGradientRadius(1.0f);
+ shape.setColor(mContext.getColor(R.color.car_user_switcher_no_user_image_bgcolor));
+ shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
+ shape.draw(canvas);
+
+ // Draw the letter in the center.
+ Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ paint.setColor(mContext.getColor(R.color.car_user_switcher_no_user_image_fgcolor));
+ paint.setTextAlign(Align.CENTER);
+ if (isAddUserText) {
+ paint.setTextSize(mRes.getDimensionPixelSize(
+ R.dimen.car_touch_target_size));
+ } else {
+ paint.setTextSize(mRes.getDimensionPixelSize(
+ R.dimen.car_fullscreen_user_pod_icon_text_size));
+ }
+
+ Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
+ // The Y coordinate is measured by taking half the height of the pod, but that would
+ // draw the character putting the bottom of the font in the middle of the pod. To
+ // correct this, half the difference between the top and bottom distance metrics of the
+ // font gives the offset of the font. Bottom is a positive value, top is negative, so
+ // the different is actually a sum. The "half" operation is then factored out.
+ canvas.drawText(displayText.toString(), mPodImageAvatarWidth / 2,
+ (mPodImageAvatarHeight - (metrics.bottom + metrics.top)) / 2, paint);
+
+ return out;
+ }
+
+ public class UserAdapterViewHolder extends RecyclerView.ViewHolder {
+
+ public ImageView mUserAvatarImageView;
+ public TextView mUserNameTextView;
+ public View mView;
+
+ public UserAdapterViewHolder(View view) {
+ super(view);
+ mView = view;
+ mUserAvatarImageView = (ImageView) view.findViewById(R.id.user_avatar);
+ mUserNameTextView = (TextView) view.findViewById(R.id.user_name);
+ }
+ }
+ }
+
+ /**
+ * Object wrapper class for the userInfo. Use it to distinguish if a profile is a
+ * guest profile, add user profile, or a current user.
+ */
+ public static final class UserRecord {
+
+ public final UserInfo mInfo;
+ public final boolean mIsGuest;
+ public final boolean mIsAddUser;
+ public final boolean mIsCurrent;
+
+ public UserRecord(UserInfo userInfo, boolean isGuest, boolean isAddUser,
+ boolean isCurrent) {
+ mInfo = userInfo;
+ mIsGuest = isGuest;
+ mIsAddUser = isAddUser;
+ mIsCurrent = isCurrent;
+ }
+ }
+
+ /**
+ * Listener used to notify when a user has been selected
+ */
+ interface UserSelectionListener {
+
+ void onUserSelected(UserRecord record);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
deleted file mode 100644
index 1bd820d..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (C) 2015 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.car;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
-import android.support.v4.view.PagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.qs.car.CarQSFragment;
-import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Vector;
-
-/**
- * Displays a ViewPager with icons for the users in the system to allow switching between users.
- * One of the uses of this is for the lock screen in auto.
- */
-public class UserGridView extends ViewPager implements
- UserInfoController.OnUserInfoChangedListener {
- private StatusBar mStatusBar;
- private UserSwitcherController mUserSwitcherController;
- private Adapter mAdapter;
- private UserSelectionListener mUserSelectionListener;
- private UserInfoController mUserInfoController;
- private Vector mUserContainers;
- private int mContainerWidth;
- private boolean mOverrideAlpha;
- private CarQSFragment.UserSwitchCallback mUserSwitchCallback;
-
- public UserGridView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public void init(StatusBar statusBar, UserSwitcherController userSwitcherController,
- boolean overrideAlpha) {
- mStatusBar = statusBar;
- mUserSwitcherController = userSwitcherController;
- mAdapter = new Adapter(mUserSwitcherController);
- mUserInfoController = Dependency.get(UserInfoController.class);
- mOverrideAlpha = overrideAlpha;
- // Whenever the container width changes, the containers must be refreshed. Instead of
- // doing an initial refreshContainers() to populate the containers, this listener will
- // refresh them on layout change because that affects how the users are split into
- // containers. Furthermore, at this point, the container width is unknown, so
- // refreshContainers() cannot populate any containers.
- addOnLayoutChangeListener(
- (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
- int newWidth = Math.max(left - right, right - left);
- if (mContainerWidth != newWidth) {
- mContainerWidth = newWidth;
- refreshContainers();
- }
- });
- }
-
- private void refreshContainers() {
- mUserContainers = new Vector();
-
- Context context = getContext();
- LayoutInflater inflater = LayoutInflater.from(context);
-
- for (int i = 0; i < mAdapter.getCount(); i++) {
- ViewGroup pods = (ViewGroup) inflater.inflate(
- R.layout.car_fullscreen_user_pod_container, null);
-
- int iconsPerPage = mAdapter.getIconsPerPage();
- int limit = Math.min(mUserSwitcherController.getUsers().size(), (i + 1) * iconsPerPage);
- for (int j = i * iconsPerPage; j < limit; j++) {
- View v = mAdapter.makeUserPod(inflater, context, j, pods);
- if (mOverrideAlpha) {
- v.setAlpha(1f);
- }
- pods.addView(v);
- // This is hacky, but the dividers on the pod container LinearLayout don't seem
- // to work for whatever reason. Instead, set a right margin on the pod if it's not
- // the right-most pod and there is more than one pod in the container.
- if (i < limit - 1 && limit > 1) {
- ViewGroup.MarginLayoutParams params =
- (ViewGroup.MarginLayoutParams) v.getLayoutParams();
- params.setMargins(0, 0, getResources().getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_margin_between), 0);
- v.setLayoutParams(params);
- }
- }
- mUserContainers.add(pods);
- }
-
- mAdapter = new Adapter(mUserSwitcherController);
- setAdapter(mAdapter);
- }
-
- @Override
- public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
- refreshContainers();
- }
-
- public void setUserSwitchCallback(CarQSFragment.UserSwitchCallback callback) {
- mUserSwitchCallback = callback;
- }
-
- public void onUserSwitched(int newUserId) {
- // Bring up security view after user switch is completed.
- post(this::showOfflineAuthUi);
- }
-
- public void setUserSelectionListener(UserSelectionListener userSelectionListener) {
- mUserSelectionListener = userSelectionListener;
- }
-
- public void setListening(boolean listening) {
- if (listening) {
- mUserInfoController.addCallback(this);
- } else {
- mUserInfoController.removeCallback(this);
- }
- }
-
- void showOfflineAuthUi() {
- // TODO: Show keyguard UI in-place.
- mStatusBar.executeRunnableDismissingKeyguard(null, null, true, true, true);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // Wrap content doesn't work in ViewPagers, so simulate the behavior in code.
- int height = 0;
- if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
- height = MeasureSpec.getSize(heightMeasureSpec);
- } else {
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- child.measure(widthMeasureSpec,
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- height = Math.max(child.getMeasuredHeight(), height);
- }
-
- // Respect the AT_MOST request from parent.
- if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
- height = Math.min(MeasureSpec.getSize(heightMeasureSpec), height);
- }
- }
- heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
-
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
- /**
- * This is a ViewPager.PagerAdapter which deletegates the work to a
- * UserSwitcherController.BaseUserAdapter. Java doesn't support multiple inheritance so we have
- * to use composition instead to achieve the same goal since both the base classes are abstract
- * classes and not interfaces.
- */
- private final class Adapter extends PagerAdapter {
- private final int mPodWidth;
- private final int mPodMarginBetween;
- private final int mPodImageAvatarWidth;
- private final int mPodImageAvatarHeight;
-
- private final WrappedBaseUserAdapter mUserAdapter;
-
- public Adapter(UserSwitcherController controller) {
- super();
- mUserAdapter = new WrappedBaseUserAdapter(controller, this);
-
- Resources res = getResources();
- mPodWidth = res.getDimensionPixelSize(R.dimen.car_fullscreen_user_pod_width);
- mPodMarginBetween = res.getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_margin_between);
- mPodImageAvatarWidth = res.getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_image_avatar_width);
- mPodImageAvatarHeight = res.getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_image_avatar_height);
- }
-
- @Override
- public void destroyItem(ViewGroup container, int position, Object object) {
- container.removeView((View) object);
- }
-
- private int getIconsPerPage() {
- // We need to know how many pods we need in this page. Each pod has its own width and
- // a margin between them. We can then divide the measured width of the parent by the
- // sum of pod width and margin to get the number of pods that will completely fit.
- // There is one less margin than the number of pods (eg. for 5 pods, there are 4
- // margins), so need to add the margin to the measured width to account for that.
- return (mContainerWidth + mPodMarginBetween) /
- (mPodWidth + mPodMarginBetween);
- }
-
- @Override
- public void finishUpdate(ViewGroup container) {
- if (mUserSwitchCallback != null) {
- mUserSwitchCallback.resetShowing();
- }
- }
-
- @Override
- public Object instantiateItem(ViewGroup container, int position) {
- if (position < mUserContainers.size()) {
- container.addView((View) mUserContainers.get(position));
- return mUserContainers.get(position);
- } else {
- return null;
- }
- }
-
- /**
- * Returns the default user icon. This icon is a circle with a letter in it. The letter is
- * the first character in the username.
- *
- * @param userName the username of the user for which the icon is to be created
- */
- private Bitmap getDefaultUserIcon(CharSequence userName) {
- CharSequence displayText = userName.subSequence(0, 1);
- Bitmap out = Bitmap.createBitmap(mPodImageAvatarWidth, mPodImageAvatarHeight,
- Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(out);
-
- // Draw the circle background.
- GradientDrawable shape = new GradientDrawable();
- shape.setShape(GradientDrawable.RADIAL_GRADIENT);
- shape.setGradientRadius(1.0f);
- shape.setColor(getContext().getColor(R.color.car_user_switcher_no_user_image_bgcolor));
- shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
- shape.draw(canvas);
-
- // Draw the letter in the center.
- Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setColor(getContext().getColor(R.color.car_user_switcher_no_user_image_fgcolor));
- paint.setTextAlign(Align.CENTER);
- paint.setTextSize(getResources().getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_icon_text_size));
- Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
- // The Y coordinate is measured by taking half the height of the pod, but that would
- // draw the character putting the bottom of the font in the middle of the pod. To
- // correct this, half the difference between the top and bottom distance metrics of the
- // font gives the offset of the font. Bottom is a positive value, top is negative, so
- // the different is actually a sum. The "half" operation is then factored out.
- canvas.drawText(displayText.toString(), mPodImageAvatarWidth / 2,
- (mPodImageAvatarHeight - (metrics.bottom + metrics.top)) / 2, paint);
-
- return out;
- }
-
- private View makeUserPod(LayoutInflater inflater, Context context,
- int position, ViewGroup parent) {
- final UserSwitcherController.UserRecord record = mUserAdapter.getItem(position);
- View view = inflater.inflate(R.layout.car_fullscreen_user_pod, parent, false);
-
- TextView nameView = view.findViewById(R.id.user_name);
- if (record != null) {
- nameView.setText(mUserAdapter.getName(context, record));
- view.setActivated(record.isCurrent);
- } else {
- nameView.setText(context.getString(R.string.unknown_user_label));
- }
-
- ImageView iconView = (ImageView) view.findViewById(R.id.user_avatar);
- if (record == null || (record.picture == null && !record.isAddUser)) {
- iconView.setImageBitmap(getDefaultUserIcon(nameView.getText()));
- } else if (record.isAddUser) {
- Drawable icon = context.getDrawable(R.drawable.ic_add_circle_qs);
- icon.setTint(context.getColor(R.color.car_user_switcher_no_user_image_bgcolor));
- iconView.setImageDrawable(icon);
- } else {
- iconView.setImageBitmap(record.picture);
- }
-
- iconView.setOnClickListener(v -> {
- if (record == null) {
- return;
- }
-
- if (mUserSelectionListener != null) {
- mUserSelectionListener.onUserSelected(record);
- }
-
- if (record.isCurrent) {
- showOfflineAuthUi();
- } else {
- mUserSwitcherController.switchTo(record);
- }
- });
-
- return view;
- }
-
- @Override
- public int getCount() {
- int iconsPerPage = getIconsPerPage();
- if (iconsPerPage == 0) {
- return 0;
- }
- return (int) Math.ceil((double) mUserAdapter.getCount() / getIconsPerPage());
- }
-
- public void refresh() {
- mUserAdapter.refresh();
- }
-
- @Override
- public boolean isViewFromObject(View view, Object object) {
- return view == object;
- }
- }
-
- private final class WrappedBaseUserAdapter extends UserSwitcherController.BaseUserAdapter {
- private final Adapter mContainer;
-
- public WrappedBaseUserAdapter(UserSwitcherController controller, Adapter container) {
- super(controller);
- mContainer = container;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- throw new UnsupportedOperationException("unused");
- }
-
- @Override
- public void notifyDataSetChanged() {
- super.notifyDataSetChanged();
- mContainer.notifyDataSetChanged();
- }
- }
-
- interface UserSelectionListener {
- void onUserSelected(UserSwitcherController.UserRecord record);
- };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 3bbfe3c..b8bce95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -238,6 +238,7 @@
t.deferTransactionUntilSurface(app.leash, systemUiSurface,
systemUiSurface.getNextFrameNumber());
}
+ t.setEarlyWakeup();
t.apply();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index d38c083..bbdaa99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -112,9 +112,9 @@
mCurrentInFrontTint = Color.BLACK;
mCurrentBehindTint = Color.BLACK;
mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG;
- // DisplayPowerManager will blank the screen for us, we just need
- // to set our state.
- mAnimateChange = !mDisplayRequiresBlanking;
+ // DisplayPowerManager may blank the screen for us,
+ // in this case we just need to set our state.
+ mAnimateChange = mDozeParameters.shouldControlScreenOff();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 13157fe..a2d2615 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -212,7 +212,6 @@
.setDuration(300)
.setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator())
.withEndAction(() -> {
- mWindow.getDecorView().requestAccessibilityFocus();
if (!Prefs.getBoolean(mContext, Prefs.Key.TOUCHED_RINGER_TOGGLE, false)) {
mRingerIcon.postOnAnimationDelayed(mSinglePress, 1500);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 1e8e14d..27c00c0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -246,7 +246,7 @@
}
@Test
- public void scrimBlanksBeforeLeavingAoD() {
+ public void scrimBlanksBeforeLeavingAod() {
// Simulate unlock with fingerprint
mScrimController.transitionTo(ScrimState.AOD);
mScrimController.finishAnimationsImmediately();
@@ -455,6 +455,20 @@
}
}
+ @Test
+ public void testAnimatesTransitionToAod() {
+ when(mDozeParamenters.shouldControlScreenOff()).thenReturn(false);
+ ScrimState.AOD.prepare(ScrimState.KEYGUARD);
+ Assert.assertFalse("No animation when ColorFade kicks in",
+ ScrimState.AOD.getAnimateChange());
+
+ reset(mDozeParamenters);
+ when(mDozeParamenters.shouldControlScreenOff()).thenReturn(true);
+ ScrimState.AOD.prepare(ScrimState.KEYGUARD);
+ Assert.assertTrue("Animate scrims when ColorFade won't be triggered",
+ ScrimState.AOD.getAnimateChange());
+ }
+
/**
* Conserves old notification density after leaving state and coming back.
*
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index e05416e..595a1d9 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -422,6 +422,16 @@
// Indicates the number of times a scan request from an external background app was throttled.
optional int32 num_external_background_app_oneshot_scan_requests_throttled = 106;
+
+ // WifiLastResortWatchdog time milliseconds delta between trigger and first connection success
+ optional int64 watchdog_trigger_to_connection_success_duration_ms = 107 [default = -1];
+
+ // The number of times wifi experienced failures after watchdog has already been triggered and is
+ // waiting for a connection success
+ optional int64 watchdog_total_connection_failure_count_after_trigger = 108;
+
+ // Number of times DFS channel scans are requested in single scan requests.
+ optional int32 num_oneshot_has_dfs_channel_scans = 109;
}
// Information that gets logged for every WiFi connection.
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index e20c180..06707da 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -99,6 +99,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -1971,8 +1972,8 @@
return;
}
- if (value != null && !value.equals(viewState.getCurrentValue())) {
- if (value.isEmpty()
+ if (!Objects.equals(value, viewState.getCurrentValue())) {
+ if ((value == null || value.isEmpty())
&& viewState.getCurrentValue() != null
&& viewState.getCurrentValue().isText()
&& viewState.getCurrentValue().getTextValue() != null
@@ -1993,18 +1994,26 @@
// Must check if this update was caused by autofilling the view, in which
// case we just update the value, but not the UI.
final AutofillValue filledValue = viewState.getAutofilledValue();
- if (value.equals(filledValue)) {
+ if (filledValue != null && filledValue.equals(value)) {
+ if (sVerbose) {
+ Slog.v(TAG, "ignoring autofilled change on id " + id);
+ }
return;
}
// Update the internal state...
viewState.setState(ViewState.STATE_CHANGED);
//..and the UI
- if (value.isText()) {
- getUiForShowing().filterFillUi(value.getTextValue().toString(), this);
+ final String filterText;
+ if (value == null || !value.isText()) {
+ filterText = null;
} else {
- getUiForShowing().filterFillUi(null, this);
+ final CharSequence text = value.getTextValue();
+ // Text should never be null, but it doesn't hurt to check to avoid a
+ // system crash...
+ filterText = (text == null) ? null : text.toString();
}
+ getUiForShowing().filterFillUi(filterText, this);
}
break;
case ACTION_VIEW_ENTERED:
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 33f7769..80d7ac9 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -128,6 +128,30 @@
}
};
+ public static final class Lifecycle extends SystemService {
+ private final NetworkScoreService mService;
+
+ public Lifecycle(Context context) {
+ super(context);
+ mService = new NetworkScoreService(context);
+ }
+
+ @Override
+ public void onStart() {
+ Log.i(TAG, "Registering " + Context.NETWORK_SCORE_SERVICE);
+ publishBinderService(Context.NETWORK_SCORE_SERVICE, mService);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_SYSTEM_SERVICES_READY) {
+ mService.systemReady();
+ } else if (phase == PHASE_BOOT_COMPLETED) {
+ mService.systemRunning();
+ }
+ }
+ }
+
/**
* Clears scores when the active scorer package is no longer valid and
* manages the service connection.
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 752c44a..66c2b07 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -53,6 +53,7 @@
import android.provider.Settings.SettingNotFoundException;
import android.util.DebugUtils;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.InputDevice;
import android.media.AudioAttributes;
@@ -91,7 +92,7 @@
private final boolean mAllowPriorityVibrationsInLowPowerMode;
private final boolean mSupportsAmplitudeControl;
private final int mDefaultVibrationAmplitude;
- private final VibrationEffect[] mFallbackEffects;
+ private final SparseArray<VibrationEffect> mFallbackEffects;
private final WorkSource mTmpWorkSource = new WorkSource();
private final Handler mH = new Handler();
private final Object mLock = new Object();
@@ -177,6 +178,7 @@
switch (prebaked.getId()) {
case VibrationEffect.EFFECT_CLICK:
case VibrationEffect.EFFECT_DOUBLE_CLICK:
+ case VibrationEffect.EFFECT_HEAVY_CLICK:
case VibrationEffect.EFFECT_TICK:
return true;
default:
@@ -293,7 +295,11 @@
com.android.internal.R.array.config_clockTickVibePattern);
VibrationEffect tickEffect = createEffect(tickEffectTimings);
- mFallbackEffects = new VibrationEffect[] { clickEffect, doubleClickEffect, tickEffect };
+ mFallbackEffects = new SparseArray<VibrationEffect>();
+ mFallbackEffects.put(VibrationEffect.EFFECT_CLICK, clickEffect);
+ mFallbackEffects.put(VibrationEffect.EFFECT_DOUBLE_CLICK, doubleClickEffect);
+ mFallbackEffects.put(VibrationEffect.EFFECT_TICK, tickEffect);
+ mFallbackEffects.put(VibrationEffect.EFFECT_HEAVY_CLICK, clickEffect);
}
private static VibrationEffect createEffect(long[] timings) {
@@ -960,10 +966,7 @@
}
private VibrationEffect getFallbackEffect(int effectId) {
- if (effectId < 0 || effectId >= mFallbackEffects.length) {
- return null;
- }
- return mFallbackEffects[effectId];
+ return mFallbackEffects.get(effectId);
}
/**
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index 1d305fb..365c436 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -1255,7 +1255,7 @@
for (int i = 0; i < recentsCount; i++) {
final TaskRecord tr = mTasks.get(i);
if (task != tr) {
- if (!task.hasCompatibleActivityType(tr)) {
+ if (!task.hasCompatibleActivityType(tr) || task.userId != tr.userId) {
continue;
}
final Intent trIntent = tr.intent;
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 66817fa..736aa46 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -127,7 +127,7 @@
* Any function with the suffix 'Locked' also needs to lock on {@link #mJobs}.
* @hide
*/
-public final class JobSchedulerService extends com.android.server.SystemService
+public class JobSchedulerService extends com.android.server.SystemService
implements StateChangedListener, JobCompletedListener {
public static final String TAG = "JobScheduler";
public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -781,6 +781,10 @@
}
};
+ public Context getTestableContext() {
+ return getContext();
+ }
+
public Object getLock() {
return mLock;
}
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index 8365fd2..0c66c5b 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -30,12 +30,12 @@
import android.net.NetworkPolicyManager;
import android.net.NetworkRequest;
import android.net.TrafficStats;
-import android.os.Process;
import android.os.UserHandle;
import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
@@ -46,6 +46,7 @@
import com.android.server.job.JobServiceContext;
import com.android.server.job.StateControllerProto;
+import java.util.Objects;
import java.util.function.Predicate;
/**
@@ -63,7 +64,6 @@
private final ConnectivityManager mConnManager;
private final NetworkPolicyManager mNetPolicyManager;
- private boolean mConnected;
@GuardedBy("mLock")
private final ArraySet<JobStatus> mTrackedJobs = new ArraySet<>();
@@ -74,9 +74,11 @@
mConnManager = mContext.getSystemService(ConnectivityManager.class);
mNetPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
- mConnected = false;
+ // We're interested in all network changes; internally we match these
+ // network changes against the active network for each UID with jobs.
+ final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
+ mConnManager.registerNetworkCallback(request, mNetworkCallback);
- mConnManager.registerDefaultNetworkCallback(mNetworkCallback);
mNetPolicyManager.registerListener(mNetPolicyListener);
}
@@ -198,14 +200,18 @@
}
private boolean updateConstraintsSatisfied(JobStatus jobStatus) {
+ final Network network = mConnManager.getActiveNetworkForUid(jobStatus.getSourceUid());
+ final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(network);
+ return updateConstraintsSatisfied(jobStatus, network, capabilities);
+ }
+
+ private boolean updateConstraintsSatisfied(JobStatus jobStatus, Network network,
+ NetworkCapabilities capabilities) {
// TODO: consider matching against non-active networks
- final int jobUid = jobStatus.getSourceUid();
final boolean ignoreBlocked = (jobStatus.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
-
- final Network network = mConnManager.getActiveNetworkForUid(jobUid, ignoreBlocked);
- final NetworkInfo info = mConnManager.getNetworkInfoForUid(network, jobUid, ignoreBlocked);
- final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(network);
+ final NetworkInfo info = mConnManager.getNetworkInfoForUid(network,
+ jobStatus.getSourceUid(), ignoreBlocked);
final boolean connected = (info != null) && info.isConnected();
final boolean satisfied = isSatisfied(jobStatus, network, capabilities, mConstants);
@@ -218,12 +224,6 @@
// using non-default routes.
jobStatus.network = network;
- // Track system-uid connected/validated as a general reportable proxy for the
- // overall state of connectivity constraint satisfiability.
- if (jobUid == Process.SYSTEM_UID) {
- mConnected = connected;
- }
-
if (DEBUG) {
Slog.i(TAG, "Connectivity " + (changed ? "CHANGED" : "unchanged")
+ " for " + jobStatus + ": connected=" + connected
@@ -233,18 +233,48 @@
}
/**
- * Update all jobs tracked by this controller.
+ * Update any jobs tracked by this controller that match given filters.
*
- * @param uid only update jobs belonging to this UID, or {@code -1} to
+ * @param filterUid only update jobs belonging to this UID, or {@code -1} to
* update all tracked jobs.
+ * @param filterNetwork only update jobs that would use this
+ * {@link Network}, or {@code null} to update all tracked jobs.
*/
- private void updateTrackedJobs(int uid) {
+ private void updateTrackedJobs(int filterUid, Network filterNetwork) {
synchronized (mLock) {
+ // Since this is a really hot codepath, temporarily cache any
+ // answers that we get from ConnectivityManager.
+ final SparseArray<Network> uidToNetwork = new SparseArray<>();
+ final SparseArray<NetworkCapabilities> networkToCapabilities = new SparseArray<>();
+
boolean changed = false;
- for (int i = mTrackedJobs.size()-1; i >= 0; i--) {
+ for (int i = mTrackedJobs.size() - 1; i >= 0; i--) {
final JobStatus js = mTrackedJobs.valueAt(i);
- if (uid == -1 || uid == js.getSourceUid()) {
- changed |= updateConstraintsSatisfied(js);
+ final int uid = js.getSourceUid();
+
+ final boolean uidMatch = (filterUid == -1 || filterUid == uid);
+ if (uidMatch) {
+ Network network = uidToNetwork.get(uid);
+ if (network == null) {
+ network = mConnManager.getActiveNetworkForUid(uid);
+ uidToNetwork.put(uid, network);
+ }
+
+ // Update either when we have a network match, or when the
+ // job hasn't yet been evaluated against the currently
+ // active network; typically when we just lost a network.
+ final boolean networkMatch = (filterNetwork == null
+ || Objects.equals(filterNetwork, network));
+ final boolean forceUpdate = !Objects.equals(js.network, network);
+ if (networkMatch || forceUpdate) {
+ final int netId = network != null ? network.netId : -1;
+ NetworkCapabilities capabilities = networkToCapabilities.get(netId);
+ if (capabilities == null) {
+ capabilities = mConnManager.getNetworkCapabilities(network);
+ networkToCapabilities.put(netId, capabilities);
+ }
+ changed |= updateConstraintsSatisfied(js, network, capabilities);
+ }
}
}
if (changed) {
@@ -273,19 +303,19 @@
private final NetworkCallback mNetworkCallback = new NetworkCallback() {
@Override
- public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
+ public void onCapabilitiesChanged(Network network, NetworkCapabilities capabilities) {
if (DEBUG) {
- Slog.v(TAG, "onCapabilitiesChanged() : " + networkCapabilities);
+ Slog.v(TAG, "onCapabilitiesChanged: " + network);
}
- updateTrackedJobs(-1);
+ updateTrackedJobs(-1, network);
}
@Override
public void onLost(Network network) {
if (DEBUG) {
- Slog.v(TAG, "Network lost");
+ Slog.v(TAG, "onLost: " + network);
}
- updateTrackedJobs(-1);
+ updateTrackedJobs(-1, network);
}
};
@@ -293,25 +323,9 @@
@Override
public void onUidRulesChanged(int uid, int uidRules) {
if (DEBUG) {
- Slog.v(TAG, "Uid rules changed for " + uid);
+ Slog.v(TAG, "onUidRulesChanged: " + uid);
}
- updateTrackedJobs(uid);
- }
-
- @Override
- public void onRestrictBackgroundChanged(boolean restrictBackground) {
- if (DEBUG) {
- Slog.v(TAG, "Background restriction change to " + restrictBackground);
- }
- updateTrackedJobs(-1);
- }
-
- @Override
- public void onUidPoliciesChanged(int uid, int uidPolicies) {
- if (DEBUG) {
- Slog.v(TAG, "Uid policy changed for " + uid);
- }
- updateTrackedJobs(uid);
+ updateTrackedJobs(uid, null);
}
};
@@ -319,9 +333,6 @@
@Override
public void dumpControllerStateLocked(IndentingPrintWriter pw,
Predicate<JobStatus> predicate) {
- pw.println("System connected: " + mConnected);
- pw.println();
-
for (int i = 0; i < mTrackedJobs.size(); i++) {
final JobStatus js = mTrackedJobs.valueAt(i);
if (predicate.test(js)) {
@@ -343,8 +354,6 @@
final long token = proto.start(fieldId);
final long mToken = proto.start(StateControllerProto.CONNECTIVITY);
- proto.write(StateControllerProto.ConnectivityController.IS_CONNECTED, mConnected);
-
for (int i = 0; i < mTrackedJobs.size(); i++) {
final JobStatus js = mTrackedJobs.valueAt(i);
if (!predicate.test(js)) {
diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java
index 495109d..c2be283 100644
--- a/services/core/java/com/android/server/job/controllers/StateController.java
+++ b/services/core/java/com/android/server/job/controllers/StateController.java
@@ -41,7 +41,7 @@
StateController(JobSchedulerService service) {
mService = service;
mStateChangedListener = service;
- mContext = service.getContext();
+ mContext = service.getTestableContext();
mLock = service.getLock();
mConstants = service.getConstants();
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 9a25dcc..0779704 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -8013,29 +8013,35 @@
private VibrationEffect getVibrationEffect(int effectId) {
long[] pattern;
switch (effectId) {
- case HapticFeedbackConstants.LONG_PRESS:
- pattern = mLongPressVibePattern;
- break;
case HapticFeedbackConstants.CLOCK_TICK:
+ case HapticFeedbackConstants.CONTEXT_CLICK:
return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
+ case HapticFeedbackConstants.KEYBOARD_RELEASE:
+ case HapticFeedbackConstants.TEXT_HANDLE_MOVE:
+ case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE:
+ case HapticFeedbackConstants.ENTRY_BUMP:
+ case HapticFeedbackConstants.DRAG_CROSSING:
+ case HapticFeedbackConstants.GESTURE_END:
+ return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false);
+ case HapticFeedbackConstants.KEYBOARD_TAP: // == KEYBOARD_PRESS
+ case HapticFeedbackConstants.VIRTUAL_KEY:
+ case HapticFeedbackConstants.EDGE_RELEASE:
+ case HapticFeedbackConstants.CONFIRM:
+ case HapticFeedbackConstants.GESTURE_START:
+ return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
+ case HapticFeedbackConstants.LONG_PRESS:
+ case HapticFeedbackConstants.EDGE_SQUEEZE:
+ return VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
+ case HapticFeedbackConstants.REJECT:
+ return VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
+
case HapticFeedbackConstants.CALENDAR_DATE:
pattern = mCalendarDateVibePattern;
break;
case HapticFeedbackConstants.SAFE_MODE_ENABLED:
pattern = mSafeModeEnabledVibePattern;
break;
- case HapticFeedbackConstants.CONTEXT_CLICK:
- return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
- case HapticFeedbackConstants.VIRTUAL_KEY:
- return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
- case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE:
- return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false);
- case HapticFeedbackConstants.KEYBOARD_PRESS: // == HapticFeedbackConstants.KEYBOARD_TAP
- return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
- case HapticFeedbackConstants.KEYBOARD_RELEASE:
- return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false);
- case HapticFeedbackConstants.TEXT_HANDLE_MOVE:
- return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false);
+
default:
return null;
}
diff --git a/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java b/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java
index 416469b..9c00d1a 100644
--- a/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java
+++ b/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java
@@ -37,6 +37,8 @@
private ArrayList<Runnable> mTmpRunnableList = new ArrayList<>();
+ private boolean mEndingDeferredFinish;
+
/**
* Notifies that an {@link AppWindowToken} has started animating.
*/
@@ -50,6 +52,11 @@
void notifyFinished(AppWindowToken token) {
mAnimatingTokens.remove(token);
mFinishedTokens.remove(token);
+
+ // If we were the last token, make sure the end all deferred finishes.
+ if (mAnimatingTokens.isEmpty()) {
+ endDeferringFinished();
+ }
}
/**
@@ -78,16 +85,28 @@
}
private void endDeferringFinished() {
- // Copy it into a separate temp list to avoid modifying the collection while iterating as
- // calling the callback may call back into notifyFinished.
- for (int i = mFinishedTokens.size() - 1; i >= 0; i--) {
- mTmpRunnableList.add(mFinishedTokens.valueAt(i));
+
+ // Don't start recursing. Running the finished listener invokes notifyFinished, which may
+ // invoked us again.
+ if (mEndingDeferredFinish) {
+ return;
}
- mFinishedTokens.clear();
- for (int i = mTmpRunnableList.size() - 1; i >= 0; i--) {
- mTmpRunnableList.get(i).run();
+ try {
+ mEndingDeferredFinish = true;
+
+ // Copy it into a separate temp list to avoid modifying the collection while iterating
+ // as calling the callback may call back into notifyFinished.
+ for (int i = mFinishedTokens.size() - 1; i >= 0; i--) {
+ mTmpRunnableList.add(mFinishedTokens.valueAt(i));
+ }
+ mFinishedTokens.clear();
+ for (int i = mTmpRunnableList.size() - 1; i >= 0; i--) {
+ mTmpRunnableList.get(i).run();
+ }
+ mTmpRunnableList.clear();
+ } finally {
+ mEndingDeferredFinish = false;
}
- mTmpRunnableList.clear();
}
void dump(PrintWriter pw, String header, String prefix) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 8fa94fb..9a4db65 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1714,7 +1714,8 @@
adapter = new LocalAnimationAdapter(
new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
mService.mAppTransition.canSkipFirstFrame(),
- mService.mAppTransition.getAppStackClipMode()),
+ mService.mAppTransition.getAppStackClipMode(),
+ true /* isAppAnimation */),
mService.mSurfaceAnimationRunner);
if (a.getZAdjustment() == Animation.ZORDER_TOP) {
mNeedsZBoost = true;
diff --git a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
index 529aacc..d89d6f0 100644
--- a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
@@ -146,6 +146,13 @@
return false;
}
+ /**
+ * @return {@code true} if we need to wake-up SurfaceFlinger earlier during this animation.
+ *
+ * @see Transaction#setEarlyWakeup
+ */
+ default boolean needsEarlyWakeup() { return false; }
+
void dump(PrintWriter pw, String prefix);
default void writeToProto(ProtoOutputStream proto, long fieldId) {
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
index 98fcb0b..7211533 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -220,6 +220,9 @@
}
private void applyTransformation(RunningAnimation a, Transaction t, long currentPlayTime) {
+ if (a.mAnimSpec.needsEarlyWakeup()) {
+ t.setEarlyWakeup();
+ }
a.mAnimSpec.apply(t, a.mLeash, currentPlayTime);
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
index 7b7cb30..548e23a 100644
--- a/services/core/java/com/android/server/wm/WindowAnimationSpec.java
+++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
@@ -47,21 +47,24 @@
private final Point mPosition = new Point();
private final ThreadLocal<TmpValues> mThreadLocalTmps = ThreadLocal.withInitial(TmpValues::new);
private final boolean mCanSkipFirstFrame;
+ private final boolean mIsAppAnimation;
private final Rect mStackBounds = new Rect();
private int mStackClipMode;
private final Rect mTmpRect = new Rect();
public WindowAnimationSpec(Animation animation, Point position, boolean canSkipFirstFrame) {
- this(animation, position, null /* stackBounds */, canSkipFirstFrame, STACK_CLIP_NONE);
+ this(animation, position, null /* stackBounds */, canSkipFirstFrame, STACK_CLIP_NONE,
+ false /* isAppAnimation */);
}
public WindowAnimationSpec(Animation animation, Point position, Rect stackBounds,
- boolean canSkipFirstFrame, int stackClipMode) {
+ boolean canSkipFirstFrame, int stackClipMode, boolean isAppAnimation) {
mAnimation = animation;
if (position != null) {
mPosition.set(position.x, position.y);
}
mCanSkipFirstFrame = canSkipFirstFrame;
+ mIsAppAnimation = isAppAnimation;
mStackClipMode = stackClipMode;
if (stackBounds != null) {
mStackBounds.set(stackBounds);
@@ -135,6 +138,11 @@
}
@Override
+ public boolean needsEarlyWakeup() {
+ return mIsAppAnimation;
+ }
+
+ @Override
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.println(mAnimation);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 84df128..c5269e1 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2001,6 +2001,11 @@
// Try starting an animation.
if (mWinAnimator.applyAnimationLocked(transit, false)) {
mAnimatingExit = true;
+
+ // mAnimatingExit affects canAffectSystemUiFlags(). Run layout such that
+ // any change from that is performed immediately.
+ setDisplayLayoutNeeded();
+ mService.requestTraversal();
}
//TODO (multidisplay): Magnification is supported only for the default display.
if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 6f50ee2..5519d22 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -725,7 +725,6 @@
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
- NetworkScoreService networkScore = null;
NsdService serviceDiscovery= null;
WindowManagerService wm = null;
SerialService serial = null;
@@ -1090,12 +1089,7 @@
}
traceBeginAndSlog("StartNetworkScoreService");
- try {
- networkScore = new NetworkScoreService(context);
- ServiceManager.addService(Context.NETWORK_SCORE_SERVICE, networkScore);
- } catch (Throwable e) {
- reportWtf("starting Network Score Service", e);
- }
+ mSystemServiceManager.startService(NetworkScoreService.Lifecycle.class);
traceEnd();
traceBeginAndSlog("StartNetworkStatsService");
@@ -1728,7 +1722,6 @@
final NetworkStatsService networkStatsF = networkStats;
final NetworkPolicyManagerService networkPolicyF = networkPolicy;
final ConnectivityService connectivityF = connectivity;
- final NetworkScoreService networkScoreF = networkScore;
final LocationManagerService locationF = location;
final CountryDetectorService countryDetectorF = countryDetector;
final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater;
@@ -1789,13 +1782,6 @@
reportWtf("starting System UI", e);
}
traceEnd();
- traceBeginAndSlog("MakeNetworkScoreReady");
- try {
- if (networkScoreF != null) networkScoreF.systemReady();
- } catch (Throwable e) {
- reportWtf("making Network Score Service ready", e);
- }
- traceEnd();
traceBeginAndSlog("MakeNetworkManagementServiceReady");
try {
if (networkManagementF != null) networkManagementF.systemReady();
@@ -1917,13 +1903,6 @@
}
traceEnd();
- traceBeginAndSlog("MakeNetworkScoreServiceReady");
- try {
- if (networkScoreF != null) networkScoreF.systemRunning();
- } catch (Throwable e) {
- reportWtf("Notifying NetworkScoreService running", e);
- }
- traceEnd();
traceBeginAndSlog("IncidentDaemonReady");
try {
// TODO: Switch from checkService to getService once it's always
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index edc6509..1192114 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -327,6 +327,33 @@
}
@Test
+ public void testAddTaskCompatibleActivityTypeDifferentUser_expectNoRemove() throws Exception {
+ Configuration config1 = new Configuration();
+ config1.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
+ TaskRecord task1 = createTaskBuilder(".Task1")
+ .setFlags(FLAG_ACTIVITY_NEW_TASK)
+ .setStack(mStack)
+ .setUserId(TEST_USER_0_ID)
+ .build();
+ task1.onConfigurationChanged(config1);
+ assertTrue(task1.getActivityType() == ACTIVITY_TYPE_UNDEFINED);
+ mRecentTasks.add(task1);
+ mCallbacksRecorder.clear();
+
+ TaskRecord task2 = createTaskBuilder(".Task1")
+ .setFlags(FLAG_ACTIVITY_NEW_TASK)
+ .setStack(mStack)
+ .setUserId(TEST_USER_1_ID)
+ .build();
+ assertTrue(task2.getActivityType() == ACTIVITY_TYPE_STANDARD);
+ mRecentTasks.add(task2);
+ assertTrue(mCallbacksRecorder.added.size() == 1);
+ assertTrue(mCallbacksRecorder.added.contains(task2));
+ assertTrue(mCallbacksRecorder.trimmed.isEmpty());
+ assertTrue(mCallbacksRecorder.removed.isEmpty());
+ }
+
+ @Test
public void testUsersTasks() throws Exception {
mRecentTasks.setOnlyTestVisibleRange();
diff --git a/services/tests/servicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/servicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
index 8874894..5b59e60 100644
--- a/services/tests/servicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -23,19 +23,28 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
import android.app.job.JobInfo;
import android.content.ComponentName;
+import android.content.Context;
import android.content.pm.PackageManagerInternal;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkPolicyManager;
import android.os.Build;
-import android.os.Handler;
import android.os.SystemClock;
-import android.support.test.runner.AndroidJUnit4;
import android.util.DataUnit;
import com.android.server.LocalServices;
@@ -45,14 +54,26 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
import java.time.Clock;
import java.time.ZoneOffset;
-@RunWith(AndroidJUnit4.class)
+@RunWith(MockitoJUnitRunner.class)
public class ConnectivityControllerTest {
+
+ @Mock private Context mContext;
+ @Mock private ConnectivityManager mConnManager;
+ @Mock private NetworkPolicyManager mNetPolicyManager;
+ @Mock private JobSchedulerService mService;
+
private Constants mConstants;
+ private static final int UID_RED = 10001;
+ private static final int UID_BLUE = 10002;
+
@Before
public void setUp() throws Exception {
// Assume all packages are current SDK
@@ -72,6 +93,19 @@
// Assume default constants for now
mConstants = new Constants();
+
+ // Get our mocks ready
+ when(mContext.getSystemServiceName(ConnectivityManager.class))
+ .thenReturn(Context.CONNECTIVITY_SERVICE);
+ when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
+ .thenReturn(mConnManager);
+ when(mContext.getSystemServiceName(NetworkPolicyManager.class))
+ .thenReturn(Context.NETWORK_POLICY_SERVICE);
+ when(mContext.getSystemService(Context.NETWORK_POLICY_SERVICE))
+ .thenReturn(mNetPolicyManager);
+ when(mService.getTestableContext()).thenReturn(mContext);
+ when(mService.getLock()).thenReturn(mService);
+ when(mService.getConstants()).thenReturn(mConstants);
}
@Test
@@ -155,6 +189,99 @@
}
}
+ @Test
+ public void testUpdates() throws Exception {
+ final ArgumentCaptor<NetworkCallback> callback = ArgumentCaptor
+ .forClass(NetworkCallback.class);
+ doNothing().when(mConnManager).registerNetworkCallback(any(), callback.capture());
+
+ final ConnectivityController controller = new ConnectivityController(mService);
+
+ final Network meteredNet = new Network(101);
+ final NetworkCapabilities meteredCaps = createCapabilities();
+ final Network unmeteredNet = new Network(202);
+ final NetworkCapabilities unmeteredCaps = createCapabilities()
+ .addCapability(NET_CAPABILITY_NOT_METERED);
+
+ final JobStatus red = createJobStatus(createJob()
+ .setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1), 0)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED), UID_RED);
+ final JobStatus blue = createJobStatus(createJob()
+ .setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1), 0)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY), UID_BLUE);
+
+ // Pretend we're offline when job is added
+ {
+ reset(mConnManager);
+ answerNetwork(UID_RED, null, null);
+ answerNetwork(UID_BLUE, null, null);
+
+ controller.maybeStartTrackingJobLocked(red, null);
+ controller.maybeStartTrackingJobLocked(blue, null);
+
+ assertFalse(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertFalse(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ }
+
+ // Metered network
+ {
+ reset(mConnManager);
+ answerNetwork(UID_RED, meteredNet, meteredCaps);
+ answerNetwork(UID_BLUE, meteredNet, meteredCaps);
+
+ callback.getValue().onCapabilitiesChanged(meteredNet, meteredCaps);
+
+ assertFalse(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ }
+
+ // Unmetered network background
+ {
+ reset(mConnManager);
+ answerNetwork(UID_RED, meteredNet, meteredCaps);
+ answerNetwork(UID_BLUE, meteredNet, meteredCaps);
+
+ callback.getValue().onCapabilitiesChanged(unmeteredNet, unmeteredCaps);
+
+ assertFalse(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ }
+
+ // Lost metered network
+ {
+ reset(mConnManager);
+ answerNetwork(UID_RED, unmeteredNet, unmeteredCaps);
+ answerNetwork(UID_BLUE, unmeteredNet, unmeteredCaps);
+
+ callback.getValue().onLost(meteredNet);
+
+ assertTrue(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ }
+
+ // Specific UID was blocked
+ {
+ reset(mConnManager);
+ answerNetwork(UID_RED, null, null);
+ answerNetwork(UID_BLUE, unmeteredNet, unmeteredCaps);
+
+ callback.getValue().onCapabilitiesChanged(unmeteredNet, unmeteredCaps);
+
+ assertFalse(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ }
+ }
+
+ private void answerNetwork(int uid, Network net, NetworkCapabilities caps) {
+ when(mConnManager.getActiveNetworkForUid(eq(uid))).thenReturn(net);
+ when(mConnManager.getNetworkCapabilities(eq(net))).thenReturn(caps);
+ if (net != null) {
+ final NetworkInfo ni = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, null, null);
+ ni.setDetailedState(DetailedState.CONNECTED, null, null);
+ when(mConnManager.getNetworkInfoForUid(eq(net), eq(uid), anyBoolean())).thenReturn(ni);
+ }
+ }
+
private static NetworkCapabilities createCapabilities() {
return new NetworkCapabilities().addCapability(NET_CAPABILITY_INTERNET)
.addCapability(NET_CAPABILITY_VALIDATED);
@@ -165,12 +292,22 @@
}
private static JobStatus createJobStatus(JobInfo.Builder job) {
- return createJobStatus(job, 0, Long.MAX_VALUE);
+ return createJobStatus(job, android.os.Process.NOBODY_UID, 0, Long.MAX_VALUE);
}
- private static JobStatus createJobStatus(JobInfo.Builder job, long earliestRunTimeElapsedMillis,
- long latestRunTimeElapsedMillis) {
- return new JobStatus(job.build(), 0, null, -1, 0, 0, null, earliestRunTimeElapsedMillis,
- latestRunTimeElapsedMillis, 0, 0, null, 0);
+ private static JobStatus createJobStatus(JobInfo.Builder job, int uid) {
+ return createJobStatus(job, uid, 0, Long.MAX_VALUE);
+ }
+
+ private static JobStatus createJobStatus(JobInfo.Builder job,
+ long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis) {
+ return createJobStatus(job, android.os.Process.NOBODY_UID,
+ earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis);
+ }
+
+ private static JobStatus createJobStatus(JobInfo.Builder job, int uid,
+ long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis) {
+ return new JobStatus(job.build(), uid, null, -1, 0, 0, null,
+ earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis, 0, 0, null, 0);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java b/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
index 8b78f10..164c80b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
@@ -88,4 +88,25 @@
verify(mMockEndDeferFinishCallback1).run();
verifyZeroInteractions(mMockEndDeferFinishCallback2);
}
+
+ @Test
+ public void testContainerRemoved() throws Exception {
+ final AppWindowToken window1 = createAppWindowToken(mDisplayContent,
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final AppWindowToken window2 = createAppWindow(window1.getTask(), ACTIVITY_TYPE_STANDARD,
+ "window2").mAppToken;
+ final AnimatingAppWindowTokenRegistry registry =
+ window1.getStack().getAnimatingAppWindowTokenRegistry();
+
+ window1.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
+ window2.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
+ assertTrue(window1.isSelfAnimating());
+ assertTrue(window2.isSelfAnimating());
+
+ // Make sure that first animation finish is deferred, and removing the second window stops
+ // finishes all pending deferred finishings.
+ registry.notifyAboutToFinish(window1, mMockEndDeferFinishCallback1);
+ window2.setParent(null);
+ verify(mMockEndDeferFinishCallback1).run();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
index 794d033..ca520ed 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
@@ -56,7 +56,8 @@
Rect windowCrop = new Rect(0, 0, 20, 20);
Animation a = createClipRectAnimation(windowCrop, windowCrop);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
- mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_NONE);
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_NONE,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
argThat(rect -> rect.equals(windowCrop)));
@@ -65,7 +66,8 @@
@Test
public void testApply_clipAfter() {
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null,
- mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_AFTER_ANIM);
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_AFTER_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
verify(mTransaction).setFinalCrop(eq(mSurfaceControl),
@@ -77,7 +79,8 @@
// Stack bounds is (0, 0, 10, 10) position is (20, 40)
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation,
new Point(20, 40), mStackBounds, false /* canSkipFirstFrame */,
- STACK_CLIP_AFTER_ANIM);
+ STACK_CLIP_AFTER_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
verify(mTransaction).setFinalCrop(eq(mSurfaceControl),
@@ -89,7 +92,8 @@
public void testApply_clipBeforeNoAnimationBounds() {
// Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 0, 0)
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null,
- mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
argThat(rect -> rect.equals(mStackBounds)));
@@ -102,7 +106,8 @@
Animation a = createClipRectAnimation(windowCrop, windowCrop);
a.initialize(0, 0, 0, 0);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
- null, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
+ null, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
}
@@ -113,7 +118,8 @@
Rect windowCrop = new Rect(0, 0, 5, 5);
Animation a = createClipRectAnimation(windowCrop, windowCrop);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
- mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
argThat(rect -> rect.equals(windowCrop)));
@@ -125,7 +131,8 @@
Rect windowCrop = new Rect(0, 0, 20, 20);
Animation a = createClipRectAnimation(windowCrop, windowCrop);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
- mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
argThat(rect -> rect.equals(mStackBounds)));
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 1a79a76..f6c67c9 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -613,37 +613,6 @@
/**
* @hide
- * Last time the system tried to connect and failed.
- */
- public long lastConnectionFailure;
-
- /**
- * @hide
- * Last time the system tried to roam and failed because of authentication failure or DHCP
- * RENEW failure.
- */
- public long lastRoamingFailure;
-
- /** @hide */
- public static int ROAMING_FAILURE_IP_CONFIG = 1;
- /** @hide */
- public static int ROAMING_FAILURE_AUTH_FAILURE = 2;
-
- /**
- * @hide
- * Initial amount of time this Wifi configuration gets blacklisted for network switching
- * because of roaming failure
- */
- public long roamingFailureBlackListTimeMilli = 1000;
-
- /**
- * @hide
- * Last roaming failure reason code
- */
- public int lastRoamingFailureReason;
-
- /**
- * @hide
* Last time the system was disconnected to this configuration.
*/
public long lastDisconnected;
@@ -1752,28 +1721,6 @@
sbuf.append("lastConnected: ").append(TimeUtils.logTimeOfDay(this.lastConnected));
sbuf.append(" ");
}
- if (this.lastConnectionFailure != 0) {
- sbuf.append('\n');
- long diff = now_ms - this.lastConnectionFailure;
- if (diff <= 0) {
- sbuf.append("lastConnectionFailure since <incorrect> ");
- } else {
- sbuf.append("lastConnectionFailure: ").append(Long.toString(diff / 1000));
- sbuf.append("sec ");
- }
- }
- if (this.lastRoamingFailure != 0) {
- sbuf.append('\n');
- long diff = now_ms - this.lastRoamingFailure;
- if (diff <= 0) {
- sbuf.append("lastRoamingFailure since <incorrect> ");
- } else {
- sbuf.append("lastRoamingFailure: ").append(Long.toString(diff / 1000));
- sbuf.append("sec ");
- }
- }
- sbuf.append("roamingFailureBlackListTimeMilli: ").
- append(Long.toString(this.roamingFailureBlackListTimeMilli));
sbuf.append('\n');
if (this.linkedConfigurations != null) {
for (String key : this.linkedConfigurations.keySet()) {
@@ -2118,10 +2065,6 @@
lastConnected = source.lastConnected;
lastDisconnected = source.lastDisconnected;
- lastConnectionFailure = source.lastConnectionFailure;
- lastRoamingFailure = source.lastRoamingFailure;
- lastRoamingFailureReason = source.lastRoamingFailureReason;
- roamingFailureBlackListTimeMilli = source.roamingFailureBlackListTimeMilli;
numScorerOverride = source.numScorerOverride;
numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork;
numAssociation = source.numAssociation;
@@ -2187,10 +2130,6 @@
dest.writeInt(lastUpdateUid);
dest.writeString(creatorName);
dest.writeString(lastUpdateName);
- dest.writeLong(lastConnectionFailure);
- dest.writeLong(lastRoamingFailure);
- dest.writeInt(lastRoamingFailureReason);
- dest.writeLong(roamingFailureBlackListTimeMilli);
dest.writeInt(numScorerOverride);
dest.writeInt(numScorerOverrideAndSwitchedNetwork);
dest.writeInt(numAssociation);
@@ -2256,10 +2195,6 @@
config.lastUpdateUid = in.readInt();
config.creatorName = in.readString();
config.lastUpdateName = in.readString();
- config.lastConnectionFailure = in.readLong();
- config.lastRoamingFailure = in.readLong();
- config.lastRoamingFailureReason = in.readInt();
- config.roamingFailureBlackListTimeMilli = in.readLong();
config.numScorerOverride = in.readInt();
config.numScorerOverrideAndSwitchedNetwork = in.readInt();
config.numAssociation = in.readInt();