Merge "Fix unexpected DatePicker validation" into oc-dev
diff --git a/Android.mk b/Android.mk
index b5f8cb0..3f2ae83 100644
--- a/Android.mk
+++ b/Android.mk
@@ -923,6 +923,7 @@
-android \
-knowntags ./frameworks/base/docs/knowntags.txt \
-knowntags ./libcore/known_oj_tags.txt \
+ -manifest ./frameworks/base/core/res/AndroidManifest.xml \
-hidePackage com.android.org.conscrypt \
-since $(SRC_API_DIR)/1.xml 1 \
-since $(SRC_API_DIR)/2.xml 2 \
diff --git a/api/test-current.txt b/api/test-current.txt
index 1cad48e..9b5b1a2 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -47112,6 +47112,7 @@
method public void setColorMode(int);
method public final void setTitle(java.lang.CharSequence);
method public void writeToParcel(android.os.Parcel, int);
+ field public static final int ACCESSIBILITY_TITLE_CHANGED = 33554432; // 0x2000000
field public static final int ALPHA_CHANGED = 128; // 0x80
field public static final int ANIMATION_CHANGED = 16; // 0x10
field public static final float BRIGHTNESS_OVERRIDE_FULL = 1.0f;
@@ -47213,6 +47214,7 @@
field public static final deprecated int TYPE_SYSTEM_OVERLAY = 2006; // 0x7d6
field public static final deprecated int TYPE_TOAST = 2005; // 0x7d5
field public static final int TYPE_WALLPAPER = 2013; // 0x7dd
+ field public java.lang.CharSequence accessibilityTitle;
field public float alpha;
field public float buttonBrightness;
field public float dimAmount;
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 8fd8043..a446296 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -24,6 +24,7 @@
import android.annotation.SdkConstant;
import android.annotation.Size;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.BroadcastBehavior;
import android.app.Activity;
@@ -161,6 +162,7 @@
* the application's main event thread. These operations throw
* {@link IllegalStateException} if they are used on the main thread.
*/
+@SystemService(Context.ACCOUNT_SERVICE)
public class AccountManager {
private static final String TAG = "AccountManager";
@@ -2509,6 +2511,18 @@
return new AuthenticatorException(message);
}
+ private void getAccountByTypeAndFeatures(String accountType, String[] features,
+ AccountManagerCallback<Bundle> callback, Handler handler) {
+ (new AmsTask(null, handler, callback) {
+ @Override
+ public void doWork() throws RemoteException {
+ mService.getAccountByTypeAndFeatures(mResponse, accountType, features,
+ mContext.getOpPackageName());
+ }
+
+ }).start();
+ }
+
private class GetAuthTokenByTypeAndFeaturesTask
extends AmsTask implements AccountManagerCallback<Bundle> {
GetAuthTokenByTypeAndFeaturesTask(final String accountType, final String authTokenType,
@@ -2535,13 +2549,16 @@
@Override
public void doWork() throws RemoteException {
- getAccountsByTypeAndFeatures(mAccountType, mFeatures,
- new AccountManagerCallback<Account[]>() {
+ getAccountByTypeAndFeatures(mAccountType, mFeatures,
+ new AccountManagerCallback<Bundle>() {
@Override
- public void run(AccountManagerFuture<Account[]> future) {
- Account[] accounts;
+ public void run(AccountManagerFuture<Bundle> future) {
+ String accountName = null;
+ String accountType = null;
try {
- accounts = future.getResult();
+ Bundle result = future.getResult();
+ accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+ accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
} catch (OperationCanceledException e) {
setException(e);
return;
@@ -2553,9 +2570,7 @@
return;
}
- mNumAccounts = accounts.length;
-
- if (accounts.length == 0) {
+ if (accountName == null) {
if (mActivity != null) {
// no accounts, add one now. pretend that the user directly
// made this request
@@ -2575,63 +2590,17 @@
}
// we are done
}
- } else if (accounts.length == 1) {
+ } else {
+ mNumAccounts = 1;
+ Account account = new Account(accountName, accountType);
// have a single account, return an authtoken for it
if (mActivity == null) {
- mFuture = getAuthToken(accounts[0], mAuthTokenType,
+ mFuture = getAuthToken(account, mAuthTokenType,
false /* notifyAuthFailure */, mMyCallback, mHandler);
} else {
- mFuture = getAuthToken(accounts[0],
- mAuthTokenType, mLoginOptions,
+ mFuture = getAuthToken(account, mAuthTokenType, mLoginOptions,
mActivity, mMyCallback, mHandler);
}
- } else {
- if (mActivity != null) {
- IAccountManagerResponse chooseResponse =
- new IAccountManagerResponse.Stub() {
- @Override
- public void onResult(Bundle value) throws RemoteException {
- Account account = new Account(
- value.getString(KEY_ACCOUNT_NAME),
- value.getString(KEY_ACCOUNT_TYPE),
- value.getString(KEY_ACCOUNT_ACCESS_ID));
- mFuture = getAuthToken(account, mAuthTokenType,
- mLoginOptions, mActivity, mMyCallback,
- mHandler);
- }
-
- @Override
- public void onError(int errorCode, String errorMessage)
- throws RemoteException {
- mResponse.onError(errorCode, errorMessage);
- }
- };
- // have many accounts, launch the chooser
- Intent intent = new Intent();
- // TODO - this activity will not include
- // USER_MANAGED_NOT_VISIBLE
- // accounts. We need to move method to service
- ComponentName componentName = ComponentName.unflattenFromString(
- Resources.getSystem().getString(
- R.string.config_chooseAccountActivity));
- intent.setClassName(componentName.getPackageName(),
- componentName.getClassName());
- intent.putExtra(KEY_ACCOUNTS, accounts);
- intent.putExtra(KEY_ACCOUNT_MANAGER_RESPONSE,
- new AccountManagerResponse(chooseResponse));
- mActivity.startActivity(intent);
- // the result will arrive via the IAccountManagerResponse
- } else {
- // send result since we can't prompt to select an account
- Bundle result = new Bundle();
- result.putString(KEY_ACCOUNTS, null);
- try {
- mResponse.onResult(result);
- } catch (RemoteException e) {
- // this will never happen
- }
- // we are done
- }
}
}}, mHandler);
}
@@ -2721,8 +2690,8 @@
public AccountManagerFuture<Bundle> getAuthTokenByFeatures(
final String accountType, final String authTokenType, final String[] features,
final Activity activity, final Bundle addAccountOptions,
- final Bundle getAuthTokenOptions,
- final AccountManagerCallback<Bundle> callback, final Handler handler) {
+ final Bundle getAuthTokenOptions, final AccountManagerCallback<Bundle> callback,
+ final Handler handler) {
if (accountType == null) throw new IllegalArgumentException("account type is null");
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
final GetAuthTokenByTypeAndFeaturesTask task =
@@ -3237,6 +3206,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
public AccountManagerFuture<Bundle> finishSessionAsUser(
final Bundle sessionBundle,
final Activity activity,
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index 7494cfc..4cf0a20 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -40,6 +40,8 @@
Account[] getAccountsAsUser(String accountType, int userId, String opPackageName);
void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features,
String opPackageName);
+ void getAccountByTypeAndFeatures(in IAccountManagerResponse response, String accountType,
+ in String[] features, String opPackageName);
void getAccountsByFeatures(in IAccountManagerResponse response, String accountType,
in String[] features, String opPackageName);
boolean addAccountExplicitly(in Account account, String password, in Bundle extras);
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 38ce427..854e531 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -473,9 +473,13 @@
if (mReversing) {
// Between start() and first frame, mLastEventId would be unset (i.e. -1)
mLastEventId = mLastEventId == -1 ? mEvents.size() : mLastEventId;
- for (int j = mLastEventId - 1; j >= 0; j--) {
- AnimationEvent event = mEvents.get(j);
+ while (mLastEventId > 0) {
+ mLastEventId = mLastEventId - 1;
+ AnimationEvent event = mEvents.get(mLastEventId);
Animator anim = event.mNode.mAnimation;
+ if (mNodeMap.get(anim).mEnded) {
+ continue;
+ }
if (event.mEvent == AnimationEvent.ANIMATION_END) {
anim.reverse();
} else if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED
@@ -487,9 +491,15 @@
}
}
} else {
- for (int j = mLastEventId + 1; j < mEvents.size(); j++) {
- AnimationEvent event = mEvents.get(j);
+ while (mLastEventId < mEvents.size() - 1) {
+ // Avoid potential reentrant loop caused by child animators manipulating
+ // AnimatorSet's lifecycle (i.e. not a recommended approach).
+ mLastEventId = mLastEventId + 1;
+ AnimationEvent event = mEvents.get(mLastEventId);
Animator anim = event.mNode.mAnimation;
+ if (mNodeMap.get(anim).mEnded) {
+ continue;
+ }
if (event.mEvent == AnimationEvent.ANIMATION_START) {
anim.start();
} else if (event.mEvent == AnimationEvent.ANIMATION_END && anim.isStarted()) {
@@ -663,6 +673,10 @@
* <p>Starting this <code>AnimatorSet</code> will, in turn, start the animations for which
* it is responsible. The details of when exactly those animations are started depends on
* the dependency relationships that have been set up between the animations.
+ *
+ * <b>Note:</b> Manipulating AnimatorSet's lifecycle in the child animators' listener callbacks
+ * will lead to undefined behaviors. Also, AnimatorSet will ignore any seeking in the child
+ * animators once {@link #start()} is called.
*/
@SuppressWarnings("unchecked")
@Override
diff --git a/core/java/android/annotation/SystemService.java b/core/java/android/annotation/SystemService.java
new file mode 100644
index 0000000..ba5002a
--- /dev/null
+++ b/core/java/android/annotation/SystemService.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.annotation;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.content.Context;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Description of a system service available through
+ * {@link Context#getSystemService(Class)}.
+ *
+ * @hide
+ */
+@Retention(SOURCE)
+@Target(TYPE)
+public @interface SystemService {
+ String value();
+}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index b360c82..3574f8d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5790,6 +5790,7 @@
*
* @return True if this is the root activity, else false.
*/
+ @Override
public boolean isTaskRoot() {
try {
return ActivityManager.getService().getTaskForActivity(mToken, true) >= 0;
@@ -7207,6 +7208,9 @@
"dispatchPictureInPictureModeChanged " + this + ": " + isInPictureInPictureMode
+ " " + newConfig);
mFragments.dispatchPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
+ if (mWindow != null) {
+ mWindow.onPictureInPictureModeChanged(isInPictureInPictureMode);
+ }
onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 7e230a3..f398c8d 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -22,6 +22,7 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.annotation.TestApi;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
@@ -117,6 +118,7 @@
* be used for testing and debugging purposes only.
* </p>
*/
+@SystemService(Context.ACTIVITY_SERVICE)
public class ActivityManager {
private static String TAG = "ActivityManager";
@@ -301,6 +303,19 @@
public static final int START_INTENT_NOT_RESOLVED = FIRST_START_FATAL_ERROR_CODE + 9;
/**
+ * Result for IActivityManager.startAssistantActivity: active session is currently hidden.
+ * @hide
+ */
+ public static final int START_ASSISTANT_HIDDEN_SESSION = FIRST_START_FATAL_ERROR_CODE + 10;
+
+ /**
+ * Result for IActivityManager.startAssistantActivity: active session does not match
+ * the requesting token.
+ * @hide
+ */
+ public static final int START_ASSISTANT_NOT_ACTIVE_SESSION = FIRST_START_FATAL_ERROR_CODE + 11;
+
+ /**
* Result for IActivityManaqer.startActivity: the activity was started
* successfully as normal.
* @hide
@@ -3597,6 +3612,7 @@
* @hide
*/
@SystemApi @TestApi
+ @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
public void addOnUidImportanceListener(OnUidImportanceListener listener,
@RunningAppProcessInfo.Importance int importanceCutpoint) {
synchronized (this) {
@@ -3625,6 +3641,7 @@
* @hide
*/
@SystemApi @TestApi
+ @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
public void removeOnUidImportanceListener(OnUidImportanceListener listener) {
synchronized (this) {
UidObserver observer = mImportanceListeners.remove(listener);
@@ -3992,6 +4009,10 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(anyOf = {
+ "android.permission.INTERACT_ACROSS_USERS",
+ "android.permission.INTERACT_ACROSS_USERS_FULL"
+ })
public static int getCurrentUser() {
UserInfo ui;
try {
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index c4d5116..cbb93a0 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -932,7 +932,7 @@
* @hide
*/
public GraphicBuffer getThumbnail() {
- return mThumbnail.createGraphicBufferHandle();
+ return mThumbnail != null ? mThumbnail.createGraphicBufferHandle() : null;
}
/** @hide */
@@ -1243,11 +1243,13 @@
case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
// Once we parcel the thumbnail for transfering over to the system, create a copy of
// the bitmap to a hardware bitmap and pass through the GraphicBuffer
- if (mThumbnail == null) {
- b.putParcelable(KEY_ANIM_THUMBNAIL, null);
- } else {
+ if (mThumbnail != null) {
final Bitmap hwBitmap = mThumbnail.copy(Config.HARDWARE, true /* immutable */);
- b.putParcelable(KEY_ANIM_THUMBNAIL, hwBitmap.createGraphicBufferHandle());
+ if (hwBitmap != null) {
+ b.putParcelable(KEY_ANIM_THUMBNAIL, hwBitmap.createGraphicBufferHandle());
+ } else {
+ Slog.w(TAG, "Failed to copy thumbnail");
+ }
}
b.putInt(KEY_ANIM_START_X, mStartX);
b.putInt(KEY_ANIM_START_Y, mStartY);
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 620e5cf..2813e8b 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -17,8 +17,10 @@
package android.app;
import android.annotation.IntDef;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
@@ -72,12 +74,8 @@
* {@link #setExact(int, long, PendingIntent)}. Applications whose {@code targetSdkVersion}
* is earlier than API 19 will continue to see the previous behavior in which all
* alarms are delivered exactly when requested.
- *
- * <p>You do not
- * instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.ALARM_SERVICE)}.
*/
+@SystemService(Context.ALARM_SERVICE)
public class AlarmManager {
private static final String TAG = "AlarmManager";
@@ -599,6 +597,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
public void set(@AlarmType int type, long triggerAtMillis, long windowMillis,
long intervalMillis, PendingIntent operation, WorkSource workSource) {
setImpl(type, triggerAtMillis, windowMillis, intervalMillis, 0, operation, null, null,
@@ -633,6 +632,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
public void set(@AlarmType int type, long triggerAtMillis, long windowMillis,
long intervalMillis, OnAlarmListener listener, Handler targetHandler,
WorkSource workSource) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 8292152..e672ada 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -17,7 +17,9 @@
package android.app;
import android.Manifest;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.media.AudioAttributes.AttributeUsage;
@@ -42,10 +44,9 @@
* API for interacting with "application operation" tracking.
*
* <p>This API is not generally intended for third party application developers; most
- * features are only available to system applications. Obtain an instance of it through
- * {@link Context#getSystemService(String) Context.getSystemService} with
- * {@link Context#APP_OPS_SERVICE Context.APP_OPS_SERVICE}.</p>
+ * features are only available to system applications.
*/
+@SystemService(Context.APP_OPS_SERVICE)
public class AppOpsManager {
/**
* <p>App ops allows callers to:</p>
@@ -1409,6 +1410,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS)
public void setUidMode(String appOp, int uid, int mode) {
try {
mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode);
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index 175b979..b6cff38 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.os.Build;
import android.os.Bundle;
@@ -72,6 +73,7 @@
* power whitelist when this broadcast is being delivered to it.
* @param duration The duration in milliseconds; 0 means to not place on whitelist.
*/
+ @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
public void setTemporaryAppWhitelistDuration(long duration) {
mTemporaryAppWhitelistDuration = duration;
}
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index b89c165..5baaeb3 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -19,6 +19,7 @@
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -51,18 +52,15 @@
* request that a URI be downloaded to a particular destination file. The download manager will
* conduct the download in the background, taking care of HTTP interactions and retrying downloads
* after failures or across connectivity changes and system reboots.
- *
- * Instances of this class should be obtained through
- * {@link android.content.Context#getSystemService(String)} by passing
- * {@link android.content.Context#DOWNLOAD_SERVICE}.
- *
+ * <p>
* Apps that request downloads through this API should register a broadcast receiver for
* {@link #ACTION_NOTIFICATION_CLICKED} to appropriately handle when the user clicks on a running
* download in a notification or from the downloads UI.
- *
+ * <p>
* Note that the application must have the {@link android.Manifest.permission#INTERNET}
* permission to use this class.
*/
+@SystemService(Context.DOWNLOAD_SERVICE)
public class DownloadManager {
/**
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 16cbb7c..dbea349 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1953,6 +1953,12 @@
case ActivityManager.START_VOICE_HIDDEN_SESSION:
throw new IllegalStateException(
"Cannot start voice activity on a hidden session");
+ case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
+ throw new IllegalStateException(
+ "Session calling startAssistantActivity does not match active session");
+ case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
+ throw new IllegalStateException(
+ "Cannot start assistant activity on a hidden session");
case ActivityManager.START_CANCELED:
throw new AndroidRuntimeException("Activity could not be started for "
+ intent);
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index fcf0aab..2a29616 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
import android.app.trust.ITrustManager;
import android.content.Context;
import android.content.Intent;
@@ -44,12 +45,11 @@
import java.util.List;
/**
- * Class that can be used to lock and unlock the keyboard. Get an instance of this
- * class by calling {@link android.content.Context#getSystemService(java.lang.String)}
- * with argument {@link android.content.Context#KEYGUARD_SERVICE}. The
+ * Class that can be used to lock and unlock the keyboard. The
* actual class to control the keyboard locking is
* {@link android.app.KeyguardManager.KeyguardLock}.
*/
+@SystemService(Context.KEYGUARD_SERVICE)
public class KeyguardManager {
private static final String TAG = "KeyguardManager";
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 31f52db..4dd71b4 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -22,6 +22,7 @@
import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
@@ -1009,6 +1010,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.NOTIFICATION_DURING_SETUP)
public static final String EXTRA_ALLOW_DURING_SETUP = "android.allowDuringSetup";
/**
@@ -1110,6 +1112,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME)
public static final String EXTRA_SUBSTITUTE_APP_NAME = "android.substName";
/**
@@ -1168,7 +1171,7 @@
*/
public static final int GROUP_ALERT_CHILDREN = 2;
- private int mGroupAlertBehavior = GROUP_ALERT_CHILDREN;
+ private int mGroupAlertBehavior = GROUP_ALERT_ALL;
/**
* If this notification is being shown as a badge, always show as a number.
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 6c55548..235b8d4 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
+import android.annotation.SystemService;
import android.annotation.TestApi;
import android.app.Notification.Builder;
import android.content.ComponentName;
@@ -81,10 +82,6 @@
* to the {@link #cancel(int)} or {@link #cancel(String, int)} method to clear
* this notification.
*
- * <p>
- * You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService}.
- *
* <div class="special reference">
* <h3>Developer Guides</h3>
* <p>For a guide to creating notifications, read the
@@ -93,10 +90,9 @@
* </div>
*
* @see android.app.Notification
- * @see android.content.Context#getSystemService
*/
-public class NotificationManager
-{
+@SystemService(Context.NOTIFICATION_SERVICE)
+public class NotificationManager {
private static String TAG = "NotificationManager";
private static boolean localLOGV = false;
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index c529e4b..ea990ad 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.SystemService;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -46,10 +47,6 @@
* services are provided through methods in {@link android.app.Activity Activity}
* and the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
* {@link android.content.Intent Intent}.
- * If you do require direct access to the SearchManager, do not instantiate
- * this class directly. Instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * context.getSystemService(Context.SEARCH_SERVICE)}.
*
* <div class="special reference">
* <h3>Developer Guides</h3>
@@ -58,9 +55,9 @@
* <a href="{@docRoot}guide/topics/search/index.html">Search</a> developer guide.</p>
* </div>
*/
+@SystemService(Context.SEARCH_SERVICE)
public class SearchManager
- implements DialogInterface.OnDismissListener, DialogInterface.OnCancelListener
-{
+ implements DialogInterface.OnDismissListener, DialogInterface.OnCancelListener {
private static final boolean DBG = false;
private static final String TAG = "SearchManager";
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index e57a9b5..fb8bd39 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -18,6 +18,7 @@
package android.app;
import android.annotation.IntDef;
+import android.annotation.SystemService;
import android.content.Context;
import android.os.Binder;
import android.os.RemoteException;
@@ -36,6 +37,7 @@
*
* @hide
*/
+@SystemService(Context.STATUS_BAR_SERVICE)
public class StatusBarManager {
public static final int DISABLE_EXPAND = View.STATUS_BAR_DISABLE_EXPAND;
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 07e2570..bc61668 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -17,6 +17,7 @@
package android.app;
import android.annotation.IntDef;
+import android.annotation.SystemService;
import android.annotation.TestApi;
import android.content.Context;
import android.content.res.Configuration;
@@ -49,11 +50,8 @@
* displayed allowing the user to exit dock mode. Thus the dock mode
* represented here may be different than the current state of the underlying
* dock event broadcast.
- *
- * <p>You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.UI_MODE_SERVICE)}.
*/
+@SystemService(Context.UI_MODE_SERVICE)
public class UiModeManager {
private static final String TAG = "UiModeManager";
diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java
index 8014eca..b40c96c 100644
--- a/core/java/android/app/VrManager.java
+++ b/core/java/android/app/VrManager.java
@@ -1,19 +1,20 @@
package android.app;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.ComponentName;
+import android.content.Context;
import android.os.RemoteException;
import android.service.vr.IVrManager;
/**
* Used to control aspects of a devices Virtual Reality (VR) capabilities.
- * <p>
- * You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService}.
* @hide
*/
@SystemApi
+@SystemService(Context.VR_SERVICE)
public class VrManager {
private final IVrManager mService;
@@ -29,11 +30,10 @@
* remain in VR mode even if the foreground does not specify Vr mode being enabled. Mainly used
* by VR viewers to indicate that a device is placed in a VR viewer.
*
- * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
- *
* @see Activity#setVrModeEnabled(boolean, ComponentName)
* @param enabled true if the device should be placed in persistent VR mode.
*/
+ @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
public void setPersistentVrModeEnabled(boolean enabled) {
try {
mService.setPersistentVrModeEnabled(enabled);
@@ -46,13 +46,12 @@
* Sets the resolution and DPI of the vr2d virtual display used to display 2D
* applications in VR mode.
*
- * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
- *
* @param vr2dDisplayProp properties to be set to the virtual display for
* 2D applications in VR mode.
*
* {@hide}
*/
+ @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
public void setVr2dDisplayProperties(
Vr2dDisplayProperties vr2dDisplayProp) {
try {
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index db2f937..a850423 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -18,8 +18,10 @@
import android.annotation.IntDef;
import android.annotation.RawRes;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -76,13 +78,13 @@
/**
* Provides access to the system wallpaper. With WallpaperManager, you can
* get the current wallpaper, get the desired dimensions for the wallpaper, set
- * the wallpaper, and more. Get an instance of WallpaperManager with
- * {@link #getInstance(android.content.Context) getInstance()}.
+ * the wallpaper, and more.
*
* <p> An app can check whether wallpapers are supported for the current user, by calling
* {@link #isWallpaperSupported()}, and whether setting of wallpapers is allowed, by calling
* {@link #isSetWallpaperAllowed()}.
*/
+@SystemService(Context.WALLPAPER_SERVICE)
public class WallpaperManager {
private static String TAG = "WallpaperManager";
private static boolean DEBUG = false;
@@ -1355,6 +1357,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_HINTS)
public void setDisplayPadding(Rect padding) {
try {
if (sGlobals.mService == null) {
@@ -1395,6 +1398,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public void clearWallpaper() {
clearWallpaper(FLAG_LOCK, mContext.getUserId());
clearWallpaper(FLAG_SYSTEM, mContext.getUserId());
@@ -1407,6 +1411,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public void clearWallpaper(@SetWallpaperFlags int which, int userId) {
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
@@ -1422,12 +1427,10 @@
/**
* Set the live wallpaper.
*
- * This can only be called by packages with android.permission.SET_WALLPAPER_COMPONENT
- * permission.
- *
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT)
public boolean setWallpaperComponent(ComponentName name) {
return setWallpaperComponent(name, UserHandle.myUserId());
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 9ae5d1c..01c4656 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -20,9 +20,12 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
@@ -98,6 +101,7 @@
* "{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a> developer
* guide. </div>
*/
+@SystemService(Context.DEVICE_POLICY_SERVICE)
public class DevicePolicyManager {
private static String TAG = "DevicePolicyManager";
@@ -1601,6 +1605,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
public boolean packageHasActiveAdmins(String packageName) {
return packageHasActiveAdmins(packageName, myUserId());
}
@@ -4512,11 +4517,10 @@
/**
* @return device owner component name, even if it's running on a different user.
*
- * <p>Requires the MANAGE_USERS permission.
- *
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public ComponentName getDeviceOwnerComponentOnAnyUser() {
return getDeviceOwnerComponentInner(/* callingUserOnly =*/ false);
}
@@ -4600,6 +4604,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public @Nullable String getDeviceOwner() {
throwIfParentInstance("getDeviceOwner");
final ComponentName name = getDeviceOwnerComponentOnCallingUser();
@@ -4617,6 +4622,7 @@
*/
@SystemApi
@TestApi
+ @SuppressLint("Doclava125")
public boolean isDeviceManaged() {
try {
return mService.hasDeviceOwner();
@@ -4629,11 +4635,10 @@
* Returns the device owner name. Note this method *will* return the device owner
* name when it's running on a different user.
*
- * <p>Requires the MANAGE_USERS permission.
- *
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public String getDeviceOwnerNameOnAnyUser() {
throwIfParentInstance("getDeviceOwnerNameOnAnyUser");
if (mService != null) {
@@ -4653,6 +4658,7 @@
*/
@Deprecated
@SystemApi
+ @SuppressLint("Doclava125")
public @Nullable String getDeviceInitializerApp() {
return null;
}
@@ -4664,6 +4670,7 @@
*/
@Deprecated
@SystemApi
+ @SuppressLint("Doclava125")
public @Nullable ComponentName getDeviceInitializerComponent() {
return null;
}
@@ -4686,6 +4693,7 @@
*/
@Deprecated
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS)
public boolean setActiveProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName)
throws IllegalArgumentException {
throwIfParentInstance("setActiveProfileOwner");
@@ -5003,6 +5011,7 @@
* @throws IllegalArgumentException if the userId is invalid.
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public @Nullable String getProfileOwnerNameAsUser(int userId) throws IllegalArgumentException {
throwIfParentInstance("getProfileOwnerNameAsUser");
if (mService != null) {
@@ -6773,8 +6782,7 @@
* Called by the system update service to notify device and profile owners of pending system
* updates.
*
- * The caller must hold {@link android.Manifest.permission#NOTIFY_PENDING_SYSTEM_UPDATE}
- * permission. This method should only be used when it is unknown whether the pending system
+ * This method should only be used when it is unknown whether the pending system
* update is a security patch. Otherwise, use
* {@link #notifyPendingSystemUpdate(long, boolean)}.
*
@@ -6785,6 +6793,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.NOTIFY_PENDING_SYSTEM_UPDATE)
public void notifyPendingSystemUpdate(long updateReceivedTime) {
throwIfParentInstance("notifyPendingSystemUpdate");
if (mService != null) {
@@ -6800,8 +6809,7 @@
* Called by the system update service to notify device and profile owners of pending system
* updates.
*
- * The caller must hold {@link android.Manifest.permission#NOTIFY_PENDING_SYSTEM_UPDATE}
- * permission. This method should be used instead of {@link #notifyPendingSystemUpdate(long)}
+ * This method should be used instead of {@link #notifyPendingSystemUpdate(long)}
* when it is known whether the pending system update is a security patch.
*
* @param updateReceivedTime The time as given by {@link System#currentTimeMillis()}
@@ -6813,6 +6821,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.NOTIFY_PENDING_SYSTEM_UPDATE)
public void notifyPendingSystemUpdate(long updateReceivedTime, boolean isSecurityPatch) {
throwIfParentInstance("notifyPendingSystemUpdate");
if (mService != null) {
@@ -7521,6 +7530,7 @@
*/
@SystemApi
@TestApi
+ @SuppressLint("Doclava125")
public @Nullable CharSequence getDeviceOwnerOrganizationName() {
try {
return mService.getDeviceOwnerOrganizationName();
@@ -7711,6 +7721,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public void setDeviceProvisioningConfigApplied() {
try {
mService.setDeviceProvisioningConfigApplied();
@@ -7731,6 +7742,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public boolean isDeviceProvisioningConfigApplied() {
try {
return mService.isDeviceProvisioningConfigApplied();
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index c99a1e4..266fa7e 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -18,7 +18,6 @@
import android.os.PooledStringWriter;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.service.autofill.FillContext;
import android.service.autofill.FillRequest;
import android.text.TextUtils;
import android.util.Log;
@@ -31,7 +30,6 @@
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
import java.util.ArrayList;
@@ -39,18 +37,18 @@
import java.util.List;
/**
- * Assist data automatically created by the platform's implementation of Assist and Autofill.
+ * Assist data automatically created by the platform's implementation of assist and autofill.
*
- * <p>The structure is used for Assist purposes when created by
+ * <p>The structure is used for assist purposes when created by
* {@link android.app.Activity#onProvideAssistData}, {@link View#onProvideStructure(ViewStructure)},
* or {@link View#onProvideVirtualStructure(ViewStructure)}.
*
- * <p>The structure is used for Autofill purposes when created by
+ * <p>The structure is used for autofill purposes when created by
* {@link View#onProvideAutofillStructure(ViewStructure, int)},
* or {@link View#onProvideAutofillVirtualStructure(ViewStructure, int)}.
*
- * <p>For performance reasons, some properties of the Assist data might be available just for Assist
- * or Autofill purposes; in those case, the property availability will be document in its javadoc.
+ * <p>For performance reasons, some properties of the assist data might be available just for assist
+ * or autofill purposes; in those case, the property availability will be document in its javadoc.
*/
public class AssistStructure implements Parcelable {
static final String TAG = "AssistStructure";
@@ -958,10 +956,10 @@
/**
* Gets the id that can be used to autofill the view contents.
*
- * <p>It's relevant set when the {@link AssistStructure} is used for Autofill purposes.
+ * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes.
*
* @return id that can be used to autofill the view contents, or {@code null} if the
- * structure was created for Assist purposes.
+ * structure was created for assist purposes.
*/
@Nullable public AutofillId getAutofillId() {
return mAutofillId;
@@ -970,10 +968,10 @@
/**
* Gets the the type of value that can be used to autofill the view contents.
*
- * <p>It's only relevant when the {@link AssistStructure} is used for Autofill purposes.
+ * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes.
*
* @return autofill type as defined by {@link View#getAutofillType()},
- * or {@link View#AUTOFILL_TYPE_NONE} if the structure was created for Assist purposes.
+ * or {@link View#AUTOFILL_TYPE_NONE} if the structure was created for assist purposes.
*/
public @View.AutofillType int getAutofillType() {
return mAutofillType;
@@ -983,11 +981,11 @@
* Describes the content of a view so that a autofill service can fill in the appropriate
* data.
*
- * <p>It's only relevant when the {@link AssistStructure} is used for Autofill purposes,
+ * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
* not for Assist - see {@link View#getAutofillHints()} for more info.
*
* @return The autofill hints for this view, or {@code null} if the structure was created
- * for Assist purposes.
+ * for assist purposes.
*/
@Nullable public String[] getAutofillHints() {
return mAutofillHints;
@@ -996,11 +994,11 @@
/**
* Gets the the value of this view.
*
- * <p>It's only relevant when the {@link AssistStructure} is used for Autofill purposes,
- * not for Assist purposes.
+ * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
+ * not for assist purposes.
*
* @return the autofill value of this view, or {@code null} if the structure was created
- * for Assist purposes.
+ * for assist purposes.
*/
@Nullable public AutofillValue getAutofillValue() {
return mAutofillValue;
@@ -1017,11 +1015,11 @@
* <p>Typically used by nodes whose {@link View#getAutofillType()} is a list to indicate
* the meaning of each possible value in the list.
*
- * <p>It's relevant when the {@link AssistStructure} is used for Autofill purposes, not
- * for Assist purposes.
+ * <p>It's relevant when the {@link AssistStructure} is used for autofill purposes, not
+ * for assist purposes.
*
* @return the options that can be used to autofill this view, or {@code null} if the
- * structure was created for Assist purposes.
+ * structure was created for assist purposes.
*/
@Nullable public CharSequence[] getAutofillOptions() {
return mAutofillOptions;
@@ -1106,8 +1104,8 @@
* or scaling. The returned Matrix object is owned by ViewNode; do not modify it.
* Returns null if there is no transformation applied to the view.
*
- * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
- * not for Autofill purposes.
+ * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+ * not for autofill purposes.
*/
public Matrix getTransformation() {
return mMatrix;
@@ -1118,8 +1116,8 @@
* characterstics, as set by {@link ViewStructure#setElevation
* ViewStructure.setElevation(float)}.
*
- * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
- * not for Autofill purposes.
+ * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+ * not for autofill purposes.
*/
public float getElevation() {
return mElevation;
@@ -1130,8 +1128,8 @@
* of the view's contents, as set by {@link ViewStructure#setAlpha
* ViewStructure.setAlpha(float)}.
*
- * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
- * not for Autofill purposes.
+ * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+ * not for autofill purposes.
*/
public float getAlpha() {
return mAlpha;
@@ -1260,7 +1258,7 @@
* document.
*
* <strong>WARNING:</strong> a {@link android.service.autofill.AutofillService} should only
- * use this domain for Autofill purposes when it trusts the app generating it (i.e., the app
+ * use this domain for autofill purposes when it trusts the app generating it (i.e., the app
* defined by {@link AssistStructure#getActivityComponent()}).
*
* @return domain-only part of the document. For example, if the full URL is
@@ -1273,11 +1271,11 @@
/**
* Returns the HTML properties associated with this view.
*
- * <p>It's only relevant when the {@link AssistStructure} is used for Autofill purposes,
- * not for Assist purposes.
+ * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
+ * not for assist purposes.
*
* @return the HTML properties associated with this view, or {@code null} if the
- * structure was created for Assist purposes.
+ * structure was created for assist purposes.
*/
@Nullable public HtmlInfo getHtmlInfo() {
return mHtmlInfo;
@@ -1301,8 +1299,8 @@
/**
* If {@link #getText()} is non-null, this is where the current selection starts.
*
- * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
- * not for Autofill purposes.
+ * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+ * not for autofill purposes.
*/
public int getTextSelectionStart() {
return mText != null ? mText.mTextSelectionStart : -1;
@@ -1313,8 +1311,8 @@
* If there is no selection, returns the same value as {@link #getTextSelectionStart()},
* indicating the cursor position.
*
- * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
- * not for Autofill purposes.
+ * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+ * not for autofill purposes.
*/
public int getTextSelectionEnd() {
return mText != null ? mText.mTextSelectionEnd : -1;
@@ -1337,8 +1335,8 @@
* Note that the text may also contain style spans that modify the color of specific
* parts of the text.
*
- * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
- * not for Autofill purposes.
+ * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+ * not for autofill purposes.
*/
public int getTextBackgroundColor() {
return mText != null ? mText.mTextBackgroundColor : TEXT_COLOR_UNDEFINED;
@@ -1350,8 +1348,8 @@
* Note that the text may also contain style spans that modify the size of specific
* parts of the text.
*
- * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
- * not for Autofill purposes.
+ * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+ * not for autofill purposes.
*/
public float getTextSize() {
return mText != null ? mText.mTextSize : 0;
@@ -1365,8 +1363,8 @@
* Note that the text may also contain style spans that modify the style of specific
* parts of the text.
*
- * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
- * not for Autofill purposes.
+ * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+ * not for autofill purposes.
*/
public int getTextStyle() {
return mText != null ? mText.mTextStyle : 0;
@@ -1378,8 +1376,8 @@
* into the text string where that line starts. May return null if there is no line
* information.
*
- * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
- * not for Autofill purposes.
+ * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+ * not for autofill purposes.
*/
public int[] getTextLineCharOffsets() {
return mText != null ? mText.mLineCharOffsets : null;
@@ -1391,8 +1389,8 @@
* where that text appears in the view. May return null if there is no line
* information.
*
- * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
- * not for Autofill purposes.
+ * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+ * not for autofill purposes.
*/
public int[] getTextLineBaselines() {
return mText != null ? mText.mLineBaselines : null;
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 9d02f53..9f9b217 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -16,6 +16,7 @@
package android.app.backup;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
@@ -324,6 +325,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BACKUP)
public RestoreSession beginRestoreSession() {
RestoreSession session = null;
checkServiceBinder();
@@ -348,11 +350,10 @@
* mechanism was disabled will still be backed up properly if it is enabled
* at some point in the future.
*
- * <p>Callers must hold the android.permission.BACKUP permission to use this method.
- *
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BACKUP)
public void setBackupEnabled(boolean isEnabled) {
checkServiceBinder();
if (sService != null) {
@@ -367,11 +368,10 @@
/**
* Report whether the backup mechanism is currently enabled.
*
- * <p>Callers must hold the android.permission.BACKUP permission to use this method.
- *
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BACKUP)
public boolean isBackupEnabled() {
checkServiceBinder();
if (sService != null) {
@@ -390,11 +390,10 @@
* the archival restore dataset (if any). When disabled, no such attempt will
* be made.
*
- * <p>Callers must hold the android.permission.BACKUP permission to use this method.
- *
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BACKUP)
public void setAutoRestore(boolean isEnabled) {
checkServiceBinder();
if (sService != null) {
@@ -407,14 +406,14 @@
}
/**
- * Identify the currently selected transport. Callers must hold the
- * android.permission.BACKUP permission to use this method.
+ * Identify the currently selected transport.
* @return The name of the currently active backup transport. In case of
* failure or if no transport is currently active, this method returns {@code null}.
*
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BACKUP)
public String getCurrentTransport() {
checkServiceBinder();
if (sService != null) {
@@ -428,12 +427,12 @@
}
/**
- * Request a list of all available backup transports' names. Callers must
- * hold the android.permission.BACKUP permission to use this method.
+ * Request a list of all available backup transports' names.
*
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BACKUP)
public String[] listAllTransports() {
checkServiceBinder();
if (sService != null) {
@@ -449,8 +448,6 @@
/**
* Specify the current backup transport.
*
- * <p> Callers must hold the android.permission.BACKUP permission to use this method.
- *
* @param transport The name of the transport to select. This should be one
* of the names returned by {@link #listAllTransports()}. This is the String returned by
* {@link BackupTransport#name()} for the particular transport.
@@ -462,6 +459,7 @@
*/
@Deprecated
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BACKUP)
public String selectBackupTransport(String transport) {
checkServiceBinder();
if (sService != null) {
@@ -479,8 +477,6 @@
* This method is async because BackupManager might need to bind to the specified transport
* which is in a separate process.
*
- * <p>Callers must hold the android.permission.BACKUP permission to use this method.
- *
* @param transport ComponentName of the service hosting the transport. This is different from
* the transport's name that is returned by {@link BackupTransport#name()}.
* @param listener A listener object to get a callback on the transport being selected.
@@ -488,6 +484,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BACKUP)
public void selectBackupTransport(ComponentName transport,
SelectBackupTransportCallback listener) {
checkServiceBinder();
@@ -510,11 +507,10 @@
* transport will still be asked to confirm via the usual requestBackupTime()
* method.
*
- * <p>Callers must hold the android.permission.BACKUP permission to use this method.
- *
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BACKUP)
public void backupNow() {
checkServiceBinder();
if (sService != null) {
@@ -530,8 +526,6 @@
* Ask the framework which dataset, if any, the given package's data would be
* restored from if we were to install it right now.
*
- * <p>Callers must hold the android.permission.BACKUP permission to use this method.
- *
* @param packageName The name of the package whose most-suitable dataset we
* wish to look up
* @return The dataset token from which a restore should be attempted, or zero if
@@ -540,6 +534,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BACKUP)
public long getAvailableRestoreToken(String packageName) {
checkServiceBinder();
if (sService != null) {
@@ -555,14 +550,13 @@
/**
* Ask the framework whether this app is eligible for backup.
*
- * <p>Callers must hold the android.permission.BACKUP permission to use this method.
- *
* @param packageName The name of the package.
* @return Whether this app is eligible for backup.
*
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BACKUP)
public boolean isAppEligibleForBackup(String packageName) {
checkServiceBinder();
if (sService != null) {
@@ -592,6 +586,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BACKUP)
public int requestBackup(String[] packages, BackupObserver observer) {
return requestBackup(packages, observer, null, 0);
}
@@ -615,6 +610,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BACKUP)
public int requestBackup(String[] packages, BackupObserver observer,
BackupManagerMonitor monitor, int flags) {
checkServiceBinder();
@@ -638,11 +634,10 @@
* Cancel all running backups. After this call returns, no currently running backups will
* interact with the selected transport.
*
- * <p>Callers must hold the android.permission.BACKUP permission to use this method.
- *
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BACKUP)
public void cancelBackups() {
checkServiceBinder();
if (sService != null) {
diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java
index 1768828..3868439 100644
--- a/core/java/android/app/job/JobScheduler.java
+++ b/core/java/android/app/job/JobScheduler.java
@@ -19,8 +19,11 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.ClipData;
+import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.PersistableBundle;
@@ -53,6 +56,7 @@
* {@link android.content.Context#getSystemService
* Context.getSystemService(Context.JOB_SCHEDULER_SERVICE)}.
*/
+@SystemService(Context.JOB_SCHEDULER_SERVICE)
public abstract class JobScheduler {
/** @hide */
@IntDef(prefix = { "RESULT_" }, value = {
@@ -132,6 +136,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
public abstract @Result int scheduleAsPackage(@NonNull JobInfo job, @NonNull String packageName,
int userId, String tag);
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 06b0aac..54a7e5c 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -18,6 +18,8 @@
import android.Manifest;
import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
+import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -31,6 +33,7 @@
* See {@link com.android.server.trust.TrustManagerService}
* @hide
*/
+@SystemService(Context.TRUST_SERVICE)
public class TrustManager {
private static final int MSG_TRUST_CHANGED = 1;
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 6cd4e92..ef262e0 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -19,6 +19,7 @@
import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.Nullable;
+import android.annotation.SystemService;
import android.app.usage.NetworkStats.Bucket;
import android.content.Context;
import android.net.ConnectivityManager;
@@ -82,6 +83,7 @@
* the above permission, even to access an app's own data usage, and carrier-privileged apps were
* not included.
*/
+@SystemService(Context.NETWORK_STATS_SERVICE)
public class NetworkStatsManager {
private static final String TAG = "NetworkStatsManager";
private static final boolean DBG = false;
diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java
index 0b2b190..7c68079 100644
--- a/core/java/android/app/usage/StorageStatsManager.java
+++ b/core/java/android/app/usage/StorageStatsManager.java
@@ -20,6 +20,7 @@
import android.annotation.BytesLong;
import android.annotation.NonNull;
+import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.WorkerThread;
import android.content.Context;
@@ -50,6 +51,7 @@
* application.
* </p>
*/
+@SystemService(Context.STORAGE_STATS_SERVICE)
public class StorageStatsManager {
private final Context mContext;
private final IStorageStatsManager mService;
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 75a4a53..1f939f9 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -16,7 +16,9 @@
package android.app.usage;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.os.RemoteException;
@@ -51,6 +53,7 @@
* the permission implies intention to use the API and the user of the device can grant permission
* through the Settings application.
*/
+@SystemService(Context.USAGE_STATS_SERVICE)
public final class UsageStatsManager {
/**
@@ -252,7 +255,6 @@
* Temporarily whitelist the specified app for a short duration. This is to allow an app
* receiving a high priority message to be able to access the network and acquire wakelocks
* even if the device is in power-save mode or the app is currently considered inactive.
- * The caller must hold the CHANGE_DEVICE_IDLE_TEMP_WHITELIST permission.
* @param packageName The package name of the app to whitelist.
* @param duration Duration to whitelist the app for, in milliseconds. It is recommended that
* this be limited to 10s of seconds. Requested duration will be clamped to a few minutes.
@@ -261,6 +263,7 @@
* @see #isAppInactive(String)
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
public void whitelistAppTemporarily(String packageName, long duration, UserHandle user) {
try {
mService.whitelistAppTemporarily(packageName, duration, user.getIdentifier());
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 6327f34..969b19e 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
+import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.PendingIntent;
import android.content.ComponentName;
@@ -51,6 +52,7 @@
* <a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a> developer guide.</p>
* </div>
*/
+@SystemService(Context.APPWIDGET_SERVICE)
public class AppWidgetManager {
/**
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index c7191ba..e2fa38a 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -18,6 +18,7 @@
import android.Manifest;
import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
import android.util.Log;
@@ -48,6 +49,7 @@
* @see Context#getSystemService
* @see BluetoothAdapter#getDefaultAdapter()
*/
+@SystemService(Context.BLUETOOTH_SERVICE)
public final class BluetoothManager {
private static final String TAG = "BluetoothManager";
private static final boolean DBG = true;
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 4e70e3f..dabe608 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemService;
import android.app.Activity;
import android.app.Application;
import android.app.PendingIntent;
@@ -47,6 +48,7 @@
*
* @see AssociationRequest
*/
+@SystemService(Context.COMPANION_DEVICE_SERVICE)
public final class CompanionDeviceManager {
private static final boolean DEBUG = false;
diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java
index f1c2f34..718e465 100644
--- a/core/java/android/content/ClipboardManager.java
+++ b/core/java/android/content/ClipboardManager.java
@@ -16,6 +16,7 @@
package android.content;
+import android.annotation.SystemService;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
@@ -29,10 +30,6 @@
* the global clipboard.
*
* <p>
- * You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService}.
- *
- * <p>
* The ClipboardManager API itself is very simple: it consists of methods
* to atomically get and set the current primary clipboard data. That data
* is expressed as a {@link ClipData} object, which defines the protocol
@@ -44,9 +41,8 @@
* <a href="{@docRoot}guide/topics/clipboard/copy-paste.html">Copy and Paste</a>
* developer guide.</p>
* </div>
- *
- * @see android.content.Context#getSystemService
*/
+@SystemService(Context.CLIPBOARD_SERVICE)
public class ClipboardManager extends android.text.ClipboardManager {
private final Context mContext;
private final IClipboard mService;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 10594af..db80c72 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1630,13 +1630,13 @@
/**
* Version of {@link #startActivity(Intent)} that allows you to specify the
* user the activity will be started for. This is not available to applications
- * that are not pre-installed on the system image. Using it requires holding
- * the INTERACT_ACROSS_USERS_FULL permission.
+ * that are not pre-installed on the system image.
* @param intent The description of the activity to start.
* @param user The UserHandle of the user to start this activity for.
* @throws ActivityNotFoundException
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
public void startActivityAsUser(@RequiresPermission Intent intent, UserHandle user) {
throw new RuntimeException("Not implemented. Must override in a subclass.");
}
@@ -1672,8 +1672,7 @@
/**
* Version of {@link #startActivity(Intent, Bundle)} that allows you to specify the
* user the activity will be started for. This is not available to applications
- * that are not pre-installed on the system image. Using it requires holding
- * the INTERACT_ACROSS_USERS_FULL permission.
+ * that are not pre-installed on the system image.
* @param intent The description of the activity to start.
* @param options Additional options for how the Activity should be started.
* May be null if there are no options. See {@link android.app.ActivityOptions}
@@ -1683,6 +1682,7 @@
* @throws ActivityNotFoundException
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
public void startActivityAsUser(@RequiresPermission Intent intent, @Nullable Bundle options,
UserHandle userId) {
throw new RuntimeException("Not implemented. Must override in a subclass.");
@@ -1781,6 +1781,7 @@
* @see #startActivities(Intent[])
* @see PackageManager#resolveActivity
*/
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
public void startActivitiesAsUser(Intent[] intents, Bundle options, UserHandle userHandle) {
throw new RuntimeException("Not implemented. Must override in a subclass.");
}
@@ -2081,20 +2082,19 @@
/**
* Version of {@link #sendBroadcast(Intent)} that allows you to specify the
* user the broadcast will be sent to. This is not available to applications
- * that are not pre-installed on the system image. Using it requires holding
- * the INTERACT_ACROSS_USERS permission.
+ * that are not pre-installed on the system image.
* @param intent The intent to broadcast
* @param user UserHandle to send the intent to.
* @see #sendBroadcast(Intent)
*/
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
public abstract void sendBroadcastAsUser(@RequiresPermission Intent intent,
UserHandle user);
/**
* Version of {@link #sendBroadcast(Intent, String)} that allows you to specify the
* user the broadcast will be sent to. This is not available to applications
- * that are not pre-installed on the system image. Using it requires holding
- * the INTERACT_ACROSS_USERS permission.
+ * that are not pre-installed on the system image.
*
* @param intent The Intent to broadcast; all receivers matching this
* Intent will receive the broadcast.
@@ -2105,14 +2105,14 @@
*
* @see #sendBroadcast(Intent, String)
*/
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
public abstract void sendBroadcastAsUser(@RequiresPermission Intent intent,
UserHandle user, @Nullable String receiverPermission);
/**
* Version of {@link #sendBroadcast(Intent, String, Bundle)} that allows you to specify the
* user the broadcast will be sent to. This is not available to applications
- * that are not pre-installed on the system image. Using it requires holding
- * the INTERACT_ACROSS_USERS permission.
+ * that are not pre-installed on the system image.
*
* @param intent The Intent to broadcast; all receivers matching this
* Intent will receive the broadcast.
@@ -2127,14 +2127,14 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
public abstract void sendBroadcastAsUser(@RequiresPermission Intent intent,
UserHandle user, @Nullable String receiverPermission, @Nullable Bundle options);
/**
* Version of {@link #sendBroadcast(Intent, String)} that allows you to specify the
* user the broadcast will be sent to. This is not available to applications
- * that are not pre-installed on the system image. Using it requires holding
- * the INTERACT_ACROSS_USERS permission.
+ * that are not pre-installed on the system image.
*
* @param intent The Intent to broadcast; all receivers matching this
* Intent will receive the broadcast.
@@ -2148,6 +2148,7 @@
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
public abstract void sendBroadcastAsUser(@RequiresPermission Intent intent,
UserHandle user, @Nullable String receiverPermission, int appOp);
@@ -2156,8 +2157,7 @@
* {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)}
* that allows you to specify the
* user the broadcast will be sent to. This is not available to applications
- * that are not pre-installed on the system image. Using it requires holding
- * the INTERACT_ACROSS_USERS permission.
+ * that are not pre-installed on the system image.
*
* <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
*
@@ -2181,6 +2181,7 @@
*
* @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
*/
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
public abstract void sendOrderedBroadcastAsUser(@RequiresPermission Intent intent,
UserHandle user, @Nullable String receiverPermission, BroadcastReceiver resultReceiver,
@Nullable Handler scheduler, int initialCode, @Nullable String initialData,
@@ -2192,6 +2193,7 @@
* BroadcastReceiver, Handler, int, String, Bundle)
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
public abstract void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
@Nullable String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
@Nullable Handler scheduler, int initialCode, @Nullable String initialData,
@@ -2203,6 +2205,7 @@
* BroadcastReceiver, Handler, int, String, Bundle)
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
public abstract void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
@Nullable String receiverPermission, int appOp, @Nullable Bundle options,
BroadcastReceiver resultReceiver, @Nullable Handler scheduler, int initialCode,
@@ -2307,8 +2310,7 @@
/**
* <p>Version of {@link #sendStickyBroadcast(Intent)} that allows you to specify the
* user the broadcast will be sent to. This is not available to applications
- * that are not pre-installed on the system image. Using it requires holding
- * the INTERACT_ACROSS_USERS permission.
+ * that are not pre-installed on the system image.
*
* @deprecated Sticky broadcasts should not be used. They provide no security (anyone
* can access them), no protection (anyone can modify them), and many other problems.
@@ -2324,6 +2326,10 @@
* @see #sendBroadcast(Intent)
*/
@Deprecated
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ android.Manifest.permission.BROADCAST_STICKY
+ })
public abstract void sendStickyBroadcastAsUser(@RequiresPermission Intent intent,
UserHandle user);
@@ -2332,6 +2338,10 @@
* This is just here for sending CONNECTIVITY_ACTION.
*/
@Deprecated
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ android.Manifest.permission.BROADCAST_STICKY
+ })
public abstract void sendStickyBroadcastAsUser(@RequiresPermission Intent intent,
UserHandle user, Bundle options);
@@ -2340,8 +2350,7 @@
* {@link #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle)}
* that allows you to specify the
* user the broadcast will be sent to. This is not available to applications
- * that are not pre-installed on the system image. Using it requires holding
- * the INTERACT_ACROSS_USERS permission.
+ * that are not pre-installed on the system image.
*
* <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
*
@@ -2369,6 +2378,10 @@
* @see #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle)
*/
@Deprecated
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ android.Manifest.permission.BROADCAST_STICKY
+ })
public abstract void sendStickyOrderedBroadcastAsUser(@RequiresPermission Intent intent,
UserHandle user, BroadcastReceiver resultReceiver,
@Nullable Handler scheduler, int initialCode, @Nullable String initialData,
@@ -2377,8 +2390,7 @@
/**
* <p>Version of {@link #removeStickyBroadcast(Intent)} that allows you to specify the
* user the broadcast will be sent to. This is not available to applications
- * that are not pre-installed on the system image. Using it requires holding
- * the INTERACT_ACROSS_USERS permission.
+ * that are not pre-installed on the system image.
*
* <p>You must hold the {@link android.Manifest.permission#BROADCAST_STICKY}
* permission in order to use this API. If you do not hold that
@@ -2396,6 +2408,10 @@
* @see #sendStickyBroadcastAsUser
*/
@Deprecated
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ android.Manifest.permission.BROADCAST_STICKY
+ })
public abstract void removeStickyBroadcastAsUser(@RequiresPermission Intent intent,
UserHandle user);
@@ -2562,9 +2578,7 @@
* @hide
* Same as {@link #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)
* but for a specific user. This receiver will receiver broadcasts that
- * are sent to the requested user. It
- * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}
- * permission.
+ * are sent to the requested user.
*
* @param receiver The BroadcastReceiver to handle the broadcast.
* @param user UserHandle to send the intent to.
@@ -2583,6 +2597,7 @@
* @see #unregisterReceiver
*/
@Nullable
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
public abstract Intent registerReceiverAsUser(BroadcastReceiver receiver,
UserHandle user, IntentFilter filter, @Nullable String broadcastPermission,
@Nullable Handler scheduler);
@@ -2691,6 +2706,7 @@
* @hide like {@link #startForegroundService(Intent)} but for a specific user.
*/
@Nullable
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
public abstract ComponentName startForegroundServiceAsUser(Intent service, UserHandle user);
/**
@@ -2728,11 +2744,13 @@
* @hide like {@link #startService(Intent)} but for a specific user.
*/
@Nullable
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
public abstract ComponentName startServiceAsUser(Intent service, UserHandle user);
/**
* @hide like {@link #stopService(Intent)} but for a specific user.
*/
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
public abstract boolean stopServiceAsUser(Intent service, UserHandle user);
/**
@@ -2792,6 +2810,7 @@
*/
@SystemApi
@SuppressWarnings("unused")
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
public boolean bindServiceAsUser(@RequiresPermission Intent service, ServiceConnection conn,
int flags, UserHandle user) {
throw new RuntimeException("Not implemented. Must override in a subclass.");
@@ -2803,6 +2822,7 @@
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
Handler handler, UserHandle user) {
throw new RuntimeException("Not implemented. Must override in a subclass.");
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index 88aae66..b463ec6 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -16,6 +16,7 @@
package android.content;
+import android.annotation.SystemService;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.pm.ApplicationInfo;
@@ -120,6 +121,7 @@
* @see DevicePolicyManager#setRestrictionsProvider(ComponentName, ComponentName)
* @see DevicePolicyManager#setApplicationRestrictions(ComponentName, String, Bundle)
*/
+@SystemService(Context.RESTRICTIONS_SERVICE)
public class RestrictionsManager {
private static final String TAG = "RestrictionsManager";
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 8ead0ec..ed41e79 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
+import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.TestApi;
import android.app.PendingIntent;
@@ -79,6 +80,7 @@
* Note as of Android O, apps on a managed profile are no longer allowed to access apps on the
* main profile. Apps can only access profiles returned by {@link #getProfiles()}.
*/
+@SystemService(Context.LAUNCHER_APPS_SERVICE)
public class LauncherApps {
static final String TAG = "LauncherApps";
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 4e11233..7f3f35f 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -473,6 +473,7 @@
/** {@hide} */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
public void setPermissionsResult(int sessionId, boolean accepted) {
try {
mInstaller.setPermissionsResult(sessionId, accepted);
@@ -1156,6 +1157,7 @@
/** {@hide} */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE)
public void setAllocateAggressive(boolean allocateAggressive) {
if (allocateAggressive) {
installFlags |= PackageManager.INSTALL_ALLOCATE_AGGRESSIVE;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a68c097..be2cd10 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3208,8 +3208,7 @@
/**
* Return a List of all packages that are installed on the device, for a
- * specific user. Requesting a list of installed packages for another user
- * will require the permission INTERACT_ACROSS_USERS_FULL.
+ * specific user.
*
* @param flags Additional option flags to modify the data returned.
* @param userId The user for whom the installed packages are to be listed
@@ -3224,6 +3223,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
public abstract List<PackageInfo> getInstalledPackagesAsUser(@PackageInfoFlags int flags,
@UserIdInt int userId);
@@ -3365,6 +3365,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
public abstract void grantRuntimePermission(@NonNull String packageName,
@NonNull String permissionName, @NonNull UserHandle user);
@@ -3390,6 +3391,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
public abstract void revokeRuntimePermission(@NonNull String packageName,
@NonNull String permissionName, @NonNull UserHandle user);
@@ -3404,6 +3406,10 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+ android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
+ })
public abstract @PermissionFlags int getPermissionFlags(String permissionName,
String packageName, @NonNull UserHandle user);
@@ -3420,6 +3426,10 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+ android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
+ })
public abstract void updatePermissionFlags(String permissionName,
String packageName, @PermissionFlags int flagMask, @PermissionFlags int flagValues,
@NonNull UserHandle user);
@@ -4719,6 +4729,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.INTENT_FILTER_VERIFICATION_AGENT)
public abstract void verifyIntentFilter(int verificationId, int verificationCode,
List<String> failedDomains);
@@ -4766,6 +4777,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
public abstract boolean updateIntentVerificationStatusAsUser(String packageName, int status,
@UserIdInt int userId);
@@ -4826,6 +4838,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
public abstract boolean setDefaultBrowserPackageNameAsUser(String packageName,
@UserIdInt int userId);
@@ -5289,6 +5302,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
public abstract void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener);
/**
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 4cee2df..99700df 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -18,7 +18,11 @@
import android.content.ComponentName;
import android.content.Intent;
+import android.content.pm.PackageManager.ApplicationInfoFlags;
+import android.content.pm.PackageManager.ComponentInfoFlags;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManager.PackageInfoFlags;
+import android.content.pm.PackageManager.ResolveInfoFlags;
import android.os.Bundle;
import android.util.SparseArray;
@@ -133,16 +137,40 @@
public abstract boolean isPermissionsReviewRequired(String packageName, int userId);
/**
- * Gets all of the information we know about a particular package.
- *
- * @param packageName The package name to find.
- * @param userId The user under which to check.
- *
- * @return An {@link ApplicationInfo} containing information about the
- * package, or {@code null} if no application exists with that
- * package name.
+ * Retrieve all of the information we know about a particular package/application.
+ * @param filterCallingUid The results will be filtered in the context of this UID instead
+ * of the calling UID.
+ * @see PackageManager#getPackageInfo(String, int)
*/
- public abstract ApplicationInfo getApplicationInfo(String packageName, int userId);
+ public abstract PackageInfo getPackageInfo(String packageName,
+ @PackageInfoFlags int flags, int filterCallingUid, int userId);
+
+ /**
+ * Retrieve all of the information we know about a particular package/application.
+ * @param filterCallingUid The results will be filtered in the context of this UID instead
+ * of the calling UID.
+ * @see PackageManager#getApplicationInfo(String, int)
+ */
+ public abstract ApplicationInfo getApplicationInfo(String packageName,
+ @ApplicationInfoFlags int flags, int filterCallingUid, int userId);
+
+ /**
+ * Retrieve all of the information we know about a particular activity class.
+ * @param filterCallingUid The results will be filtered in the context of this UID instead
+ * of the calling UID.
+ * @see PackageManager#getActivityInfo(ComponentName, int)
+ */
+ public abstract ActivityInfo getActivityInfo(ComponentName component,
+ @ComponentInfoFlags int flags, int filterCallingUid, int userId);
+
+ /**
+ * Retrieve all activities that can be performed for the given intent.
+ * @param filterCallingUid The results will be filtered in the context of this UID instead
+ * of the calling UID.
+ * @see PackageManager#queryIntentActivities(Intent, int)
+ */
+ public abstract List<ResolveInfo> queryIntentActivities(Intent intent,
+ @ResolveInfoFlags int flags, int filterCallingUid, int userId);
/**
* Interface to {@link com.android.server.pm.PackageManagerService#getHomeActivitiesAsUser}.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 9b0bab4..5e5a6fc 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -7000,6 +7000,7 @@
return null;
}
if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
+ updateApplicationInfo(a.info.applicationInfo, flags, state);
return a.info;
}
// Make shallow copies so we can store the metadata safely
@@ -7088,6 +7089,7 @@
return null;
}
if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
+ updateApplicationInfo(s.info.applicationInfo, flags, state);
return s.info;
}
// Make shallow copies so we can store the metadata safely
@@ -7183,6 +7185,7 @@
if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
&& ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
|| p.info.uriPermissionPatterns == null)) {
+ updateApplicationInfo(p.info.applicationInfo, flags, state);
return p.info;
}
// Make shallow copies so we can store the metadata safely
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index f779aeb..c0b82b4 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -17,6 +17,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.UserIdInt;
import android.app.Activity;
@@ -24,6 +25,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
+import android.graphics.drawable.AdaptiveIconDrawable;
import android.os.Build.VERSION_CODES;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -335,6 +337,14 @@
* {@link #isRequestPinShortcutSupported()}. Based on this return value, you might decide to hide
* the option in your app that allows users to pin a shortcut.
*
+ * <p class="note"><strong>Note:</strong> See also the support library APIs
+ * {@link android.support.v4.content.pm.ShortcutManagerCompat#isRequestPinShortcutSupported(
+ * Context)} and
+ * {@link android.support.v4.content.pm.ShortcutManagerCompat#requestPinShortcut(
+ * Context, ShortcutInfoCompat, IntentSender)}, which works on Android versions lower than
+ * {@link VERSION_CODES#O} by falling back to the deprecated private intent
+ * {@code com.android.launcher.action.INSTALL_SHORTCUT}.
+ *
* <h4>Custom Activity for Pinning Shortcuts</h4>
*
* <p>You can also create a specialized activity that helps users create shortcuts, complete with
@@ -569,6 +579,7 @@
* All shortcut information is stored in credential encrypted storage, so no shortcuts can be
* accessed when the user is locked.
*/
+@SystemService(Context.SHORTCUT_SERVICE)
public class ShortcutManager {
private static final String TAG = "ShortcutManager";
@@ -889,7 +900,7 @@
*
* <p> Note that this method returns max width of icon's visible part. Hence, it does not take
* into account the inset introduced by {@link AdaptiveIconDrawable}. To calculate bitmap image
- * to function as {@link AcaptiveIconDrawable}, multiply
+ * to function as {@link AdaptiveIconDrawable}, multiply
* 1 + 2 * {@link AdaptiveIconDrawable#getExtraInsetFraction()} to the returned size.
*/
public int getIconMaxWidth() {
@@ -938,8 +949,15 @@
* Return {@code TRUE} if the app is running on a device whose default launcher supports
* {@link #requestPinShortcut(ShortcutInfo, IntentSender)}.
*
- * <p><b>Note:</b> The return value may change in subsequent calls, if the user changes
- * the default launcher app.
+ * <p>The return value may change in subsequent calls if the user changes the default launcher
+ * app.
+ *
+ * <p><b>Note:</b> See also the support library counterpart
+ * {@link android.support.v4.content.pm.ShortcutManagerCompat#isRequestPinShortcutSupported(
+ * Context)}, which supports Android versions lower than {@link VERSION_CODES#O} using the
+ * legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}.
+ *
+ * @see #requestPinShortcut(ShortcutInfo, IntentSender)
*/
public boolean isRequestPinShortcutSupported() {
try {
@@ -963,6 +981,12 @@
* package calls this API multiple times in a row. One possible strategy is to ignore any
* previous requests.
*
+ * <p><b>Note:</b> See also the support library counterpart
+ * {@link android.support.v4.content.pm.ShortcutManagerCompat#requestPinShortcut(
+ * Context, ShortcutInfoCompat, IntentSender)},
+ * which supports Android versions lower than {@link VERSION_CODES#O} using the
+ * legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}.
+ *
* @param shortcut Shortcut to pin. If an app wants to pin an existing (either static
* or dynamic) shortcut, then it only needs to have an ID. Although other fields don't have
* to be set, the target shortcut must be enabled.
diff --git a/core/java/android/hardware/ConsumerIrManager.java b/core/java/android/hardware/ConsumerIrManager.java
index b221e16..c7a33ff 100644
--- a/core/java/android/hardware/ConsumerIrManager.java
+++ b/core/java/android/hardware/ConsumerIrManager.java
@@ -16,6 +16,7 @@
package android.hardware;
+import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -24,14 +25,8 @@
/**
* Class that operates consumer infrared on the device.
- *
- * <p>
- * To obtain an instance of the system infrared transmitter, call
- * {@link android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with
- * {@link android.content.Context#CONSUMER_IR_SERVICE} as the argument.
- * </p>
*/
+@SystemService(Context.CONSUMER_IR_SERVICE)
public final class ConsumerIrManager {
private static final String TAG = "ConsumerIr";
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index ed56391..4bc62b1 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -17,6 +17,8 @@
package android.hardware;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.MemoryFile;
@@ -30,10 +32,7 @@
/**
* <p>
* SensorManager lets you access the device's {@link android.hardware.Sensor
- * sensors}. Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with the argument
- * {@link android.content.Context#SENSOR_SERVICE}.
+ * sensors}.
* </p>
* <p>
* Always make sure to disable sensors you don't need, especially when your
@@ -79,6 +78,7 @@
* @see Sensor
*
*/
+@SystemService(Context.SENSOR_SERVICE)
public abstract class SensorManager {
/** @hide */
protected static final String TAG = "SensorManager";
diff --git a/core/java/android/hardware/SerialManager.java b/core/java/android/hardware/SerialManager.java
index 83f7649..610f6a5 100644
--- a/core/java/android/hardware/SerialManager.java
+++ b/core/java/android/hardware/SerialManager.java
@@ -16,6 +16,7 @@
package android.hardware;
+import android.annotation.SystemService;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -25,6 +26,7 @@
/**
* @hide
*/
+@SystemService(Context.SERIAL_SERVICE)
public class SerialManager {
private static final String TAG = "SerialManager";
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index f61032e..1b150bf 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -17,6 +17,7 @@
package android.hardware.camera2;
import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -44,15 +45,11 @@
* <p>A system service manager for detecting, characterizing, and connecting to
* {@link CameraDevice CameraDevices}.</p>
*
- * <p>You can get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String) Context.getSystemService()}.</p>
- *
- * <pre>CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);</pre>
- *
* <p>For more details about communicating with camera devices, read the Camera
* developer guide or the {@link android.hardware.camera2 camera2}
* package documentation.</p>
*/
+@SystemService(Context.CAMERA_SERVICE)
public final class CameraManager {
private static final String TAG = "CameraManager";
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 266be9a..6a02b6b 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemService;
import android.content.Context;
import android.media.projection.MediaProjection;
import android.os.Handler;
@@ -29,13 +30,8 @@
/**
* Manages the properties of attached displays.
- * <p>
- * Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with the argument
- * {@link android.content.Context#DISPLAY_SERVICE}.
- * </p>
*/
+@SystemService(Context.DISPLAY_SERVICE)
public final class DisplayManager {
private static final String TAG = "DisplayManager";
private static final boolean DEBUG = false;
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 324a08c..b51a791 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
import android.app.ActivityManager;
import android.content.Context;
import android.os.Binder;
@@ -47,12 +48,8 @@
/**
* A class that coordinates access to the fingerprint hardware.
- * <p>
- * Use {@link android.content.Context#getSystemService(java.lang.String)}
- * with argument {@link android.content.Context#FINGERPRINT_SERVICE} to get
- * an instance of this class.
*/
-
+@SystemService(Context.FINGERPRINT_SERVICE)
public class FingerprintManager {
private static final String TAG = "FingerprintManager";
private static final boolean DEBUG = true;
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 27e2a50..a772cbe 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -17,9 +17,13 @@
package android.hardware.hdmi;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
+import android.content.Context;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Log;
@@ -37,6 +41,7 @@
* @hide
*/
@SystemApi
+@SystemService(Context.HDMI_CONTROL_SERVICE)
public final class HdmiControlManager {
private static final String TAG = "HdmiControlManager";
@@ -295,6 +300,7 @@
* See {@link HdmiDeviceInfo#DEVICE_TV}
*/
@Nullable
+ @SuppressLint("Doclava125")
public HdmiClient getClient(int type) {
if (mService == null) {
return null;
@@ -319,6 +325,7 @@
* @return {@link HdmiPlaybackClient} instance. {@code null} on failure.
*/
@Nullable
+ @SuppressLint("Doclava125")
public HdmiPlaybackClient getPlaybackClient() {
return (HdmiPlaybackClient) getClient(HdmiDeviceInfo.DEVICE_PLAYBACK);
}
@@ -333,6 +340,7 @@
* @return {@link HdmiTvClient} instance. {@code null} on failure.
*/
@Nullable
+ @SuppressLint("Doclava125")
public HdmiTvClient getTvClient() {
return (HdmiTvClient) getClient(HdmiDeviceInfo.DEVICE_TV);
}
@@ -343,6 +351,7 @@
*
* @param isStandbyModeOn target status of the system's standby mode
*/
+ @RequiresPermission(android.Manifest.permission.HDMI_CEC)
public void setStandbyMode(boolean isStandbyModeOn) {
try {
mService.setStandbyMode(isStandbyModeOn);
@@ -403,6 +412,7 @@
* @param listener {@link HotplugEventListener} instance
* @see HdmiControlManager#removeHotplugEventListener(HotplugEventListener)
*/
+ @RequiresPermission(android.Manifest.permission.HDMI_CEC)
public void addHotplugEventListener(HotplugEventListener listener) {
if (mService == null) {
Log.e(TAG, "HdmiControlService is not available");
@@ -426,6 +436,7 @@
*
* @param listener {@link HotplugEventListener} instance to be removed
*/
+ @RequiresPermission(android.Manifest.permission.HDMI_CEC)
public void removeHotplugEventListener(HotplugEventListener listener) {
if (mService == null) {
Log.e(TAG, "HdmiControlService is not available");
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 631b77d..5149e93 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -21,6 +21,7 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
+import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.media.AudioAttributes;
@@ -53,13 +54,8 @@
/**
* Provides information about input devices and available key layouts.
- * <p>
- * Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with the argument
- * {@link android.content.Context#INPUT_SERVICE}.
- * </p>
*/
+@SystemService(Context.INPUT_SERVICE)
public final class InputManager {
private static final String TAG = "InputManager";
private static final boolean DEBUG = false;
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 7c4df47..6050046 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -15,7 +15,10 @@
*/
package android.hardware.location;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
@@ -33,6 +36,7 @@
* @hide
*/
@SystemApi
+@SystemService(Context.CONTEXTHUB_SERVICE)
public final class ContextHubManager {
private static final String TAG = "ContextHubManager";
@@ -91,6 +95,7 @@
* Get a handle to all the context hubs in the system
* @return array of context hub handles
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public int[] getContextHubHandles() {
try {
return mService.getContextHubHandles();
@@ -107,6 +112,7 @@
*
* @see ContextHubInfo
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public ContextHubInfo getContextHubInfo(int hubHandle) {
try {
return mService.getContextHubInfo(hubHandle);
@@ -134,6 +140,7 @@
*
* @see NanoApp
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public int loadNanoApp(int hubHandle, NanoApp app) {
try {
return mService.loadNanoApp(hubHandle, app);
@@ -157,6 +164,7 @@
* @return 0 if the command for unloading was sent to the context hub;
* -1 otherwise
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public int unloadNanoApp(int nanoAppHandle) {
try {
return mService.unloadNanoApp(nanoAppHandle);
@@ -191,6 +199,7 @@
*
* @see NanoAppInstanceInfo
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
try {
return mService.getNanoAppInstanceInfo(nanoAppHandle);
@@ -209,6 +218,7 @@
*
* @return int[] Array of handles to any found nano apps
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
try {
return mService.findNanoAppOnHub(hubHandle, filter);
@@ -236,6 +246,7 @@
*
* @return int 0 on success, -1 otherwise
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage message) {
try {
return mService.sendMessage(hubHandle, nanoAppHandle, message);
@@ -253,6 +264,7 @@
*
* @return int 0 on success, -1 otherwise
*/
+ @SuppressLint("Doclava125")
public int registerCallback(Callback callback) {
return registerCallback(callback, null);
}
@@ -281,6 +293,7 @@
*
* @return int 0 on success, -1 otherwise
*/
+ @SuppressLint("Doclava125")
public int registerCallback(Callback callback, Handler handler) {
synchronized(this) {
if (mCallback != null) {
@@ -302,6 +315,7 @@
*
* @return int 0 on success, -1 otherwise
*/
+ @SuppressLint("Doclava125")
public int unregisterCallback(Callback callback) {
synchronized(this) {
if (callback != mCallback) {
diff --git a/core/java/android/hardware/radio/RadioManager.java b/core/java/android/hardware/radio/RadioManager.java
index 14bb923..403b13c 100644
--- a/core/java/android/hardware/radio/RadioManager.java
+++ b/core/java/android/hardware/radio/RadioManager.java
@@ -17,6 +17,7 @@
package android.hardware.radio;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.Context;
import android.os.Handler;
import android.os.Parcel;
@@ -32,6 +33,7 @@
* @hide
*/
@SystemApi
+@SystemService(Context.RADIO_SERVICE)
public class RadioManager {
/** Method return status: successful operation */
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index b2a2aaf..33a92fd 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -19,6 +19,7 @@
import android.annotation.Nullable;
import android.annotation.SdkConstant;
+import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.PendingIntent;
import android.content.ComponentName;
@@ -38,18 +39,13 @@
* This class allows you to access the state of USB and communicate with USB devices.
* Currently only host mode is supported in the public API.
*
- * <p>You can obtain an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- *
- * {@samplecode
- * UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);}
- *
* <div class="special reference">
* <h3>Developer Guides</h3>
* <p>For more information about communicating with USB hardware, read the
* <a href="{@docRoot}guide/topics/connectivity/usb/index.html">USB developer guide</a>.</p>
* </div>
*/
+@SystemService(Context.USB_SERVICE)
public class UsbManager {
private static final String TAG = "UsbManager";
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index b0cc38c..e64cbcd 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -23,6 +23,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
@@ -64,9 +65,7 @@
/**
* Class that answers queries about the state of network connectivity. It also
- * notifies applications when network connectivity changes. Get an instance
- * of this class by calling
- * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.CONNECTIVITY_SERVICE)}.
+ * notifies applications when network connectivity changes.
* <p>
* The primary responsibilities of this class are to:
* <ol>
@@ -80,6 +79,7 @@
* traffic</li>
* </ol>
*/
+@SystemService(Context.CONNECTIVITY_SERVICE)
public class ConnectivityManager {
private static final String TAG = "ConnectivityManager";
@@ -2105,6 +2105,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
public void startTethering(int type, boolean showProvisioningUi,
final OnStartTetheringCallback callback, Handler handler) {
checkNotNull(callback, "OnStartTetheringCallback cannot be null.");
@@ -2139,6 +2140,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
public void stopTethering(int type) {
try {
mService.stopTethering(type);
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index 664b7b4..31a3096 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -16,6 +16,7 @@
package android.net;
+import android.annotation.SystemService;
import android.content.Context;
import android.net.IEthernetManager;
import android.net.IEthernetServiceListener;
@@ -31,6 +32,7 @@
*
* @hide
*/
+@SystemService(Context.ETHERNET_SERVICE)
public class EthernetManager {
private static final String TAG = "EthernetManager";
private static final int MSG_AVAILABILITY_CHANGED = 1000;
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 114e46e..e3cda5e 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -18,6 +18,8 @@
import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.NonNull;
+import android.annotation.SystemService;
+import android.content.Context;
import android.os.Binder;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
@@ -34,12 +36,9 @@
* This class contains methods for managing IPsec sessions, which will perform kernel-space
* encryption and decryption of socket or Network traffic.
*
- * <p>An IpSecManager may be obtained by calling {@link
- * android.content.Context#getSystemService(String) Context#getSystemService(String)} with {@link
- * android.content.Context#IPSEC_SERVICE Context#IPSEC_SERVICE}
- *
* @hide
*/
+@SystemService(Context.IPSEC_SERVICE)
public final class IpSecManager {
private static final String TAG = "IpSecManager";
diff --git a/core/java/android/net/NetworkBadging.java b/core/java/android/net/NetworkBadging.java
index 6de28b7..c119b63 100644
--- a/core/java/android/net/NetworkBadging.java
+++ b/core/java/android/net/NetworkBadging.java
@@ -66,15 +66,7 @@
*/
@NonNull public static Drawable getWifiIcon(
@IntRange(from=0, to=4) int signalLevel, @Badging int badging, @Nullable Theme theme) {
- Resources resources = Resources.getSystem();
- if (badging == BADGING_NONE) {
- return resources.getDrawable(getWifiSignalResource(signalLevel), theme);
- }
- Drawable[] layers = new Drawable[] {
- resources.getDrawable(getBadgedWifiSignalResource(signalLevel), theme),
- resources.getDrawable(getWifiBadgeResource(badging), theme)
- };
- return new LayerDrawable(layers);
+ return Resources.getSystem().getDrawable(getWifiSignalResource(signalLevel), theme);
}
/**
@@ -134,31 +126,4 @@
throw new IllegalArgumentException("Invalid signal level: " + signalLevel);
}
}
-
- /**
- * Returns the wifi quality badge resource id for the the given badging balue.
- *
- * <p>This badge should be displayed with the badge signal resource retrieved from
- * {@link #getBadgedWifiSignalResource(int)}.
- *
- * @param badging {@see NetworkBadging#Badging} from {@link ScoredNetwork#calculateBadge(int)}.
- * @return the @DrawableRes for the icon or {@link View#NO_ID} for
- * {@link NetworkBadging#BADGING_NONE}
- * @throws IllegalArgumentException for an invalid badging value.
- * @hide
- */
- @DrawableRes private static int getWifiBadgeResource(@Badging int badging) {
- switch (badging) {
- case BADGING_NONE:
- return View.NO_ID;
- case BADGING_SD:
- return com.android.internal.R.drawable.ic_signal_wifi_badged_sd;
- case BADGING_HD:
- return com.android.internal.R.drawable.ic_signal_wifi_badged_hd;
- case BADGING_4K:
- return com.android.internal.R.drawable.ic_signal_wifi_badged_4k;
- default:
- throw new IllegalArgumentException("No resource found for badge: " + badging);
- }
- }
}
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 43fab03..4d94a55 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -19,6 +19,7 @@
import static android.content.pm.PackageManager.GET_SIGNATURES;
import static android.net.NetworkPolicy.CYCLE_NONE;
+import android.annotation.SystemService;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
@@ -40,6 +41,7 @@
*
* {@hide}
*/
+@SystemService(Context.NETWORK_POLICY_SERVICE)
public class NetworkPolicyManager {
/* POLICY_* are masks and can be ORed, although currently they are not.*/
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 9f6e45c..7e0c9ce 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -19,9 +19,11 @@
import android.Manifest.permission;
import android.annotation.IntDef;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -34,12 +36,6 @@
/**
* Class that manages communication between network subsystems and a network scorer.
*
- * <p>You can get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String)}:
- *
- * <pre>NetworkScoreManager manager =
- * (NetworkScoreManager) getSystemService(Context.NETWORK_SCORE_SERVICE)</pre>
- *
* <p>A network scorer is any application which:
* <ul>
* <li>Declares the {@link permission#SCORE_NETWORKS} permission.
@@ -51,6 +47,7 @@
* @hide
*/
@SystemApi
+@SystemService(Context.NETWORK_SCORE_SERVICE)
public class NetworkScoreManager {
/**
* Activity action: ask the user to change the active network scorer. This will show a dialog
@@ -243,6 +240,7 @@
* @hide
*/
@Nullable
+ @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
public NetworkScorerAppData getActiveScorer() {
try {
return mService.getActiveScorer();
@@ -276,6 +274,7 @@
* @return whether the update was successful.
* @throws SecurityException if the caller is not the active scorer.
*/
+ @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS)
public boolean updateScores(ScoredNetwork[] networks) throws SecurityException {
try {
return mService.updateScores(networks);
@@ -296,6 +295,7 @@
* @return whether the clear was successful.
* @throws SecurityException if the caller is not the active scorer or privileged.
*/
+ @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
public boolean clearScores() throws SecurityException {
try {
return mService.clearScores();
@@ -316,6 +316,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS)
public boolean setActiveScorer(String packageName) throws SecurityException {
try {
return mService.setActiveScorer(packageName);
@@ -331,6 +332,7 @@
*
* @throws SecurityException if the caller is neither the active scorer nor the system.
*/
+ @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
public void disableScoring() throws SecurityException {
try {
mService.disableScoring();
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index fc66395..f934616 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -16,6 +16,7 @@
package android.net;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.DownloadManager;
import android.app.backup.BackupManager;
@@ -243,6 +244,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
public static void setThreadStatsUid(int uid) {
NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
}
@@ -255,6 +257,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
public static void clearThreadStatsUid() {
NetworkManagementSocketTagger.setThreadSocketStatsUid(-1);
}
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index c6daa15..2d9860c 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -19,6 +19,7 @@
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_INET6;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.Activity;
import android.app.PendingIntent;
@@ -177,6 +178,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.CONTROL_VPN)
public static void prepareAndAuthorize(Context context) {
IConnectivityManager cm = getService();
String packageName = context.getPackageName();
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index 1dde3ca..2d480a1 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -17,6 +17,7 @@
package android.net.nsd;
import android.annotation.SdkConstant;
+import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.os.Handler;
@@ -113,11 +114,9 @@
* http://www.iana.org/form/ports-service. Existing services can be found at
* http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml
*
- * Get an instance of this class by calling {@link android.content.Context#getSystemService(String)
- * Context.getSystemService(Context.NSD_SERVICE)}.
- *
* {@see NsdServiceInfo}
*/
+@SystemService(Context.NSD_SERVICE)
public final class NsdManager {
private static final String TAG = NsdManager.class.getSimpleName();
private static final boolean DBG = false;
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 783c25a..48869c7 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -18,6 +18,7 @@
import java.util.HashMap;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
@@ -725,6 +726,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean enable() {
try {
return sService.enable();
@@ -753,6 +755,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean disable() {
try {
return sService.disable(true);
@@ -767,6 +770,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean disable(boolean persist) {
try {
return sService.disable(persist);
@@ -1552,6 +1556,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean enableNdefPush() {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
@@ -1570,6 +1575,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean disableNdefPush() {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
@@ -1736,6 +1742,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler,
String[] tagTechnologies) {
synchronized (NfcAdapter.class) {
@@ -1785,6 +1792,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
diff --git a/core/java/android/nfc/NfcManager.java b/core/java/android/nfc/NfcManager.java
index ea08014..50d6745 100644
--- a/core/java/android/nfc/NfcManager.java
+++ b/core/java/android/nfc/NfcManager.java
@@ -16,6 +16,7 @@
package android.nfc;
+import android.annotation.SystemService;
import android.content.Context;
/**
@@ -34,9 +35,9 @@
* <a href="{@docRoot}guide/topics/nfc/index.html">Near Field Communication</a> developer guide.</p>
* </div>
*
- * @see Context#getSystemService
* @see NfcAdapter#getDefaultAdapter(android.content.Context)
*/
+@SystemService(Context.NFC_SERVICE)
public final class NfcManager {
private final NfcAdapter mAdapter;
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 734d89e..f715f50 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -16,6 +16,8 @@
package android.os;
+import android.annotation.SystemService;
+import android.content.Context;
import android.hardware.health.V1_0.Constants;
import com.android.internal.app.IBatteryStats;
@@ -24,6 +26,7 @@
* in the {@link android.content.Intent#ACTION_BATTERY_CHANGED} Intent, and
* provides a method for querying battery and charging properties.
*/
+@SystemService(Context.BATTERY_SERVICE)
public class BatteryManager {
/**
* Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index ecc4dec..635df4c 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -201,7 +201,7 @@
* New in version 22:
* - BLE scan result background count, BLE unoptimized scan time
*/
- static final String CHECKIN_VERSION = "22";
+ static final String CHECKIN_VERSION = "23";
/**
* Old version, we hit 9 and ran out of room, need to remove.
@@ -3051,6 +3051,7 @@
boolean wifiOnly) {
final long rawUptime = SystemClock.uptimeMillis() * 1000;
final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
+ final long rawRealtimeMs = (rawRealtime + 500) / 1000;
final long batteryUptime = getBatteryUptime(rawUptime);
final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
@@ -3437,7 +3438,6 @@
final int count = bleTimer.getCountLocked(which);
final Timer bleTimerBg = u.getBluetoothScanBackgroundTimer();
final int countBg = bleTimerBg != null ? bleTimerBg.getCountLocked(which) : 0;
- final long rawRealtimeMs = (rawRealtime + 500) / 1000;
// 'actualTime' are unpooled and always since reset (regardless of 'which')
final long actualTime = bleTimer.getTotalDurationMsLocked(rawRealtimeMs);
final long actualTimeBg = bleTimerBg != null ?
@@ -3486,11 +3486,11 @@
if (u.getAggregatedPartialWakelockTimer() != null) {
final Timer timer = u.getAggregatedPartialWakelockTimer();
- // Convert from microseconds to milliseconds with rounding
- final long totTimeMs = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+ // Times are since reset (regardless of 'which')
+ final long totTimeMs = timer.getTotalDurationMsLocked(rawRealtimeMs);
final Timer bgTimer = timer.getSubTimer();
final long bgTimeMs = bgTimer != null ?
- (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : 0;
+ bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : 0;
dumpLine(pw, uid, category, AGGREGATED_WAKELOCK_DATA, totTimeMs, bgTimeMs);
}
@@ -3527,7 +3527,7 @@
final int count = timer.getCountLocked(which);
final Timer bgTimer = timer.getSubTimer();
final long bgTime = bgTimer != null ?
- (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+ bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : -1;
final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
if (totalTime != 0) {
dumpLine(pw, uid, category, SYNC_DATA, "\"" + syncs.keyAt(isy) + "\"",
@@ -3543,7 +3543,7 @@
final int count = timer.getCountLocked(which);
final Timer bgTimer = timer.getSubTimer();
final long bgTime = bgTimer != null ?
- (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+ bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : -1;
final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
if (totalTime != 0) {
dumpLine(pw, uid, category, JOB_DATA, "\"" + jobs.keyAt(ij) + "\"",
@@ -3574,7 +3574,6 @@
final int count = timer.getCountLocked(which);
final Timer bgTimer = se.getSensorBackgroundTime();
final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : 0;
- final long rawRealtimeMs = (rawRealtime + 500) / 1000;
// 'actualTime' are unpooled and always since reset (regardless of 'which')
final long actualTime = timer.getTotalDurationMsLocked(rawRealtimeMs);
final long bgActualTime = bgTimer != null ?
@@ -3715,6 +3714,7 @@
int reqUid, boolean wifiOnly) {
final long rawUptime = SystemClock.uptimeMillis() * 1000;
final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
+ final long rawRealtimeMs = (rawRealtime + 500) / 1000;
final long batteryUptime = getBatteryUptime(rawUptime);
final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
@@ -4655,7 +4655,6 @@
final int count = bleTimer.getCountLocked(which);
final Timer bleTimerBg = u.getBluetoothScanBackgroundTimer();
final int countBg = bleTimerBg != null ? bleTimerBg.getCountLocked(which) : 0;
- final long rawRealtimeMs = (rawRealtime + 500) / 1000;
// 'actualTime' are unpooled and always since reset (regardless of 'which')
final long actualTimeMs = bleTimer.getTotalDurationMsLocked(rawRealtimeMs);
final long actualTimeMsBg = bleTimerBg != null ?
@@ -4823,10 +4822,10 @@
final Timer aggTimer = u.getAggregatedPartialWakelockTimer();
// Convert from microseconds to milliseconds with rounding
actualTotalPartialWakelock =
- (aggTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+ aggTimer.getTotalDurationMsLocked(rawRealtimeMs);
final Timer bgAggTimer = aggTimer.getSubTimer();
actualBgPartialWakelock = bgAggTimer != null ?
- (bgAggTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : 0;
+ bgAggTimer.getTotalDurationMsLocked(rawRealtimeMs) : 0;
}
if (actualTotalPartialWakelock != 0 || actualBgPartialWakelock != 0 ||
@@ -4894,7 +4893,7 @@
final int count = timer.getCountLocked(which);
final Timer bgTimer = timer.getSubTimer();
final long bgTime = bgTimer != null ?
- (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+ bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : -1;
final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
sb.setLength(0);
sb.append(prefix);
@@ -4928,7 +4927,7 @@
final int count = timer.getCountLocked(which);
final Timer bgTimer = timer.getSubTimer();
final long bgTime = bgTimer != null ?
- (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+ bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : -1;
final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
sb.setLength(0);
sb.append(prefix);
@@ -4987,7 +4986,6 @@
final int count = timer.getCountLocked(which);
final Timer bgTimer = se.getSensorBackgroundTime();
final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : 0;
- final long rawRealtimeMs = (rawRealtime + 500) / 1000;
// 'actualTime' are unpooled and always since reset (regardless of 'which')
final long actualTime = timer.getTotalDurationMsLocked(rawRealtimeMs);
final long bgActualTime = bgTimer != null ?
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index db84b6f..97f0e0c 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -17,6 +17,7 @@
package android.os;
import android.annotation.SdkConstant;
+import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.util.Log;
@@ -36,13 +37,10 @@
* enqueued data exceeds the maximum size. You can think of this as a
* persistent, system-wide, blob-oriented "logcat".
*
- * <p>You can obtain an instance of this class by calling
- * {@link android.content.Context#getSystemService}
- * with {@link android.content.Context#DROPBOX_SERVICE}.
- *
* <p>DropBoxManager entries are not sent anywhere directly, but other system
* services and debugging tools may scan and upload entries for processing.
*/
+@SystemService(Context.DROPBOX_SERVICE)
public class DropBoxManager {
private static final String TAG = "DropBoxManager";
diff --git a/core/java/android/os/HardwarePropertiesManager.java b/core/java/android/os/HardwarePropertiesManager.java
index 67edefc..aad202e 100644
--- a/core/java/android/os/HardwarePropertiesManager.java
+++ b/core/java/android/os/HardwarePropertiesManager.java
@@ -17,6 +17,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.SystemService;
import android.content.Context;
import android.hardware.thermal.V1_0.Constants;
import android.util.Log;
@@ -28,6 +29,7 @@
* The HardwarePropertiesManager class provides a mechanism of accessing hardware state of a
* device: CPU, GPU and battery temperatures, CPU usage per core, fan speed, etc.
*/
+@SystemService(Context.HARDWARE_PROPERTIES_SERVICE)
public class HardwarePropertiesManager {
private static final String TAG = HardwarePropertiesManager.class.getSimpleName();
diff --git a/core/java/android/os/IncidentManager.java b/core/java/android/os/IncidentManager.java
index 976d594..bc8e2e4 100644
--- a/core/java/android/os/IncidentManager.java
+++ b/core/java/android/os/IncidentManager.java
@@ -16,7 +16,9 @@
package android.os;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.annotation.TestApi;
import android.content.Context;
import android.os.IIncidentManager;
@@ -31,6 +33,7 @@
*/
@SystemApi
@TestApi
+@SystemService(Context.INCIDENT_SERVICE)
public class IncidentManager {
private static final String TAG = "incident";
@@ -46,6 +49,10 @@
/**
* Take an incident report and put it in dropbox.
*/
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.DUMP,
+ android.Manifest.permission.PACKAGE_USAGE_STATS
+ })
public void reportIncident(IncidentReportArgs args) {
final IIncidentManager service = IIncidentManager.Stub.asInterface(
ServiceManager.getService("incident"));
@@ -76,6 +83,10 @@
* {@link android.util.proto.ProtoOutputStream#bytes bytes()} method to retrieve
* the encoded data for the header.
*/
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.DUMP,
+ android.Manifest.permission.PACKAGE_USAGE_STATS
+ })
public void reportIncident(String settingName, byte[] headerProto) {
// Sections
String setting = Settings.System.getString(mContext.getContentResolver(), settingName);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 7d1369f..a85ed9c 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -17,8 +17,10 @@
package android.os;
import android.annotation.IntDef;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.Context;
import android.util.Log;
import java.lang.annotation.Retention;
@@ -32,9 +34,6 @@
* Do not acquire {@link WakeLock}s unless you really need them, use the minimum levels
* possible, and be sure to release them as soon as possible.
* </p><p>
- * You can obtain an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- * </p><p>
* The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}.
* This will create a {@link PowerManager.WakeLock} object. You can then use methods
* on the wake lock object to control the power state of the device.
@@ -102,6 +101,7 @@
* permission in an {@code <uses-permission>} element of the application's manifest.
* </p>
*/
+@SystemService(Context.POWER_SERVICE)
public final class PowerManager {
private static final String TAG = "PowerManager";
@@ -689,6 +689,10 @@
* @hide Requires signature or system permission.
*/
@SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.DEVICE_POWER,
+ android.Manifest.permission.USER_ACTIVITY
+ })
public void userActivity(long when, int event, int flags) {
try {
mService.userActivity(when, event, flags);
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index d2598c7..ba339a3 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -18,7 +18,10 @@
import static java.nio.charset.StandardCharsets.UTF_8;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -67,6 +70,7 @@
* recovery system (the separate partition that can be used to install
* system updates, wipe user data, etc.)
*/
+@SystemService(Context.RECOVERY_SERVICE)
public class RecoverySystem {
private static final String TAG = "RecoverySystem";
@@ -387,6 +391,7 @@
* {@hide}
*/
@SystemApi
+ @SuppressLint("Doclava125")
public static boolean verifyPackageCompatibility(File compatibilityFile) throws IOException {
try (InputStream inputStream = new FileInputStream(compatibilityFile)) {
return verifyPackageCompatibility(inputStream);
@@ -409,6 +414,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.RECOVERY)
public static void processPackage(Context context,
File packageFile,
final ProgressListener listener,
@@ -469,6 +475,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.RECOVERY)
public static void processPackage(Context context,
File packageFile,
final ProgressListener listener)
@@ -490,6 +497,7 @@
* @throws IOException if writing the recovery command file
* fails, or if the reboot itself fails.
*/
+ @RequiresPermission(android.Manifest.permission.RECOVERY)
public static void installPackage(Context context, File packageFile)
throws IOException {
installPackage(context, packageFile, false);
@@ -511,6 +519,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.RECOVERY)
public static void installPackage(Context context, File packageFile, boolean processed)
throws IOException {
synchronized (sRequestLock) {
@@ -602,6 +611,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.RECOVERY)
public static void scheduleUpdateOnBoot(Context context, File packageFile)
throws IOException {
String filename = packageFile.getCanonicalPath();
@@ -639,6 +649,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.RECOVERY)
public static void cancelScheduledUpdate(Context context)
throws IOException {
RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
@@ -777,6 +788,10 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.RECOVERY,
+ android.Manifest.permission.REBOOT
+ })
public static void rebootWipeAb(Context context, File packageFile, String reason)
throws IOException {
String reasonArg = null;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 7bd3bf6..a7fc2e7 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -23,6 +23,7 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
@@ -63,6 +64,7 @@
* <p>
* See {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE} for more on managed profiles.
*/
+@SystemService(Context.USER_SERVICE)
public class UserManager {
private static final String TAG = "UserManager";
@@ -1038,12 +1040,12 @@
/**
* Checks if the calling app is running in a managed profile.
- * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
*
* @return whether the caller is in a managed profile.
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public boolean isManagedProfile() {
// No need for synchronization. Once it becomes non-null, it'll be non-null forever.
// Worst case we might end up calling the AIDL method multiple times but that's fine.
@@ -1067,6 +1069,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public boolean isManagedProfile(@UserIdInt int userId) {
if (userId == UserHandle.myUserId()) {
return isManagedProfile();
@@ -1252,7 +1255,6 @@
* @hide
*
* Returns who set a user restriction on a user.
- * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
* @param restrictionKey the string key representing the restriction
* @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
* @return The source of user restriction. Any combination of {@link #RESTRICTION_NOT_SET},
@@ -1263,6 +1265,7 @@
@Deprecated
@SystemApi
@UserRestrictionSource
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public int getUserRestrictionSource(String restrictionKey, UserHandle userHandle) {
try {
return mService.getUserRestrictionSource(restrictionKey, userHandle.getIdentifier());
@@ -1275,12 +1278,12 @@
* @hide
*
* Returns a list of users who set a user restriction on a given user.
- * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
* @param restrictionKey the string key representing the restriction
* @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
* @return a list of user ids enforcing this restriction.
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public List<EnforcingUser> getUserRestrictionSources(
String restrictionKey, UserHandle userHandle) {
try {
@@ -1622,9 +1625,10 @@
/**
* @hide
*
- * Returns the preferred account name for user creation. Requires MANAGE_USERS permission.
+ * Returns the preferred account name for user creation.
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public String getSeedAccountName() {
try {
return mService.getSeedAccountName();
@@ -1636,9 +1640,10 @@
/**
* @hide
*
- * Returns the preferred account type for user creation. Requires MANAGE_USERS permission.
+ * Returns the preferred account type for user creation.
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public String getSeedAccountType() {
try {
return mService.getSeedAccountType();
@@ -1650,11 +1655,11 @@
/**
* @hide
*
- * Returns the preferred account's options bundle for user creation. Requires MANAGE_USERS
- * permission.
+ * Returns the preferred account's options bundle for user creation.
* @return Any options set by the requestor that created the user.
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public PersistableBundle getSeedAccountOptions() {
try {
return mService.getSeedAccountOptions();
@@ -1686,9 +1691,10 @@
/**
* @hide
- * Clears the seed information used to create this user. Requires MANAGE_USERS permission.
+ * Clears the seed information used to create this user.
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public void clearSeedAccountData() {
try {
mService.clearSeedAccountData();
@@ -1771,13 +1777,13 @@
/**
* Returns serial numbers of all users on this device.
- * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
*
* @param excludeDying specify if the list should exclude users being removed.
* @return the list of serial numbers of users that exist on the device.
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public long[] getSerialNumbersOfUsers(boolean excludeDying) {
try {
List<UserInfo> users = mService.getUsers(excludeDying);
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 2f0eeca..8078fb8 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -17,6 +17,7 @@
package android.os;
import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
import android.app.ActivityThread;
import android.content.Context;
import android.media.AudioAttributes;
@@ -27,10 +28,8 @@
* <p>
* If your process exits, any vibration you started will stop.
* </p>
- *
- * To obtain an instance of the system vibrator, call
- * {@link Context#getSystemService} with {@link Context#VIBRATOR_SERVICE} as the argument.
*/
+@SystemService(Context.VIBRATOR_SERVICE)
public abstract class Vibrator {
private static final String TAG = "Vibrator";
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
index 7c0af25..bba4cd1 100644
--- a/core/java/android/os/health/SystemHealthManager.java
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -16,6 +16,7 @@
package android.os.health;
+import android.annotation.SystemService;
import android.content.Context;
import android.os.BatteryStats;
import android.os.Process;
@@ -40,6 +41,7 @@
* JobScheduler}), and while that can affect charging rates, it is still preferable
* to actually draining the battery.
*/
+@SystemService(Context.SYSTEM_HEALTH_SERVICE)
public class SystemHealthManager {
private final IBatteryStats mBatteryStats;
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index d81ee4e..5046735 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -25,7 +25,9 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.annotation.WorkerThread;
import android.app.ActivityThread;
import android.content.ContentResolver;
@@ -98,11 +100,8 @@
* guarantee the security of the OBB file itself: if any program modifies the
* OBB, there is no guarantee that a read from that OBB will produce the
* expected output.
- * <p>
- * Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String)} with an
- * argument of {@link android.content.Context#STORAGE_SERVICE}.
*/
+@SystemService(Context.STORAGE_SERVICE)
public class StorageManager {
private static final String TAG = "StorageManager";
@@ -1404,23 +1403,7 @@
/** {@hide} */
public static File maybeTranslateEmulatedPathToInternal(File path) {
- final IStorageManager storageManager = IStorageManager.Stub.asInterface(
- ServiceManager.getService("mount"));
- try {
- final VolumeInfo[] vols = storageManager.getVolumes(0);
- for (VolumeInfo vol : vols) {
- if ((vol.getType() == VolumeInfo.TYPE_EMULATED
- || vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.isMountedReadable()) {
- final File internalPath = FileUtils.rewriteAfterRename(vol.getPath(),
- vol.getInternalPath(), path);
- if (internalPath != null && internalPath.exists()) {
- return internalPath;
- }
- }
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ // Disabled now that FUSE has been replaced by sdcardfs
return path;
}
@@ -1701,8 +1684,9 @@
/** @hide */
@SystemApi
- public long getAllocatableBytes(@NonNull UUID storageUuid, @AllocateFlags int flags)
- throws IOException {
+ @SuppressLint("Doclava125")
+ public long getAllocatableBytes(@NonNull UUID storageUuid,
+ @RequiresPermission @AllocateFlags int flags) throws IOException {
try {
return mStorageManager.getAllocatableBytes(convert(storageUuid), flags);
} catch (ParcelableException e) {
@@ -1715,8 +1699,9 @@
/** @removed */
@Deprecated
- public long getAllocatableBytes(@NonNull File path, @AllocateFlags int flags)
- throws IOException {
+ @SuppressLint("Doclava125")
+ public long getAllocatableBytes(@NonNull File path,
+ @RequiresPermission @AllocateFlags int flags) throws IOException {
return getAllocatableBytes(getUuidForPath(path), flags);
}
@@ -1749,8 +1734,9 @@
/** @hide */
@SystemApi
+ @SuppressLint("Doclava125")
public void allocateBytes(@NonNull UUID storageUuid, @BytesLong long bytes,
- @AllocateFlags int flags) throws IOException {
+ @RequiresPermission @AllocateFlags int flags) throws IOException {
try {
mStorageManager.allocateBytes(convert(storageUuid), bytes, flags);
} catch (ParcelableException e) {
@@ -1762,8 +1748,9 @@
/** @removed */
@Deprecated
- public void allocateBytes(@NonNull File path, @BytesLong long bytes, @AllocateFlags int flags)
- throws IOException {
+ @SuppressLint("Doclava125")
+ public void allocateBytes(@NonNull File path, @BytesLong long bytes,
+ @RequiresPermission @AllocateFlags int flags) throws IOException {
allocateBytes(getUuidForPath(path), bytes, flags);
}
@@ -1798,8 +1785,9 @@
/** @hide */
@SystemApi
- public void allocateBytes(FileDescriptor fd, @BytesLong long bytes, @AllocateFlags int flags)
- throws IOException {
+ @SuppressLint("Doclava125")
+ public void allocateBytes(FileDescriptor fd, @BytesLong long bytes,
+ @RequiresPermission @AllocateFlags int flags) throws IOException {
final File file = ParcelFileDescriptor.getFile(fd);
for (int i = 0; i < 3; i++) {
try {
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 8ee0517..e8ff2e2 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.app.Activity;
import android.app.Application.ActivityLifecycleCallbacks;
import android.content.ComponentName;
@@ -57,14 +58,6 @@
/**
* System level service for accessing the printing capabilities of the platform.
- * <p>
- * To obtain a handle to the print manager do the following:
- * </p>
- *
- * <pre>
- * PrintManager printManager =
- * (PrintManager) context.getSystemService(Context.PRINT_SERVICE);
- * </pre>
*
* <h3>Print mechanics</h3>
* <p>
@@ -109,6 +102,7 @@
* @see PrintJob
* @see PrintJobInfo
*/
+@SystemService(Context.PRINT_SERVICE)
public final class PrintManager {
private static final String LOG_TAG = "PrintManager";
diff --git a/core/java/android/service/autofill/FillContext.java b/core/java/android/service/autofill/FillContext.java
index 251d346..6956c8a 100644
--- a/core/java/android/service/autofill/FillContext.java
+++ b/core/java/android/service/autofill/FillContext.java
@@ -114,7 +114,7 @@
*
* @hide
*/
- @NonNull public ViewNode[] findViewNodesByAutofillIds(@NonNull AutofillId[] ids) {
+ @NonNull public ViewNode[] findViewNodesByAutofillIds(@NonNull AutofillId... ids) {
final LinkedList<ViewNode> nodesToProcess = new LinkedList<>();
final ViewNode[] foundNodes = new AssistStructure.ViewNode[ids.length];
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 31b2dcc..d1ebc6e 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -318,6 +318,17 @@
}
/**
+ * The ID passed to setGroup(), or the override, or null.
+ * @hide
+ */
+ public String getGroup() {
+ if (overrideGroupKey != null) {
+ return overrideGroupKey;
+ }
+ return getNotification().getGroup();
+ }
+
+ /**
* Sets the override group key.
*/
public void setOverrideGroupKey(String overrideGroupKey) {
diff --git a/core/java/android/service/oemlock/OemLockManager.java b/core/java/android/service/oemlock/OemLockManager.java
index c4fbe5e..e2ade87 100644
--- a/core/java/android/service/oemlock/OemLockManager.java
+++ b/core/java/android/service/oemlock/OemLockManager.java
@@ -17,7 +17,10 @@
package android.service.oemlock;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
import android.os.RemoteException;
/**
@@ -31,6 +34,7 @@
* @hide
*/
@SystemApi
+@SystemService(Context.OEM_LOCK_SERVICE)
public class OemLockManager {
private IOemLockService mService;
@@ -55,6 +59,7 @@
*
* @see #isOemUnlockAllowedByCarrier()
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE)
public void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
try {
mService.setOemUnlockAllowedByCarrier(allowed, signature);
@@ -69,6 +74,7 @@
*
* @see #setOemUnlockAllowedByCarrier(boolean, byte[])
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE)
public boolean isOemUnlockAllowedByCarrier() {
try {
return mService.isOemUnlockAllowedByCarrier();
@@ -86,6 +92,7 @@
*
* @see #isOemUnlockAllowedByUser()
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE)
public void setOemUnlockAllowedByUser(boolean allowed) {
try {
mService.setOemUnlockAllowedByUser(allowed);
@@ -100,6 +107,7 @@
*
* @see #setOemUnlockAllowedByUser(boolean)
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE)
public boolean isOemUnlockAllowedByUser() {
try {
return mService.isOemUnlockAllowedByUser();
diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
index 326796a..fa75ad3 100644
--- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java
+++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
@@ -16,10 +16,14 @@
package android.service.persistentdata;
-import android.annotation.SystemApi;
import android.annotation.IntDef;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
import android.os.RemoteException;
-import android.util.Slog;
+import android.service.oemlock.OemLockManager;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -43,6 +47,7 @@
* @hide
*/
@SystemApi
+@SystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE)
public class PersistentDataBlockManager {
private static final String TAG = PersistentDataBlockManager.class.getSimpleName();
private IPersistentDataBlockService sService;
@@ -85,6 +90,7 @@
*
* @param data the data to write
*/
+ @SuppressLint("Doclava125")
public int write(byte[] data) {
try {
return sService.write(data);
@@ -96,6 +102,7 @@
/**
* Returns the data block stored on the persistent partition.
*/
+ @SuppressLint("Doclava125")
public byte[] read() {
try {
return sService.read();
@@ -109,6 +116,7 @@
*
* Return -1 on error.
*/
+ @RequiresPermission(android.Manifest.permission.ACCESS_PDB_STATE)
public int getDataBlockSize() {
try {
return sService.getDataBlockSize();
@@ -136,6 +144,7 @@
* It will also prevent any further {@link #write} operation until reboot,
* in order to prevent a potential race condition. See b/30352311.
*/
+ @RequiresPermission(android.Manifest.permission.OEM_UNLOCK_STATE)
public void wipe() {
try {
sService.wipe();
@@ -149,6 +158,7 @@
*
* @deprecated use {@link OemLockManager#setOemUnlockAllowedByUser(boolean)} instead.
*/
+ @RequiresPermission(android.Manifest.permission.OEM_UNLOCK_STATE)
public void setOemUnlockEnabled(boolean enabled) {
try {
sService.setOemUnlockEnabled(enabled);
@@ -162,6 +172,10 @@
*
* @deprecated use {@link OemLockManager#isOemUnlockAllowedByUser()} instead.
*/
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_OEM_UNLOCK_STATE,
+ android.Manifest.permission.OEM_UNLOCK_STATE
+ })
public boolean getOemUnlockEnabled() {
try {
return sService.getOemUnlockEnabled();
@@ -177,6 +191,10 @@
* {@link #FLASH_LOCK_UNLOCKED} if device bootloader is unlocked, or {@link #FLASH_LOCK_UNKNOWN}
* if this information cannot be ascertained on this device.
*/
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_OEM_UNLOCK_STATE,
+ android.Manifest.permission.OEM_UNLOCK_STATE
+ })
@FlashLockState
public int getFlashLockState() {
try {
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index a2a129d..625dd9e 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -235,6 +235,8 @@
@Override
public void hide() {
+ // Remove any pending messages to show the session
+ mHandlerCaller.removeMessages(MSG_SHOW);
mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_HIDE));
}
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index ad46d07..47b8d92 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -18,6 +18,7 @@
import android.annotation.LayoutRes;
import android.annotation.Nullable;
+import android.annotation.SystemService;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -47,10 +48,7 @@
* {@link android.app.Activity#getLayoutInflater()} or
* {@link Context#getSystemService} to retrieve a standard LayoutInflater instance
* that is already hooked up to the current context and correctly configured
- * for the device you are running on. For example:
- *
- * <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
- * (Context.LAYOUT_INFLATER_SERVICE);</pre>
+ * for the device you are running on.
*
* <p>
* To create a new LayoutInflater with an additional {@link Factory} for your
@@ -64,9 +62,8 @@
* to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
* it only works with an XmlPullParser returned from a compiled resource
* (R.<em>something</em> file.)
- *
- * @see Context#getSystemService
*/
+@SystemService(Context.LAYOUT_INFLATER_SERVICE)
public abstract class LayoutInflater {
private static final String TAG = LayoutInflater.class.getSimpleName();
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index b57ac66..ef78559 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -31,6 +31,7 @@
import android.graphics.Region;
import android.os.Build;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.SystemClock;
import android.util.AttributeSet;
@@ -452,6 +453,14 @@
}
}
+ private void updateOpaqueFlag() {
+ if (!PixelFormat.formatHasAlpha(mRequestedFormat)) {
+ mSurfaceFlags |= SurfaceControl.OPAQUE;
+ } else {
+ mSurfaceFlags &= ~SurfaceControl.OPAQUE;
+ }
+ }
+
private Rect getParentSurfaceInsets() {
final ViewRootImpl root = getViewRootImpl();
if (root == null) {
@@ -522,7 +531,9 @@
if (creating) {
mSurfaceSession = new SurfaceSession(viewRoot.mSurface);
mDeferredDestroySurfaceControl = mSurfaceControl;
- mSurfaceControl = new SurfaceControl(mSurfaceSession,
+
+ updateOpaqueFlag();
+ mSurfaceControl = new SurfaceControlWithBackground(mSurfaceSession,
"SurfaceView - " + viewRoot.getTitle().toString(),
mSurfaceWidth, mSurfaceHeight, mFormat,
mSurfaceFlags);
@@ -1071,4 +1082,126 @@
return mSurfaceFrame;
}
};
+
+ class SurfaceControlWithBackground extends SurfaceControl {
+ private SurfaceControl mBackgroundControl;
+ private boolean mOpaque = true;
+ public boolean mVisible = false;
+
+ public SurfaceControlWithBackground(SurfaceSession s,
+ String name, int w, int h, int format, int flags)
+ throws Exception {
+ super(s, name, w, h, format, flags);
+ mBackgroundControl = new SurfaceControl(s, "Background for - " + name, w, h,
+ PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM);
+ mOpaque = (flags & SurfaceControl.OPAQUE) != 0;
+ }
+
+ @Override
+ public void setAlpha(float alpha) {
+ super.setAlpha(alpha);
+ mBackgroundControl.setAlpha(alpha);
+ }
+
+ @Override
+ public void setLayer(int zorder) {
+ super.setLayer(zorder);
+ // -3 is below all other child layers as SurfaceView never goes below -2
+ mBackgroundControl.setLayer(-3);
+ }
+
+ @Override
+ public void setPosition(float x, float y) {
+ super.setPosition(x, y);
+ mBackgroundControl.setPosition(x, y);
+ }
+
+ @Override
+ public void setSize(int w, int h) {
+ super.setSize(w, h);
+ mBackgroundControl.setSize(w, h);
+ }
+
+ @Override
+ public void setWindowCrop(Rect crop) {
+ super.setWindowCrop(crop);
+ mBackgroundControl.setWindowCrop(crop);
+ }
+
+ @Override
+ public void setFinalCrop(Rect crop) {
+ super.setFinalCrop(crop);
+ mBackgroundControl.setFinalCrop(crop);
+ }
+
+ @Override
+ public void setLayerStack(int layerStack) {
+ super.setLayerStack(layerStack);
+ mBackgroundControl.setLayerStack(layerStack);
+ }
+
+ @Override
+ public void setOpaque(boolean isOpaque) {
+ super.setOpaque(isOpaque);
+ mOpaque = isOpaque;
+ updateBackgroundVisibility();
+ }
+
+ @Override
+ public void setSecure(boolean isSecure) {
+ super.setSecure(isSecure);
+ }
+
+ @Override
+ public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+ super.setMatrix(dsdx, dtdx, dsdy, dtdy);
+ mBackgroundControl.setMatrix(dsdx, dtdx, dsdy, dtdy);
+ }
+
+ @Override
+ public void hide() {
+ super.hide();
+ mVisible = false;
+ updateBackgroundVisibility();
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ mVisible = true;
+ updateBackgroundVisibility();
+ }
+
+ @Override
+ public void destroy() {
+ super.destroy();
+ mBackgroundControl.destroy();
+ }
+
+ @Override
+ public void release() {
+ super.release();
+ mBackgroundControl.release();
+ }
+
+ @Override
+ public void setTransparentRegionHint(Region region) {
+ super.setTransparentRegionHint(region);
+ mBackgroundControl.setTransparentRegionHint(region);
+ }
+
+ @Override
+ public void deferTransactionUntil(IBinder handle, long frame) {
+ super.deferTransactionUntil(handle, frame);
+ mBackgroundControl.deferTransactionUntil(handle, frame);
+ }
+
+ void updateBackgroundVisibility() {
+ if (mOpaque && mVisible) {
+ mBackgroundControl.show();
+ } else {
+ mBackgroundControl.hide();
+ }
+ }
+ }
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 25a58e6..7cec957 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -341,6 +341,7 @@
private boolean mEnabled;
private boolean mRequested = true;
+ private boolean mIsOpaque = false;
ThreadedRenderer(Context context, boolean translucent, String name) {
final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
@@ -355,6 +356,7 @@
long rootNodePtr = nCreateRootRenderNode();
mRootNode = RenderNode.adopt(rootNodePtr);
mRootNode.setClipToBounds(false);
+ mIsOpaque = !translucent;
mNativeProxy = nCreateProxy(translucent, rootNodePtr);
nSetName(mNativeProxy, name);
@@ -571,7 +573,12 @@
* Change the ThreadedRenderer's opacity
*/
void setOpaque(boolean opaque) {
- nSetOpaque(mNativeProxy, opaque && !mHasInsets);
+ mIsOpaque = opaque && !mHasInsets;
+ nSetOpaque(mNativeProxy, mIsOpaque);
+ }
+
+ boolean isOpaque() {
+ return mIsOpaque;
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a69b813..a9c85f0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1139,6 +1139,10 @@
/**
* Autofill type for views that cannot be autofilled.
+ *
+ * <p>Typically used when the view is read-only; for example, a text label.
+ *
+ * @see #getAutofillType()
*/
public static final int AUTOFILL_TYPE_NONE = 0;
@@ -1148,6 +1152,8 @@
* <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
* {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
* {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
+ *
+ * @see #getAutofillType()
*/
public static final int AUTOFILL_TYPE_TEXT = 1;
@@ -1157,6 +1163,8 @@
* <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
* {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
* {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
+ *
+ * @see #getAutofillType()
*/
public static final int AUTOFILL_TYPE_TOGGLE = 2;
@@ -1170,6 +1178,8 @@
*
* <p>The available options in the selection list are typically provided by
* {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
+ *
+ * @see #getAutofillType()
*/
public static final int AUTOFILL_TYPE_LIST = 3;
@@ -1182,6 +1192,8 @@
* <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
* {@link AutofillValue#forDate(long)}, and the values passed to
* autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
+ *
+ * @see #getAutofillType()
*/
public static final int AUTOFILL_TYPE_DATE = 4;
@@ -1198,26 +1210,41 @@
/**
* Automatically determine whether a view is important for autofill.
+ *
+ * @see #isImportantForAutofill()
+ * @see #setImportantForAutofill(int)
*/
public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
/**
* The view is important for autofill, and its children (if any) will be traversed.
+ *
+ * @see #isImportantForAutofill()
+ * @see #setImportantForAutofill(int)
*/
public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
/**
* The view is not important for autofill, but its children (if any) will be traversed.
+ *
+ * @see #isImportantForAutofill()
+ * @see #setImportantForAutofill(int)
*/
public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
/**
* The view is important for autofill, but its children (if any) will not be traversed.
+ *
+ * @see #isImportantForAutofill()
+ * @see #setImportantForAutofill(int)
*/
public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
/**
* The view is not important for autofill, and its children (if any) will not be traversed.
+ *
+ * @see #isImportantForAutofill()
+ * @see #setImportantForAutofill(int)
*/
public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
@@ -7366,23 +7393,70 @@
}
/**
- * Called when assist structure is being retrieved from a view as part of an autofill request.
+ * Populates a {@link ViewStructure} to fullfil an autofill request.
*
- * <p>This method already provides most of what's needed for autofill, but should be overridden
- * when:
+ * <p>The structure should contain at least the following properties:
* <ul>
- * <li>The view contents does not include PII (Personally Identifiable Information), so it
- * can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
- * <li>It must set fields such {@link ViewStructure#setText(CharSequence)},
- * {@link ViewStructure#setAutofillOptions(CharSequence[])},
- * or {@link ViewStructure#setWebDomain(String)}.
- * <li> The {@code left} and {@code top} values set in
- * {@link ViewStructure#setDimens(int, int, int, int, int, int)} need to be relative to the next
- * {@link ViewGroup#isImportantForAutofill() included} parent in the structure.
+ * <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
+ * <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
+ * <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
+ * <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
* </ul>
*
- * @param structure Fill in with structured view data. The default implementation
- * fills in all data that can be inferred from the view itself.
+ * <p>It's also recommended to set the following properties - the more properties the structure
+ * has, the higher the changes of an {@link android.service.autofill.AutofillService} properly
+ * using the structure:
+ *
+ * <ul>
+ * <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
+ * <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
+ * view can only be filled with predefined values (typically used when the autofill type
+ * is {@link #AUTOFILL_TYPE_LIST}).
+ * <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
+ * <li>Class name ({@link ViewStructure#setClassName(String)}).
+ * <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
+ * <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
+ * dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
+ * opacity ({@link ViewStructure#setOpaque(boolean)}).
+ * <li>For views representing text fields, text properties such as the text itself
+ * ({@link ViewStructure#setText(CharSequence)}), text hints
+ * ({@link ViewStructure#setHint(CharSequence)}, input type
+ * ({@link ViewStructure#setInputType(int)}),
+ * <li>For views representing HTML nodes, its web domain
+ * ({@link ViewStructure#setWebDomain(String)}) and HTML properties
+ * (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
+ * </ul>
+ *
+ * <p>The default implementation of this method already sets most of these properties based on
+ * related {@link View} methods (for example, the autofill id is set using
+ * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
+ * and views in the standard Android widgets library also override it to set their
+ * relevant properties (for example, {@link android.widget.TextView} already sets the text
+ * properties), so it's recommended to only override this method
+ * (and call {@code super.onProvideAutofillStructure()}) when:
+ *
+ * <ul>
+ * <li>The view contents does not include PII (Personally Identifiable Information), so it
+ * can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
+ * <li>The view can only be autofilled with predefined options, so it can call
+ * {@link ViewStructure#setAutofillOptions(CharSequence[])}.
+ * </ul>
+ *
+ * <p><b>NOTE:</b> the {@code left} and {@code top} values set in
+ * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
+ * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
+ *
+ * <p>Views support the Autofill Framework mainly by:
+ * <ul>
+ * <li>Providing the metadata defining what the view means and how it can be autofilled.
+ * <li>Notifying the Android System when the view value changed by calling
+ * {@link AutofillManager#notifyValueChanged(View)}.
+ * <li>Implementing the methods that autofill the view.
+ * </ul>
+ * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
+ * for the latter.
+ *
+ * @param structure fill in with structured view data for autofill purposes.
* @param flags optional flags.
*
* @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
@@ -7510,32 +7584,56 @@
}
/**
- * Called when assist structure is being retrieved from a view as part of an autofill request
- * to generate additional virtual structure under this view.
+ * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
+ * request.
+ *
+ * <p>This method should be used when the view manages a virtual structure under this view. For
+ * example, a view that draws input fields using {@link #draw(Canvas)}.
*
* <p>When implementing this method, subclasses must follow the rules below:
*
- * <ol>
- * <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
- * children.
- * <li>Call
- * {@link android.view.autofill.AutofillManager#notifyViewEntered} and
- * {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
- * when the focus inside the view changed.
- * <li>Call {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int,
- * AutofillValue)} when the value of a child changed.
- * <li>Call {@link AutofillManager#commit()} when the autofill context
- * of the view structure changed and you want the current autofill interaction if such
- * to be commited.
- * <li>Call {@link AutofillManager#cancel()} when the autofill context
- * of the view structure changed and you want the current autofill interaction if such
- * to be cancelled.
- * <li> The {@code left} and {@code top} values set in
- * {@link ViewStructure#setDimens(int, int, int, int, int, int)} need to be relative to the next
- * {@link ViewGroup#isImportantForAutofill() included} parent in the structure.
- * </ol>
+ * <ul>
+ * <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
+ * {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
+ * identifying the children in the virtual structure.
+ * <li>The children hierarchy can have multiple levels if necessary, but ideally it should
+ * exclude intermediate levels that are irrelevant for autofill; that would improve the
+ * autofill performance.
+ * <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
+ * children.
+ * <li>Set the autofill properties of the child structure as defined by
+ * {@link #onProvideAutofillStructure(ViewStructure, int)}, using
+ * {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
+ * <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
+ * and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
+ * when the focused virtual child changed.
+ * <li>Call
+ * {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
+ * when the value of a virtual child changed.
+ * <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
+ * changed and the current context should be committed (for example, when the user tapped
+ * a {@code SUBMIT} button in an HTML page).
+ * <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
+ * changed and the current context should be canceled (for example, when the user tapped
+ * a {@code CANCEL} button in an HTML page).
+ * <li>Provide ways for users to manually request autofill by calling
+ * {@link AutofillManager#requestAutofill(View, int, Rect)}.
+ * <li>The {@code left} and {@code top} values set in
+ * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
+ * next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
+ * structure.
+ * </ul>
*
- * @param structure Fill in with structured view data.
+ * <p>Views with virtual children support the Autofill Framework mainly by:
+ * <ul>
+ * <li>Providing the metadata defining what the virtual children mean and how they can be
+ * autofilled.
+ * <li>Implementing the methods that autofill the virtual children.
+ * </ul>
+ * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
+ * for the latter.
+ *
+ * @param structure fill in with virtual children data for autofill purposes.
* @param flags optional flags.
*
* @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
@@ -7546,15 +7644,21 @@
/**
* Automatically fills the content of this view with the {@code value}.
*
- * <p>By default does nothing, but views should override it (and {@link #getAutofillType()},
- * {@link #getAutofillValue()}, and {@link #onProvideAutofillStructure(ViewStructure, int)}
- * to support the Autofill Framework.
+ * <p>Views support the Autofill Framework mainly by:
+ * <ul>
+ * <li>Providing the metadata defining what the view means and how it can be autofilled.
+ * <li>Implementing the methods that autofill the view.
+ * </ul>
+ * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
+ * this method is responsible for latter.
*
- * <p>Typically, it is implemented by:
- *
+ * <p>This method does nothing by default, but when overridden it typically:
* <ol>
- * <li>Calling the proper getter method on {@link AutofillValue} to fetch the actual value.
- * <li>Passing the actual value to the equivalent setter in the view.
+ * <li>Checks if the provided value matches the expected type (which is defined by
+ * {@link #getAutofillType()}).
+ * <li>Checks if the view is editable - if it isn't, it should return right away.
+ * <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
+ * <li>Pass the actual value to the equivalent setter in the view.
* </ol>
*
* <p>For example, a text-field view could implement the method this way:
@@ -7573,7 +7677,7 @@
* </pre>
*
* <p>If the value is updated asynchronously the next call to
- * {@link AutofillManager#notifyValueChanged(View)} must happen <u>after</u> the value was
+ * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
* changed to the autofilled value. If not, the view will not be considered autofilled.
*
* @param value value to be autofilled.
@@ -7582,11 +7686,19 @@
}
/**
- * Automatically fills the content of a virtual views.
+ * Automatically fills the content of the virtual children within this view.
*
- * <p>See {@link #autofill(AutofillValue)} and
- * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info.
- * <p>To indicate that a virtual view was autofilled
+ * <p>Views with virtual children support the Autofill Framework mainly by:
+ * <ul>
+ * <li>Providing the metadata defining what the virtual children mean and how they can be
+ * autofilled.
+ * <li>Implementing the methods that autofill the virtual children.
+ * </ul>
+ * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
+ * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
+ * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
+ *
+ * <p><b>NOTE:</b> to indicate that a virtual view was autofilled,
* <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
* changes.
*
@@ -7598,9 +7710,9 @@
}
/**
- * Gets the unique identifier of this view on the screen for Autofill purposes.
+ * Gets the unique identifier of this view in the screen, for autofill purposes.
*
- * @return The View's Autofill id.
+ * @return The View's autofill id.
*/
public final AutofillId getAutofillId() {
if (mAutofillId == null) {
@@ -7612,11 +7724,18 @@
}
/**
- * Describes the autofill type that should be used on calls to
- * {@link #autofill(AutofillValue)} and {@link #autofill(SparseArray)}.
+ * Describes the autofill type of this view, so an
+ * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
+ * when autofilling the view.
*
- * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it (and
- * {@link #autofill(AutofillValue)} to support the Autofill Framework.
+ * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
+ * support the Autofill Framework.
+ *
+ * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
+ * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
+ *
+ * @see #onProvideAutofillStructure(ViewStructure, int)
+ * @see #autofill(AutofillValue)
*/
public @AutofillType int getAutofillType() {
return AUTOFILL_TYPE_NONE;
@@ -7648,9 +7767,11 @@
/**
* Gets the {@link View}'s current autofill value.
*
- * <p>By default returns {@code null}, but views should override it (and
- * {@link #autofill(AutofillValue)}, and {@link #getAutofillType()} to support the Autofill
- * Framework.
+ * <p>By default returns {@code null}, but views should override it to properly support the
+ * Autofill Framework.
+ *
+ * @see #onProvideAutofillStructure(ViewStructure, int)
+ * @see #autofill(AutofillValue)
*/
@Nullable
public AutofillValue getAutofillValue() {
@@ -7658,9 +7779,10 @@
}
/**
- * Gets the mode for determining whether this View is important for autofill.
+ * Gets the mode for determining whether this view is important for autofill.
*
- * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
+ * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
+ * info about this mode.
*
* @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
* {@link #setImportantForAutofill(int)}.
@@ -7681,20 +7803,29 @@
}
/**
- * Sets the mode for determining whether this View is important for autofill.
- *
- * <p>This property controls how this view is presented to the autofill components
- * which help users to fill credentials, addresses, etc. For example, views
- * that contain labels and input fields are useful for autofill components to
- * determine the user context and provide values for the inputs. Note that the
- * user can always override this by manually triggering autotill which would
- * expose the view to the autofill provider.
+ * Sets the mode for determining whether this view is considered important for autofill.
*
* <p>The platform determines the importance for autofill automatically but you
- * can use this method to customize the behavior. See the autofill modes below
- * for more details.
+ * can use this method to customize the behavior. For example:
*
- * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
+ * <ol>
+ * <li>When the view contents is irrelevant for autofill (for example, a text field used in a
+ * "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
+ * <li>When both the view and its children are irrelevant for autofill (for example, the root
+ * view of an activity containing a spreadhseet editor), it should be
+ * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
+ * <li>When the view content is relevant for autofill but its children aren't (for example,
+ * a credit card expiration date represented by a custom view that overrides the proper
+ * autofill methods and has 2 children representing the month and year), it should
+ * be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
+ * </ol>
+ *
+ * <p><b>NOTE:</strong> setting the mode as does {@link #IMPORTANT_FOR_AUTOFILL_NO} or
+ * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
+ * children) will be always be considered not important; for example, when the user explicitly
+ * makes an autofill request, all views are considered important. See
+ * {@link #isImportantForAutofill()} for more details about how the View's importance for
+ * autofill is used.
*
* @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
* {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
@@ -7710,40 +7841,51 @@
/**
* Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
- * associated with this View should be included in a {@link ViewStructure} used for
- * autofill purposes.
+ * associated with this view is considered important for autofill purposes.
*
* <p>Generally speaking, a view is important for autofill if:
* <ol>
- * <li>The view can-be autofilled by an {@link android.service.autofill.AutofillService}.
- * <li>The view contents can help an {@link android.service.autofill.AutofillService} to
- * autofill other views.
+ * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
+ * <li>The view contents can help an {@link android.service.autofill.AutofillService}
+ * determine how other views can be autofilled.
* <ol>
*
* <p>For example, view containers should typically return {@code false} for performance reasons
- * (since the important info is provided by their children), but if the container is actually
- * whose children are part of a compound view, it should return {@code true} (and then override
- * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
- * {@link #onProvideAutofillStructure(ViewStructure, int)} so its children are not included in
- * the structure). On the other hand, views representing labels or editable fields should
- * typically return {@code true}, but in some cases they could return {@code false} (for
- * example, if they're part of a "Captcha" mechanism).
+ * (since the important info is provided by their children), but if its properties have relevant
+ * information (for example, a resource id called {@code credentials}, it should return
+ * {@code true}. On the other hand, views representing labels or editable fields should
+ * typically return {@code true}, but in some cases they could return {@code false}
+ * (for example, if they're part of a "Captcha" mechanism).
*
- * <p>By default, this method returns {@code true} if {@link #getImportantForAutofill()} returns
- * {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@code false } if it returns
- * {@link #IMPORTANT_FOR_AUTOFILL_NO}, and use some heuristics to define the importance when it
- * returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}. Hence, it should rarely be overridden - Views
- * should use {@link #setImportantForAutofill(int)} instead.
+ * <p>The value returned by this method depends on the value returned by
+ * {@link #getImportantForAutofill()}:
*
- * <p><strong>Note:</strong> returning {@code false} does not guarantee the view will be
- * excluded from the structure; for example, if the user explicitly requested autofill, the
- * View might be always included.
+ * <ol>
+ * <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
+ * {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
+ * <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
+ * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
+ * <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
+ * that can return {@code true} in some cases (like a container with a resource id),
+ * but {@code false} in most.
+ * <li>otherwise, it returns {@code false}.
+ * </ol>
*
- * <p>This decision applies just for the view, not its children - if the view children are not
- * important for autofill, the view should override
- * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
- * {@link #onProvideAutofillStructure(ViewStructure, int)} (instead of calling
- * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} for each child).
+ * <p>When a view is considered important for autofill:
+ * <ul>
+ * <li>The view might automatically trigger an autofill request when focused on.
+ * <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
+ * request.
+ * </ul>
+ *
+ * <p>On the other hand, when a view is considered not important for autofill:
+ * <ul>
+ * <li>The view never automatically triggers autofill requests, but it can trigger a manual
+ * request through {@link AutofillManager#requestAutofill(View)}.
+ * <li>The contents of the view are not included in the {@link ViewStructure} used in an
+ * autofill request, unless the request has the
+ * {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
+ * </ul>
*
* @return whether the view is considered important for autofill.
*
@@ -7753,6 +7895,7 @@
* @see #IMPORTANT_FOR_AUTOFILL_NO
* @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
* @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
+ * @see AutofillManager#requestAutofill(View)
*/
public final boolean isImportantForAutofill() {
// Check parent mode to ensure we're not hidden.
@@ -7877,29 +8020,38 @@
}
/**
- * Dispatch creation of {@link ViewStructure} down the hierarchy.
+ * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
+ * when an Assist structure is being created as part of an autofill request.
*
* <p>The default implementation does the following:
- *
* <ul>
* <li>Sets the {@link AutofillId} in the structure.
* <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
* <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
* </ul>
*
- * <p>When overridden, it must either call
- * {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
- * set the {@link AutofillId} in the structure (for example, by calling
- * {@code structure.setAutofillId(getAutofillId())}).
+ * <p>Typically, this method should only be overridden by subclasses that provide a view
+ * hierarchy (such as {@link ViewGroup}) - other classes should override
+ * {@link #onProvideAutofillStructure(ViewStructure, int)} or
+ * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
*
- * <p>When providing your implementation you need to decide how to handle
- * the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag which instructs you
- * to report all views to the structure regardless if {@link #isImportantForAutofill()}
- * returns true. We encourage you respect the importance property for a better
- * user experience in your app. If the flag is not set then you should filter out
- * not important views to optimize autofill performance in your app.
+ * <p>When overridden, it must:
*
- * @param structure Fill in with structured view data.
+ * <ul>
+ * <li>Either call
+ * {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
+ * set the {@link AutofillId} in the structure (for example, by calling
+ * {@code structure.setAutofillId(getAutofillId())}).
+ * <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
+ * set, all views in the structure should be considered important for autofill,
+ * regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
+ * respect this flag to provide a better user experience - this flag is typically used
+ * when an user explicitly requested autofill. If the flag is not set,
+ * then only views marked as important for autofill should be included in the
+ * structure - skipping non-important views optimizes the overall autofill performance.
+ * </ul>
+ *
+ * @param structure fill in with structured view data for autofill purposes.
* @param flags optional flags.
*
* @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
@@ -10028,12 +10180,20 @@
// Going from one cluster to another, so save last-focused.
// This covers cluster jumps because they are always FOCUS_DOWN
oldFocus.setFocusedInCluster(oldCluster);
+ if (!(oldFocus.mParent instanceof ViewGroup)) {
+ return;
+ }
if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
// This is a result of ordered navigation so consider navigation through
// the previous cluster "complete" and clear its last-focused memory.
- if (oldFocus.mParent instanceof ViewGroup) {
- ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
- }
+ ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
+ } else if (oldFocus instanceof ViewGroup
+ && ((ViewGroup) oldFocus).getDescendantFocusability()
+ == ViewGroup.FOCUS_AFTER_DESCENDANTS
+ && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
+ // This means oldFocus is not focusable since it obviously has a focusable
+ // child (this). Don't restore focus to it in the future.
+ ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
}
}
}
@@ -13080,7 +13240,7 @@
// about in case nothing has focus. even if this specific view
// isn't focusable, it may contain something that is, so let
// the root view try to give this focus if nothing else does.
- if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
+ if ((mParent != null)) {
mParent.focusableViewAvailable(this);
}
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 09464eec4..4b79b8c 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -833,8 +833,9 @@
public void focusableViewAvailable(View v) {
if (mParent != null
// shortcut: don't report a new focusable view if we block our descendants from
- // getting focus
+ // getting focus or if we're not visible
&& (getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS)
+ && ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
&& (isFocusableInTouchMode() || !shouldBlockFocusForTouchscreen())
// shortcut: don't report a new focusable view if we already are focused
// (and we don't prefer our descendants)
@@ -1159,18 +1160,25 @@
// Determine whether we have a focused descendant.
final int descendantFocusability = getDescendantFocusability();
if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
- final int count = mChildrenCount;
- final View[] children = mChildren;
+ return hasFocusableChild(dispatchExplicit);
+ }
- for (int i = 0; i < count; i++) {
- final View child = children[i];
+ return false;
+ }
- // In case the subclass has overridden has[Explicit]Focusable, dispatch
- // to the expected one for each child even though we share logic here.
- if ((dispatchExplicit && child.hasExplicitFocusable())
- || (!dispatchExplicit && child.hasFocusable())) {
- return true;
- }
+ boolean hasFocusableChild(boolean dispatchExplicit) {
+ // Determine whether we have a focusable descendant.
+ final int count = mChildrenCount;
+ final View[] children = mChildren;
+
+ for (int i = 0; i < count; i++) {
+ final View child = children[i];
+
+ // In case the subclass has overridden has[Explicit]Focusable, dispatch
+ // to the expected one for each child even though we share logic here.
+ if ((dispatchExplicit && child.hasExplicitFocusable())
+ || (!dispatchExplicit && child.hasFocusable())) {
+ return true;
}
}
@@ -3230,7 +3238,7 @@
// will refer to a view not-in a cluster.
return restoreFocusInCluster(View.FOCUS_DOWN);
}
- if (isKeyboardNavigationCluster()) {
+ if (isKeyboardNavigationCluster() || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
return false;
}
int descendentFocusability = getDescendantFocusability();
@@ -3248,7 +3256,7 @@
return true;
}
}
- if (descendentFocusability == FOCUS_AFTER_DESCENDANTS) {
+ if (descendentFocusability == FOCUS_AFTER_DESCENDANTS && !hasFocusableChild(false)) {
return super.requestFocus(FOCUS_DOWN, null);
}
return false;
@@ -4914,7 +4922,8 @@
child.mParent = this;
}
- if (child.hasFocus()) {
+ final boolean childHasFocus = child.hasFocus();
+ if (childHasFocus) {
requestChildFocus(child, child.findFocus());
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a720aae..2605b4a 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -40,6 +40,7 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Point;
@@ -2651,6 +2652,15 @@
@Override
public void onPreDraw(DisplayListCanvas canvas) {
+ // If mCurScrollY is not 0 then this influences the hardwareYOffset. The end result is we
+ // can apply offsets that are not handled by anything else, resulting in underdraw as
+ // the View is shifted (thus shifting the window background) exposing unpainted
+ // content. To handle this with minimal glitches we just clear to BLACK if the window
+ // is opaque. If it's not opaque then HWUI already internally does a glClear to
+ // transparent, so there's no risk of underdraw on non-opaque surfaces.
+ if (mCurScrollY != 0 && mHardwareYOffset != 0 && mAttachInfo.mThreadedRenderer.isOpaque()) {
+ canvas.drawColor(Color.BLACK);
+ }
canvas.translate(-mHardwareXOffset, -mHardwareYOffset);
}
@@ -2668,7 +2678,7 @@
void outputDisplayList(View view) {
view.mRenderNode.output();
if (mAttachInfo.mThreadedRenderer != null) {
- ((ThreadedRenderer)mAttachInfo.mThreadedRenderer).serializeDisplayListTree();
+ mAttachInfo.mThreadedRenderer.serializeDisplayListTree();
}
}
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index ddfe697..0ecd20d 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -269,6 +269,9 @@
* Create a new child {@link ViewStructure} in this view, putting into the list of
* children at <var>index</var>.
*
+ * <p><b>NOTE: </b>you must pre-allocate space for the child first, by calling either
+ * {@link #addChildCount(int)} or {@link #setChildCount(int)}.
+ *
* @return Returns an fresh {@link ViewStructure} ready to be filled in.
*/
public abstract ViewStructure newChild(int index);
@@ -279,6 +282,10 @@
* to build its content (and children etc). Once done, some thread must call
* {@link #asyncCommit} to tell the containing {@link ViewStructure} that the async
* population is done.
+ *
+ * <p><b>NOTE: </b>you must pre-allocate space for the child first, by calling either
+ * {@link #addChildCount(int)} or {@link #setChildCount(int)}.
+ *
* @return Returns an fresh {@link ViewStructure} ready to be filled in.
*/
public abstract ViewStructure asyncNewChild(int index);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 6dd8ecf..0d5c075 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -624,6 +624,9 @@
/** Returns the current stack Id for the window. */
int getWindowStackId() throws RemoteException;
+
+ /** Returns whether the window belongs to the task root. */
+ boolean isTaskRoot();
}
/**
@@ -2271,6 +2274,12 @@
public abstract void onMultiWindowModeChanged();
/**
+ * Called when the activity changes to/from picture-in-picture mode.
+ * @hide
+ */
+ public abstract void onPictureInPictureModeChanged(boolean isInPictureInPictureMode);
+
+ /**
* Called when the activity just relaunched.
* @hide
*/
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 3f91476..4060b9a 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.annotation.TestApi;
import android.app.KeyguardManager;
import android.app.Presentation;
@@ -39,8 +40,6 @@
/**
* The interface that apps use to talk to the window manager.
- * <p>
- * Use <code>Context.getSystemService(Context.WINDOW_SERVICE)</code> to get one of these.
* </p><p>
* Each window manager instance is bound to a particular {@link Display}.
* To obtain a {@link WindowManager} for a different display, use
@@ -52,10 +51,8 @@
* {@link Presentation}. The presentation will automatically obtain a
* {@link WindowManager} and {@link Context} for that display.
* </p>
- *
- * @see android.content.Context#getSystemService
- * @see android.content.Context#WINDOW_SERVICE
*/
+@SystemService(Context.WINDOW_SERVICE)
public interface WindowManager extends ViewManager {
/** @hide */
@@ -1903,6 +1900,7 @@
*
* @hide
*/
+ @TestApi
public CharSequence accessibilityTitle;
/**
@@ -2185,6 +2183,7 @@
/** {@hide} */
public static final int ACCESSIBILITY_ANCHOR_CHANGED = 1 << 24;
/** {@hide} */
+ @TestApi
public static final int ACCESSIBILITY_TITLE_CHANGED = 1 << 25;
/** {@hide} */
public static final int EVERYTHING_CHANGED = 0xffffffff;
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 7eb7bd9..41a8b8a 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -24,6 +24,7 @@
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -59,15 +60,6 @@
* {@link android.view.View} changes etc. Parties interested in handling accessibility
* events implement and register an accessibility service which extends
* {@link android.accessibilityservice.AccessibilityService}.
- * <p>
- * To obtain a handle to the accessibility manager do the following:
- * </p>
- * <p>
- * <code>
- * <pre>AccessibilityManager accessibilityManager =
- * (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);</pre>
- * </code>
- * </p>
*
* @see AccessibilityEvent
* @see AccessibilityNodeInfo
@@ -75,6 +67,7 @@
* @see Context#getSystemService
* @see Context#ACCESSIBILITY_SERVICE
*/
+@SystemService(Context.ACCESSIBILITY_SERVICE)
public final class AccessibilityManager {
private static final boolean DEBUG = false;
diff --git a/core/java/android/view/accessibility/CaptioningManager.java b/core/java/android/view/accessibility/CaptioningManager.java
index 14f0b0a..d6455e7 100644
--- a/core/java/android/view/accessibility/CaptioningManager.java
+++ b/core/java/android/view/accessibility/CaptioningManager.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemService;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
@@ -34,14 +35,8 @@
/**
* Contains methods for accessing and monitoring preferred video captioning state and visual
* properties.
- * <p>
- * To obtain a handle to the captioning manager, do the following:
- * <p>
- * <code>
- * <pre>CaptioningManager captioningManager =
- * (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE);</pre>
- * </code>
*/
+@SystemService(Context.CAPTIONING_SERVICE)
public class CaptioningManager {
/** Default captioning enabled value. */
private static final int DEFAULT_ENABLED = 0;
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 02ecc50..310ec1c 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -23,6 +23,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemService;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
@@ -55,6 +56,7 @@
*
* <p>It is safe to call into this from any thread.
*/
+@SystemService(Context.AUTOFILL_MANAGER_SERVICE)
public final class AutofillManager {
private static final String TAG = "AutofillManager";
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index da9316c..e2f7979 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
import android.content.Context;
import android.graphics.Rect;
import android.net.Uri;
@@ -73,8 +74,6 @@
/**
* Central system API to the overall input method framework (IMF) architecture,
* which arbitrates interaction between applications and the current input method.
- * You can retrieve an instance of this interface with
- * {@link Context#getSystemService(String) Context.getSystemService()}.
*
* <p>Topics covered here:
* <ol>
@@ -211,6 +210,7 @@
* and want to make it available for use.</p>
* </ul>
*/
+@SystemService(Context.INPUT_METHOD_SERVICE)
public final class InputMethodManager {
static final boolean DEBUG = false;
static final String TAG = "InputMethodManager";
diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java
index 6b641db..efc88e2 100644
--- a/core/java/android/view/textclassifier/TextClassificationManager.java
+++ b/core/java/android/view/textclassifier/TextClassificationManager.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemService;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import android.util.Log;
@@ -33,10 +34,8 @@
/**
* Interface to the text classification service.
- *
- * <p>You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService}.
*/
+@SystemService(Context.TEXT_CLASSIFICATION_SERVICE)
public final class TextClassificationManager {
private static final String LOG_TAG = "TextClassificationManager";
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index b4e6c56..d9bfade 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -16,6 +16,7 @@
package android.view.textservice;
+import android.annotation.SystemService;
import android.content.Context;
import android.os.Bundle;
import android.os.RemoteException;
@@ -30,8 +31,7 @@
/**
* System API to the overall text services, which arbitrates interaction between applications
- * and text services. You can retrieve an instance of this interface with
- * {@link Context#getSystemService(String) Context.getSystemService()}.
+ * and text services.
*
* The user can change the current text services in Settings. And also applications can specify
* the target text services.
@@ -61,6 +61,7 @@
* </ul>
*
*/
+@SystemService(Context.TEXT_SERVICES_MANAGER_SERVICE)
public final class TextServicesManager {
private static final String TAG = TextServicesManager.class.getSimpleName();
private static final boolean DBG = false;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 1fef7cb..c19ee56 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3842,11 +3842,12 @@
}
if (mTextView.canRequestAutofill()) {
- final int mode = mTextView.getText().length() <= 0
- ? MenuItem.SHOW_AS_ACTION_IF_ROOM : MenuItem.SHOW_AS_ACTION_NEVER;
- menu.add(Menu.NONE, TextView.ID_AUTOFILL, MENU_ITEM_ORDER_AUTOFILL,
- com.android.internal.R.string.autofill)
- .setShowAsAction(mode);
+ final String selected = mTextView.getSelectedText();
+ if (selected == null || selected.isEmpty()) {
+ menu.add(Menu.NONE, TextView.ID_AUTOFILL, MENU_ITEM_ORDER_AUTOFILL,
+ com.android.internal.R.string.autofill)
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ }
}
if (mTextView.canPasteAsPlainText()) {
diff --git a/core/java/com/android/internal/app/NightDisplayController.java b/core/java/com/android/internal/app/NightDisplayController.java
index d19f1ec..bb54085 100644
--- a/core/java/com/android/internal/app/NightDisplayController.java
+++ b/core/java/com/android/internal/app/NightDisplayController.java
@@ -109,17 +109,39 @@
}
/**
- * Sets whether Night display should be activated.
+ * Sets whether Night display should be activated. This also sets the last activated time.
*
* @param activated {@code true} if Night display should be activated
* @return {@code true} if the activated value was set successfully
*/
public boolean setActivated(boolean activated) {
+ if (isActivated() != activated) {
+ Secure.putLongForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, System.currentTimeMillis(),
+ mUserId);
+ }
return Secure.putIntForUser(mContext.getContentResolver(),
Secure.NIGHT_DISPLAY_ACTIVATED, activated ? 1 : 0, mUserId);
}
/**
+ * Returns the time when Night display's activation state last changed, or {@code null} if it
+ * has never been changed.
+ */
+ public Calendar getLastActivatedTime() {
+ final ContentResolver cr = mContext.getContentResolver();
+ final long lastActivatedTimeMillis = Secure.getLongForUser(
+ cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1, mUserId);
+ if (lastActivatedTimeMillis < 0) {
+ return null;
+ }
+
+ final Calendar lastActivatedTime = Calendar.getInstance();
+ lastActivatedTime.setTimeInMillis(lastActivatedTimeMillis);
+ return lastActivatedTime;
+ }
+
+ /**
* Returns the current auto mode value controlling when Night display will be automatically
* activated. One of {@link #AUTO_MODE_DISABLED}, {@link #AUTO_MODE_CUSTOM}, or
* {@link #AUTO_MODE_TWILIGHT}.
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index 797cf2b..d327180 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -135,7 +135,7 @@
channelsList.add(new NotificationChannel(
FOREGROUND_SERVICE,
context.getString(R.string.notification_channel_foreground_service),
- NotificationManager.IMPORTANCE_MIN));
+ NotificationManager.IMPORTANCE_LOW));
nm.createNotificationChannels(channelsList);
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 1b0d332..235ebc8 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -3518,6 +3518,7 @@
public void removeIsolatedUidLocked(int isolatedUid) {
mIsolatedUids.delete(isolatedUid);
mKernelUidCpuTimeReader.removeUid(isolatedUid);
+ mKernelUidCpuFreqTimeReader.removeUid(isolatedUid);
}
public int mapUid(int uid) {
@@ -10175,7 +10176,16 @@
new KernelUidCpuTimeReader.Callback() {
@Override
public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) {
- final Uid u = getUidStatsLocked(mapUid(uid));
+ uid = mapUid(uid);
+ if (Process.isIsolated(uid)) {
+ // This could happen if the isolated uid mapping was removed before
+ // that process was actually killed.
+ mKernelUidCpuTimeReader.removeUid(uid);
+ Slog.d(TAG, "Got readings for an isolated uid with"
+ + " no mapping to owning uid: " + uid);
+ return;
+ }
+ final Uid u = getUidStatsLocked(uid);
// Accumulate the total system and user time.
mTempTotalCpuUserTimeUs += userTimeUs;
@@ -10340,7 +10350,14 @@
@Override
public void onUidCpuFreqTime(int uid, long[] cpuFreqTimeMs) {
- final Uid u = getUidStatsLocked(mapUid(uid));
+ uid = mapUid(uid);
+ if (Process.isIsolated(uid)) {
+ mKernelUidCpuFreqTimeReader.removeUid(uid);
+ Slog.d(TAG, "Got freq readings for an isolated uid with"
+ + " no mapping to owning uid: " + uid);
+ return;
+ }
+ final Uid u = getUidStatsLocked(uid);
if (u.mCpuFreqTimeMs == null) {
u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
}
@@ -11006,6 +11023,7 @@
*/
public void removeUidStatsLocked(int uid) {
mKernelUidCpuTimeReader.removeUid(uid);
+ mKernelUidCpuFreqTimeReader.removeUid(uid);
mUidStats.remove(uid);
}
diff --git a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
index 568c883..ff521c2 100644
--- a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
@@ -53,14 +53,29 @@
private SparseArray<long[]> mLastUidCpuFreqTimeMs = new SparseArray<>();
+ // We check the existence of proc file a few times (just in case it is not ready yet when we
+ // start reading) and if it is not available, we simply ignore further read requests.
+ private static final int TOTAL_READ_ERROR_COUNT = 5;
+ private int mReadErrorCounter;
+ private boolean mProcFileAvailable;
+
public void readDelta(@Nullable Callback callback) {
+ if (!mProcFileAvailable && mReadErrorCounter >= TOTAL_READ_ERROR_COUNT) {
+ return;
+ }
try (BufferedReader reader = new BufferedReader(new FileReader(UID_TIMES_PROC_FILE))) {
readDelta(reader, callback);
+ mProcFileAvailable = true;
} catch (IOException e) {
+ mReadErrorCounter++;
Slog.e(TAG, "Failed to read " + UID_TIMES_PROC_FILE + ": " + e);
}
}
+ public void removeUid(int uid) {
+ mLastUidCpuFreqTimeMs.delete(uid);
+ }
+
@VisibleForTesting
public void readDelta(BufferedReader reader, @Nullable Callback callback) throws IOException {
String line = reader.readLine();
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index ba3aa36..60fbbe9 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -16,6 +16,8 @@
package com.android.internal.policy;
+import android.graphics.Outline;
+import android.view.ViewOutlineProvider;
import android.view.accessibility.AccessibilityNodeInfo;
import com.android.internal.R;
import com.android.internal.policy.PhoneWindow.PanelFeatureState;
@@ -135,6 +137,16 @@
com.android.internal.R.id.navigationBarBackground,
0 /* hideWindowFlag */);
+ // This is used to workaround an issue where the PiP shadow can be transparent if the window
+ // background is transparent
+ private static final ViewOutlineProvider PIP_OUTLINE_PROVIDER = new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRect(0, 0, view.getWidth(), view.getHeight());
+ outline.setAlpha(1f);
+ }
+ };
+
// Cludge to address b/22668382: Set the shadow size to the maximum so that the layer
// size calculation takes the shadow size into account. We set the elevation currently
// to max until the first layout command has been executed.
@@ -142,6 +154,12 @@
private boolean mElevationAdjustedForStack = false;
+ // Keeps track of the picture-in-picture mode for the view shadow
+ private boolean mIsInPictureInPictureMode;
+
+ // Stores the previous outline provider prior to applying PIP_OUTLINE_PROVIDER
+ private ViewOutlineProvider mLastOutlineProvider;
+
int mDefaultOpacity = PixelFormat.OPAQUE;
/** The feature ID of the panel, or -1 if this is the application's DecorView */
@@ -1404,6 +1422,41 @@
}
}
+ /**
+ * Overrides the view outline when the activity enters picture-in-picture to ensure that it has
+ * an opaque shadow even if the window background is completely transparent. This only applies
+ * to activities that are currently the task root.
+ */
+ public void updatePictureInPictureOutlineProvider(boolean isInPictureInPictureMode) {
+ if (mIsInPictureInPictureMode == isInPictureInPictureMode) {
+ return;
+ }
+
+ if (isInPictureInPictureMode) {
+ final Window.WindowControllerCallback callback =
+ mWindow.getWindowControllerCallback();
+ if (callback != null && callback.isTaskRoot()) {
+ // Call super implementation directly as we don't want to save the PIP outline
+ // provider to be restored
+ super.setOutlineProvider(PIP_OUTLINE_PROVIDER);
+ }
+ } else {
+ // Restore the previous outline provider
+ if (getOutlineProvider() != mLastOutlineProvider) {
+ setOutlineProvider(mLastOutlineProvider);
+ }
+ }
+ mIsInPictureInPictureMode = isInPictureInPictureMode;
+ }
+
+ @Override
+ public void setOutlineProvider(ViewOutlineProvider provider) {
+ super.setOutlineProvider(provider);
+
+ // Save the outline provider set to ensure that we can restore when the activity leaves PiP
+ mLastOutlineProvider = provider;
+ }
+
private void drawableChanged() {
if (mChanging) {
return;
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index a019ea1..3f35c91 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -93,4 +93,10 @@
* @param fadeoutDuration the duration of the exit animation, in milliseconds
*/
void startKeyguardExitAnimation(long startTime, long fadeoutDuration);
+
+ /**
+ * Notifies the Keyguard that the power key was pressed while locked and launched Home rather
+ * than putting the device to sleep or waking up.
+ */
+ void onShortPowerPressedGoHome();
}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 243916b..8fe9100 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -729,6 +729,13 @@
}
@Override
+ public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
+ if (mDecor != null) {
+ mDecor.updatePictureInPictureOutlineProvider(isInPictureInPictureMode);
+ }
+ }
+
+ @Override
public void reportActivityRelaunched() {
if (mDecor != null && mDecor.getViewRootImpl() != null) {
mDecor.getViewRootImpl().reportActivityRelaunched();
diff --git a/core/java/com/android/internal/view/TooltipPopup.java b/core/java/com/android/internal/view/TooltipPopup.java
index ebbbdbb..d834e63 100644
--- a/core/java/com/android/internal/view/TooltipPopup.java
+++ b/core/java/com/android/internal/view/TooltipPopup.java
@@ -25,6 +25,7 @@
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.widget.PopupWindow;
import android.widget.TextView;
public class TooltipPopup {
@@ -32,6 +33,7 @@
private final Context mContext;
+ private final PopupWindow mPopupWindow;
private final View mContentView;
private final TextView mMessageView;
@@ -43,6 +45,8 @@
public TooltipPopup(Context context) {
mContext = context;
+ mPopupWindow = new PopupWindow(context);
+ mPopupWindow.setBackgroundDrawable(null);
mContentView = LayoutInflater.from(mContext).inflate(
com.android.internal.R.layout.tooltip, null);
mMessageView = (TextView) mContentView.findViewById(
@@ -70,17 +74,16 @@
computePosition(anchorView, anchorX, anchorY, fromTouch, mLayoutParams);
- WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
- wm.addView(mContentView, mLayoutParams);
+ mPopupWindow.setContentView(mContentView);
+ mPopupWindow.showAtLocation(
+ anchorView, mLayoutParams.gravity, mLayoutParams.x, mLayoutParams.y);
}
public void hide() {
if (!isShowing()) {
return;
}
-
- WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
- wm.removeView(mContentView);
+ mPopupWindow.dismiss();
}
public View getContentView() {
@@ -88,7 +91,7 @@
}
public boolean isShowing() {
- return mContentView.getParent() != null;
+ return mPopupWindow.isShowing();
}
public void updateContent(CharSequence tooltipText) {
diff --git a/core/res/res/drawable/stat_sys_vitals.xml b/core/res/res/drawable/stat_sys_vitals.xml
new file mode 100644
index 0000000..213dd5f
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_vitals.xml
@@ -0,0 +1,29 @@
+<!--
+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.
+-->
+<!-- "system vitals", as represented by an EKG trace -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M19.5608645,12.0797103 L17.15,5.15 L15.25,5.15 L11.95,15.95 L9.75,11.5 L7.95,11.55 L7.2,13.3
+ L6.65,14.6 L3.25,14.6 L3.25,16.6 L7.35,16.6 L8,16.6 L8.25,16 L8.9,14.3 L11.2,18.85 L13.15,18.85 L16.25,8.8
+ L17.5310733,12.642689 C17.2014325,12.9992627 17,13.4761078 17,14 C17,15.1045695 17.8954305,16 19,16
+ C20.1045695,16 21,15.1045695 21,14 C21,13.0901368 20.3924276,12.3221796 19.5608645,12.0797103 Z M21,3
+ C22,3 23,4 23,5 L23,19 C23,20 22,21 21,21 L3,21 C1.9,21 1,20.1 1,19 L1,5 C1,4 2,3 3,3 L21,3 Z" />
+</vector>
diff --git a/core/res/res/drawable/sym_def_app_icon.xml b/core/res/res/drawable/sym_def_app_icon.xml
index 9c02402..129d38a 100644
--- a/core/res/res/drawable/sym_def_app_icon.xml
+++ b/core/res/res/drawable/sym_def_app_icon.xml
@@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
- <background android:drawable="@android:color/white" />
+ <background android:drawable="@drawable/sym_def_app_icon_background" />
<foreground>
- <inset android:inset="27.7%">
- <bitmap android:src="@mipmap/sym_def_app_icon"/>
- </inset>
+ <bitmap android:src="@mipmap/sym_def_app_icon_foreground"/>
</foreground>
</adaptive-icon>
diff --git a/core/res/res/drawable/sym_def_app_icon_background.xml b/core/res/res/drawable/sym_def_app_icon_background.xml
new file mode 100644
index 0000000..5755210
--- /dev/null
+++ b/core/res/res/drawable/sym_def_app_icon_background.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector
+ android:height="108dp"
+ android:width="108dp"
+ android:viewportHeight="108.0"
+ android:viewportWidth="108.0"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/material_deep_teal_500"
+ android:pathData="M0,0h108v108h-108z"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,0L19,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M9,0L9,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M39,0L39,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M29,0L29,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M59,0L59,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M49,0L49,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M79,0L79,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M69,0L69,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M89,0L89,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M99,0L99,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,89L108,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,99L108,99"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,69L108,69"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,79L108,79"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,49L108,49"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,59L108,59"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,29L108,29"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,39L108,39"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,19L108,19"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,9L108,9"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+</vector>
+
diff --git a/core/res/res/mipmap-hdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-hdpi/sym_def_app_icon_foreground.png
new file mode 100644
index 0000000..4e526c9
--- /dev/null
+++ b/core/res/res/mipmap-hdpi/sym_def_app_icon_foreground.png
Binary files differ
diff --git a/core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png
deleted file mode 100644
index bf58413..0000000
--- a/core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/mipmap-mdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-mdpi/sym_def_app_icon_foreground.png
new file mode 100644
index 0000000..2c38c71
--- /dev/null
+++ b/core/res/res/mipmap-mdpi/sym_def_app_icon_foreground.png
Binary files differ
diff --git a/core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png
deleted file mode 100644
index 47f6f81..0000000
--- a/core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/mipmap-xhdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-xhdpi/sym_def_app_icon_foreground.png
new file mode 100644
index 0000000..072467e
--- /dev/null
+++ b/core/res/res/mipmap-xhdpi/sym_def_app_icon_foreground.png
Binary files differ
diff --git a/core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png
deleted file mode 100644
index f60b896..0000000
--- a/core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/mipmap-xxhdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-xxhdpi/sym_def_app_icon_foreground.png
new file mode 100644
index 0000000..78a6b7a
--- /dev/null
+++ b/core/res/res/mipmap-xxhdpi/sym_def_app_icon_foreground.png
Binary files differ
diff --git a/core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png
deleted file mode 100644
index 6d4f315..0000000
--- a/core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_foreground.png
new file mode 100644
index 0000000..68ebe33
--- /dev/null
+++ b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_foreground.png
Binary files differ
diff --git a/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png
deleted file mode 100644
index 08e54d0..0000000
--- a/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index d78a980..f77980a 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tik om taal en uitleg te kies"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> word bo-oor ander programme gewys"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> wys bo-oor ander programme"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"As jy nie wil hê dat <xliff:g id="NAME">%s</xliff:g> hierdie kenmerk gebruik nie, tik om instellings oop te maak en skakel dit af."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 475167e..bbcc81d 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ቋንቋ እና አቀማመጥን ለመምረጥ መታ ያድርጉ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> በሌሎች መተግበሪያዎች ላይ እያሳየ ነው"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> በሌሎች መተግበሪያዎች ላይ እያሳየ ነው"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ይህን ባህሪ እንዲጠቀም ካልፈለጉ ቅንብሮችን ለመክፈት መታ ያድርጉና ያጥፉት።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 7e5a081..ae35122 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1292,6 +1292,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"انقر لاختيار لغة وتنسيق"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789 أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"جارٍ عرض <xliff:g id="NAME">%s</xliff:g> فوق تطبيقات أخرى"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"يتم عرض <xliff:g id="NAME">%s</xliff:g> فوق التطبيقات الأخرى."</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"إذا كنت لا تريد أن يستخدم <xliff:g id="NAME">%s</xliff:g> هذه الميزة، فانقر لفتح الإعدادات، ثم اختر تعطيلها."</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index f9c699c..b70ad39 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dil və tərtibatı seçmək üçün tıklayın"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCÇDEƏFGĞHXIİJKQLMNOÖPRSŞTUÜVYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCÇDEƏFGĞHİIJKLMNOÖPQRSŞTUÜVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> digər tətbiqlər üzərindən göstərilir"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> tətbiq üzərindən göstərilir"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> adlı şəxsin bu funksiyadan istifadə etməyini istəmirsinizsə, ayarları açmaq və deaktiv etmək üçün klikləyin."</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index b7bdb69..06dc7e7 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1226,6 +1226,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite da biste izabrali jezik i raspored"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Aplikacija <xliff:g id="NAME">%s</xliff:g> se prikazuje preko drugih aplikacija"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> se prikazuje preko drugih aplik."</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Ako ne želite ovu funkciju za <xliff:g id="NAME">%s</xliff:g>, dodirnite da biste otvorili podešavanja i isključili je."</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 6515803..fbeb50c 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1248,6 +1248,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Дакраніцеся, каб выбраць мову і раскладку"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГДЕЁЖЗІЙКЛМНОПРСТУЎФХЦЧШ\'ЫЬЭЮЯ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> паказваецца паверх іншых праграм"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> паказв. паверх іншых праграм"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Калі вы не хочаце, каб праграма <xliff:g id="NAME">%s</xliff:g> выкарыстоўвала гэту функцыю, дакраніцеся, каб адкрыць налады і адключыць гэта."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index ba640b5..c54379a 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Докоснете, за да изберете език и подредба"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> се показва върху други приложения"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> се показва в/у други прилож."</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Ако не искате <xliff:g id="NAME">%s</xliff:g> да използва тази функция, докоснете, за да отворите настройките, и я изключете."</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index ec7bc7d..c3c8e46 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ভাষা এবং লেআউট নির্বাচন করুন আলতো চাপ দিন"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> অন্যান্য অ্যাপ্লিকেশানের ওপরেও প্রদর্শিত"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> অন্যান্য অ্যাপের ওপর প্রদর্শিত হচ্ছে"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> কে এই বৈশিষ্ট্যটি ব্যবহার করতে দিতে না চাইলে, ট্যাপ করে সেটিংসে যান ও বৈশিষ্ট্যটি বন্ধ করে দিন।"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 06e6020..3c1dbdb 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1231,6 +1231,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite za odabir jezika i rasporeda"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Aplikacija <xliff:g id="NAME">%s</xliff:g> prekriva ostale aplikacije"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"Aplikacija <xliff:g id="NAME">%s</xliff:g> prekriva druge apl."</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Ako ne želite da <xliff:g id="NAME">%s</xliff:g> koristi ovu funkciju, dodirnite da otvorite postavke i isključite je."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index c5774cf..8804d48 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca per seleccionar l\'idioma i el disseny"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"S\'està superposant <xliff:g id="NAME">%s</xliff:g> a altres aplicacions"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> s\'està superposant a altres apps"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Si no vols que <xliff:g id="NAME">%s</xliff:g> utilitzi aquesta funció, toca per obrir la configuració i desactiva-la."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index e33b3df..785e32f 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1248,6 +1248,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Klepnutím vyberte jazyk a rozvržení"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Aplikace <xliff:g id="NAME">%s</xliff:g> se zobrazuje přes ostatní aplikace"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> se zobrazuje přes ostatní aplikace"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Pokud nechcete, aby aplikace <xliff:g id="NAME">%s</xliff:g> tuto funkci používala, klepnutím otevřete nastavení a funkci vypněte."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index cdb8a2b..f9bfc51 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tryk for at vælge sprog og layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> vises over andre apps"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> vises over andre apps"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Hvis du ikke ønsker, at <xliff:g id="NAME">%s</xliff:g> skal benytte denne funktion, kan du åbne indstillingerne og deaktivere den."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 58f3204..d90f6f3 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Zum Auswählen von Sprache und Layout tippen"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> wird über anderen Apps angezeigt"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> wird über anderen Apps angezeigt"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Wenn du nicht möchtest, dass <xliff:g id="NAME">%s</xliff:g> diese Funktion verwendet, tippe, um die Einstellungen zu öffnen und die Funktion zu deaktivieren."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 780c69d..ff86202 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Πατήστε για να επιλέξετε γλώσσα και διάταξη"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Η εφαρμογή <xliff:g id="NAME">%s</xliff:g> προβάλλεται πάνω από άλλες εφαρμογές"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"Η εφαρμογή <xliff:g id="NAME">%s</xliff:g> επικαλύπτει άλλες"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Εάν δεν θέλετε να χρησιμοποιείται αυτή η λειτουργία από την εφαρμογή <xliff:g id="NAME">%s</xliff:g>, πατήστε για να ανοίξετε τις ρυθμίσεις και απενεργοποιήστε την."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 2d823ea..5b03ddb 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> displaying over other apps"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> is displaying over other apps"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"If you don’t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 2d823ea..5b03ddb 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> displaying over other apps"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> is displaying over other apps"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"If you don’t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 2d823ea..5b03ddb 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> displaying over other apps"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> is displaying over other apps"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"If you don’t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 45584b5..d85c4b7 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Presiona para seleccionar el idioma y el diseño"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> se muestra sobre otras apps"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> se muestra sobre otras apps"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Si no quieres que <xliff:g id="NAME">%s</xliff:g> use esta función, presiona para abrir la configuración y desactivarla."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 926ee47..a989f59 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca para seleccionar el idioma y el diseño"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> se muestra sobre otras aplicaciones"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> se muestra sobre otras apps"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Si no quieres que <xliff:g id="NAME">%s</xliff:g> utilice esta función, toca la notificación para abrir los ajustes y desactivarla."</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 7e690be..7d58cd1 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Puudutage keele ja paigutuse valimiseks"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Rakendus <xliff:g id="NAME">%s</xliff:g> kuvatakse teiste rakenduste peal"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> kuvat. teiste rakenduste peal"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Kui te ei soovi, et rakendus <xliff:g id="NAME">%s</xliff:g> seda funktsiooni kasutaks, puudutage seadete avamiseks ja lülitage see välja."</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 1407479..05f6dde 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Hizkuntza eta diseinua hautatzeko, sakatu hau"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> aplikazioen gainean agertzea"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"Besteen gainean agertzen da <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Ez baduzu nahi <xliff:g id="NAME">%s</xliff:g> zerbitzuak eginbide hori erabiltzea, sakatu hau ezarpenak ireki eta aukera desaktibatzeko."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 8b894ee..0b1f62f 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"برای انتخاب زبان و چیدمان ضربه بزنید"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> روی برنامههای دیگر نشان داده میشود"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> روی برنامههای دیگر نشان داده میشود"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"اگر نمیخواهید <xliff:g id="NAME">%s</xliff:g> از این قابلیت استفاده کند، با ضربه زدن، تنظیمات را باز کنید و قابلیت را خاموش کنید."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index af1a061..d0270c7 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Valitse kieli ja asettelu koskettamalla."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> näkyy muiden sovellusten päällä"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> näkyy sovellusten päällä"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Jos et halua, että <xliff:g id="NAME">%s</xliff:g> voi käyttää tätä ominaisuutta, avaa asetukset napauttamalla ja poista se käytöstä."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index ba2c01e..dcb8f53 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Touchez pour sélectionner la langue et la configuration du clavier"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> affiche du contenu par-dessus d\'autres applications"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> aff. contenu par-dessus applis"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Si vous ne voulez pas que <xliff:g id="NAME">%s</xliff:g> utilise cette fonctionnalités, touchez l\'écran pour ouvrir les paramètres, puis désactivez-la."</string>
@@ -1286,14 +1288,14 @@
<string name="vr_listener_binding_label" msgid="4316591939343607306">"Écouteur de réalité virtuelle"</string>
<string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Fournisseur de conditions"</string>
<string name="notification_ranker_binding_label" msgid="774540592299064747">"Service de classement des notifications"</string>
- <string name="vpn_title" msgid="19615213552042827">"VPN activé"</string>
- <string name="vpn_title_long" msgid="6400714798049252294">"VPN activé par <xliff:g id="APP">%s</xliff:g>"</string>
+ <string name="vpn_title" msgid="19615213552042827">"RPV activé"</string>
+ <string name="vpn_title_long" msgid="6400714798049252294">"RPV activé par <xliff:g id="APP">%s</xliff:g>"</string>
<string name="vpn_text" msgid="1610714069627824309">"Appuyez ici pour gérer le réseau."</string>
<string name="vpn_text_long" msgid="4907843483284977618">"Connecté à <xliff:g id="SESSION">%s</xliff:g>. Appuyez ici pour gérer le réseau."</string>
- <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN permanent en cours de connexion…"</string>
- <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN permanent connecté"</string>
+ <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"RPV permanent en cours de connexion…"</string>
+ <string name="vpn_lockdown_connected" msgid="8202679674819213931">"RPV permanent connecté"</string>
<string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"RPV permanent déconnecté"</string>
- <string name="vpn_lockdown_error" msgid="6009249814034708175">"Erreur du VPN permanent"</string>
+ <string name="vpn_lockdown_error" msgid="6009249814034708175">"Erreur du RPV permanent"</string>
<string name="vpn_lockdown_config" msgid="5099330695245008680">"Touchez pour configurer"</string>
<string name="upload_file" msgid="2897957172366730416">"Choisir un fichier"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Aucun fichier sélectionné"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 12c6866..ccaed18 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Appuyer pour sélectionner la langue et la disposition"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> est affichée sur les autres applications"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> s\'affiche sur autres applis"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Si vous ne voulez pas que l\'application <xliff:g id="NAME">%s</xliff:g> utilise cette fonctionnalité, appuyez ici pour ouvrir les paramètres et la désactiver."</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 68998c3..16c9943 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca para seleccionar o idioma e o deseño"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Mostrando <xliff:g id="NAME">%s</xliff:g> sobre outras aplicacións"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> móstrase sobre outras aplicacións"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Se non queres que <xliff:g id="NAME">%s</xliff:g> utilice esta función, toca para abrir a configuración e desactívaa."</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 7cae6b6..3fcbc97 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ભાષા અને લેઆઉટ પસંદ કરવા માટે ટૅપ કરો"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> અન્ય ઍપ્લિકેશનોની ઉપર પ્રદર્શિત થઈ રહ્યું છે"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> અન્ય ઍપ્લિકેશનો પર દેખાઈ છે"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"જો તમે નથી ઇચ્છતા કે <xliff:g id="NAME">%s</xliff:g> આ સુવિધાનો ઉપયોગ કરે, તો સેટિંગ્સ ખોલવા માટે ટૅપ કરો અને તેને બંધ કરો."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 224710d..d8cab55 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा और लेआउट चुनने के लिए टैप करें"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> अन्य ऐप्लिकेशन के ऊपर दिखाई दे रहा है"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> अन्य ऐप पर दिखाई दे रहा है"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"अगर आप नहीं चाहते कि <xliff:g id="NAME">%s</xliff:g> इस सुविधा का उपयोग करे, तो सेटिंग खोलने और उसे बंद करने के लिए टैप करें."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 61d1862..657456c 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1226,6 +1226,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite da biste odabrali jezik i raspored"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Aplikacija <xliff:g id="NAME">%s</xliff:g> prikazuje se preko drugih aplikacija"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"Apl. <xliff:g id="NAME">%s</xliff:g> zakriva druge aplikacije"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Ako ne želite da aplikacija <xliff:g id="NAME">%s</xliff:g> upotrebljava tu značajku, dodirnite da biste otvorili postavke i isključili je."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index e5105b8..0e05296 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Koppintson a nyelv és a billentyűzetkiosztás kiválasztásához"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"A(z) <xliff:g id="NAME">%s</xliff:g> a többi alkalmazás felett jelenik meg"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> – a többi alkalmazás felett"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Ha nem szeretné, hogy a(z) <xliff:g id="NAME">%s</xliff:g> használja ezt a funkciót, koppintson a beállítások megnyitásához, és kapcsolja ki."</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 215d83a..22dbe67f 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Հպեք՝ լեզուն և դասավորությունն ընտրելու համար"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՈՒՓՔԵւՕՖ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է այլ հավելվածների վերևում"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է այլ հավելվածների վերևում"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Եթե չեք ցանկանում, որ <xliff:g id="NAME">%s</xliff:g>-ն օգտագործի այս գործառույթը, հպեք՝ կարգավորումները բացելու և այն անջատելու համար։"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index c9a8942..3c20118 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1166,7 +1166,7 @@
<string name="sim_done_button" msgid="827949989369963775">"Selesai"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Kartu SIM ditambahkan"</string>
<string name="sim_added_message" msgid="6599945301141050216">"Mulai ulang perangkat Anda untuk mengakses jaringan selular."</string>
- <string name="sim_restart_button" msgid="4722407842815232347">"Mulai Ulang"</string>
+ <string name="sim_restart_button" msgid="4722407842815232347">"Nyalakan Ulang"</string>
<string name="carrier_app_dialog_message" msgid="7066156088266319533">"Agar SIM baru bekerja dengan baik, Anda harus memasang dan membuka aplikasi dari operator."</string>
<string name="carrier_app_dialog_button" msgid="7900235513678617329">"DAPATKAN APLIKASI"</string>
<string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"LAIN KALI"</string>
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ketuk untuk memilih bahasa dan tata letak"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ditampilkan di atas aplikasi lain"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ditampilkan di atas aplikasi lain"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Jika Anda tidak ingin <xliff:g id="NAME">%s</xliff:g> menggunakan fitur ini, tap untuk membuka setelan dan menonaktifkannya."</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 9e8e022..38bc24b 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ýttu til að velja tungumál og útlit"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁBCDÐEÉFGHIÍJKLMNOÓPQRSTUÚVWXYÝZÞÆÖ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AÁBCDÐEÉFGHIÍJKLMNOÓPQRSTUÚVWXYÝZÞÆÖ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> birtist yfir öðrum forritum"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> birtist yfir öðrum forritum"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Ef þú vilt ekki að <xliff:g id="NAME">%s</xliff:g> noti þennan eiginleika skaltu ýta til að opna stillingarnar og slökkva á því."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 975bb57..be2dd22 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tocca per selezionare la lingua e il layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"App <xliff:g id="NAME">%s</xliff:g> visualizzata sopra altre app"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"App <xliff:g id="NAME">%s</xliff:g> mostrata sopra altre app"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Se non desideri che l\'app <xliff:g id="NAME">%s</xliff:g> utilizzi questa funzione, tocca per aprire le impostazioni e disattivarla."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 6eafaaf..93d3df9 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1248,6 +1248,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"הקש כדי לבחור שפה ופריסה"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"תצוגה של <xliff:g id="NAME">%s</xliff:g> מעל אפליקציות אחרות"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> מוצגת מעל אפליקציות אחרות"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"אם אינך רוצה ש-<xliff:g id="NAME">%s</xliff:g> תשתמש בתכונה הזו, הקש כדי לפתוח את ההגדרות ולכבות אותה."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 2a3d9e1..d4745df 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"タップして言語とレイアウトを選択してください"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g>を他のアプリの上に重ねて表示"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>が他のアプリの上に表示されています"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g>でこの機能を使用しない場合は、タップして設定を開いて OFF にしてください。"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 1c3f970..aa92609 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"შეეხეთ ენისა და განლაგების ასარჩევად"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ნაჩვენებია სხვა აპების ინტერფეისის გადაფარვით"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ნაჩვენებია სხვა აპების ინტერფეისის გადაფარვით"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"თუ არ გსურთ <xliff:g id="NAME">%s</xliff:g>-ის მიერ ამ ფუნქციის გამოყენება, შეეხეთ პარამეტრების გასახსნელად და გამორთეთ."</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 4e11c56..50f136f 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Тіл мен пернетақта схемасын таңдау үшін түртіңіз"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> басқа қолданбалардың үстінен шықты"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> басқа қолданбалардың үстінен көрсетіледі"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> деген пайдаланушының бұл функцияны пайдалануына жол бермеу үшін параметрлерді түртіп ашыңыз да, оларды өшіріңіз."</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 6994d7f..9022e3d 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1206,6 +1206,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ប៉ះដើម្បីជ្រើសភាសា និងប្លង់"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> កំពុងបង្ហាញពីលើកម្មវិធីផ្សេងទៀត"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> កំពុងបង្ហាញពីលើកម្មវិធីផ្សេងទៀត"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"ប្រសិនបើអ្នកមិនចង់ឲ្យ <xliff:g id="NAME">%s</xliff:g> ប្រើមុខងារនេះទេ សូមចុចដើម្បីបើកការកំណត់ រួចបិទវា។"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index b3f42d1..6f0ed95 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ಭಾಷೆ ಮತ್ತು ವಿನ್ಯಾಸವನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ಇತರ ಅಪ್ಲಿಕೇಶನ್ಗಳ ಮೂಲಕ ಪ್ರದರ್ಶಿಸುತ್ತಿದೆ"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ಇತರವುಗಳ ಮೇಲೆ ಪ್ರದರ್ಶಿಸುತ್ತಿದೆ"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ಈ ವೈಶಿಷ್ಟ್ಯ ಬಳಸುವುದನ್ನು ನೀವು ಬಯಸದಿದ್ದರೆ, ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆರೆದು, ಅದನ್ನು ಆಫ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index d2f8ecf..5cf961b 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"탭하여 언어와 레이아웃을 선택하세요."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g>이(가) 다른 앱 위에 표시됨"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>이(가) 다른 앱 위에 표시됨"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g>에서 이 기능이 사용되는 것을 원하지 않는 경우 탭하여 설정을 열고 기능을 사용 중지하세요."</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index d627e61..460306c 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Тил жана калып тандоо үчүн таптап коюңуз"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> колдонмосун башка терезелердин үстүнөн көрсөтүү"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>: башка колдонмолордун үстүнөн"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Эгер <xliff:g id="NAME">%s</xliff:g> колдонмосу бул функцияны пайдаланбасын десеңиз, жөндөөлөрдү ачып туруп, аны өчүрүп коюңуз."</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 5dc58f6..9bbb0a98 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ແຕະເພື່ອເລືອກພາສາ ແລະ ໂຄງແປ້ນພິມ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ກຳລັງສະແດງຜົນຢູເທິງແອັບອື່ນຢູ່"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ກຳລັງສະແດງຜົນບັງແອັບອື່ນຢູ່"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"ຫາກທ່ານບໍ່ຕ້ອງການ <xliff:g id="NAME">%s</xliff:g> ໃຫ້ໃຊ້ຄຸນສົມບັດນີ້, ໃຫ້ແຕະເພື່ອເປີດການຕັ້ງຄ່າ ແລ້ວປິດມັນໄວ້."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 14de0a2..8c6175e 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1248,6 +1248,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Palieskite, kad pasirinktumėte kalbą ir išdėstymą"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> rodomi virš kitų programų"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> rodomi virš kitų programų."</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Jei nenorite, kad <xliff:g id="NAME">%s</xliff:g> naudotų šią funkciją, palietę atidarykite nustatymus ir išjunkite ją."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index b191747..d090739 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1226,6 +1226,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Pieskarieties, lai atlasītu valodu un izkārtojumu"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Lietotne <xliff:g id="NAME">%s</xliff:g> tiek rādīta pāri citām lietotnēm"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"Lietotne <xliff:g id="NAME">%s</xliff:g> pāri citām lietotnēm"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Ja nevēlaties lietotnē <xliff:g id="NAME">%s</xliff:g> izmantot šo funkciju, pieskarieties, lai atvērtu iestatījumus un to izslēgtu."</string>
diff --git a/core/res/res/values-mcc310-mnc004/config.xml b/core/res/res/values-mcc310-mnc004/config.xml
index 3049488..a328c49 100755
--- a/core/res/res/values-mcc310-mnc004/config.xml
+++ b/core/res/res/values-mcc310-mnc004/config.xml
@@ -23,6 +23,7 @@
<string-array translatable="false" name="config_cdma_home_system">
<item>64</item>
<item>65</item>
+ <item>66</item>
<item>76</item>
<item>77</item>
<item>78</item>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index 6f85081..04f182e 100755
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -23,6 +23,7 @@
<string-array translatable="false" name="config_cdma_home_system">
<item>64</item>
<item>65</item>
+ <item>66</item>
<item>76</item>
<item>77</item>
<item>78</item>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 2e115fc..f48345b 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Допрете за избирање јазик и распоред"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> се прикажува врз други апликации"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> се прикажува врз апликации"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Ако не сакате <xliff:g id="NAME">%s</xliff:g> да ја користи функцијава, допрете за да ги отворите поставките и исклучете ја."</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 8bc3ff8..cd8e8c9 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ഭാഷയും ലേഔട്ടും തിരഞ്ഞെടുക്കുന്നതിന് ടാപ്പുചെയ്യുക"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> മറ്റ് ആപ്പുകൾക്ക് മുകളിൽ പ്രദർശിപ്പിക്കുന്നു"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> മറ്റ് ആപ്പുകൾക്ക് മുകളിൽ പ്രദർശിപ്പിക്കുന്നു"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ഈ ഫീച്ചർ ഉപയോഗിക്കുന്നതിൽ നിങ്ങൾക്ക് താൽപ്പര്യമില്ലെങ്കിൽ, ടാപ്പുചെയ്ത് ക്രമീകരണം തുറന്ന് അത് ഓഫാക്കുക."</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 8309d77..81f5eaa 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Хэл болон бүдүүвчийг сонгохын тулд дарна уу"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Бусад апп дээгүүр <xliff:g id="NAME">%s</xliff:g>-г харуулж байна"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>-г бусад апп дээр харуулж байна"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Та <xliff:g id="NAME">%s</xliff:g>-д энэ онцлогийг ашиглахыг хүсэхгүй байгаа бол тохиргоог нээгээд, унтраана уу."</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index c0bc82c..cbeaacd 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा आणि लेआउट निवडण्यासाठी टॅप करा"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> इतर अॅप्सवर प्रदर्शित करीत आहे"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> अन्य अॅप्सवर प्रदर्शित करीत आहे"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ने हे वैशिष्ट्य वापरू नये असे आपण इच्छित असल्यास, सेटिंग्ज उघडण्यासाठी टॅप करा आणि ते बंद करा."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 8c4bb4c..2a3c046 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ketik untuk memilih bahasa dan susun atur"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> dipaparkan di atas apl lain"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> dipaparkan di atas apl lain"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Jika anda tidak mahu <xliff:g id="NAME">%s</xliff:g> menggunakan ciri ini, ketik untuk membuka tetapan dan matikannya."</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index f5a1429..993c5cf 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ဘာသာစကားနှင့် အသွင်အပြင်ရွေးချယ်ရန် တို့ပါ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> သည် အခြားအက်ပ်များအပေါ်တွင် ပြပါသည်"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ကို အခြားအက်ပ်များပေါ်တွင် မြင်နေရပါသည်။"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ကို ဤဝန်ဆောင်မှုအား အသုံးမပြုစေလိုလျှင် ဆက်တင်ကို တို့၍ ဖွင့်ပြီး ၎င်းကို ပိတ်လိုက်ပါ။"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 5972329..b88ff35 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Trykk for å velge språk og layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> vises over andre apper"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> vises over andre apper"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Hvis du ikke vil at <xliff:g id="NAME">%s</xliff:g> skal bruke denne funksjonen, kan du trykke for å åpne innstillingene og slå den av."</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 7283936..7734681 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1210,6 +1210,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा र लेआउट चयन गर्न ट्याप गर्नुहोस्"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> अन्य अनुप्रयोगहरूमा देखिँदैछ"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> अन्य अनुप्रयोगहरूमा देखिँदैछ"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"तपाईं <xliff:g id="NAME">%s</xliff:g> ले यो विशेषता प्रयोग नगरेको चाहनुहुन्न भने सेटिङहरू खोली यसलाई निष्क्रिय पार्न ट्याप गर्नुहोस्।"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 09cfa70..b174572 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tik om een taal en indeling te selecteren"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> wordt weergegeven over andere apps"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> wordt weergegeven over apps"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Als je niet wilt dat <xliff:g id="NAME">%s</xliff:g> deze functie gebruikt, tik je om de instellingen te openen en schakel je de functie uit."</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index c89224d..4160344 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ਭਾਸ਼ਾ ਅਤੇ ਖਾਕਾ ਚੁਣਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ਐਪ ਹੋਰ ਐਪਾਂ ਦੇ ਉੱਤੇ ਹੈ"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ਐਪ ਹੋਰਾਂ ਐਪਾਂ ਦੇ ਉੱਤੇ ਹੈ।"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"ਜੇ ਤੁਸੀਂ ਨਹੀਂ ਚਾਹੁੰਦੇ ਕਿ <xliff:g id="NAME">%s</xliff:g> ਐਪ ਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਦੀ ਵਰਤੋਂ ਕਰੇ, ਤਾਂ ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ ਅਤੇ ਇਸਨੂੰ ਬੰਦ ਕਰੋ।"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index cac8e583..209bd21 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1248,6 +1248,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Kliknij, by wybrać język i układ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Wyświetlanie aplikacji <xliff:g id="NAME">%s</xliff:g> nad innymi"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"Aplikacja <xliff:g id="NAME">%s</xliff:g> jest nad innymi"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Jeśli nie chcesz, by aplikacja <xliff:g id="NAME">%s</xliff:g> korzystała z tej funkcji, otwórz ustawienia i ją wyłącz."</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index fe6b766..076e728 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> exibido sobre outros apps"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> exibido sobre outros apps."</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Se você não deseja que o <xliff:g id="NAME">%s</xliff:g> use este recurso, toque para abrir as configurações e desativá-lo."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 4c04879..15e1e3c 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o esquema"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"A aplicação <xliff:g id="NAME">%s</xliff:g> sobrepõe-se a outras aplicações"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"O <xliff:g id="NAME">%s</xliff:g> sobrepõe-se a outras aplic."</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Se não pretende que a aplicação <xliff:g id="NAME">%s</xliff:g> utilize esta funcionalidade, toque para abrir as definições e desative-a."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index fe6b766..076e728 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> exibido sobre outros apps"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> exibido sobre outros apps."</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Se você não deseja que o <xliff:g id="NAME">%s</xliff:g> use este recurso, toque para abrir as configurações e desativá-lo."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 835c9ac..cefbccc 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1226,6 +1226,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Atingeți pentru a selecta limba și aspectul"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> se afișează peste alte aplicații"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> se afișează peste aplicații"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Dacă nu doriți ca <xliff:g id="NAME">%s</xliff:g> să utilizeze această funcție, atingeți pentru a deschide setările și dezactivați-o."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 0d5f04a..d6dd1ee 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1248,6 +1248,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Нажмите, чтобы выбрать язык и раскладку"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g>: поверх других приложений"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>: поверх других приложений"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Чтобы отключить эту функцию для приложения <xliff:g id="NAME">%s</xliff:g>, перейдите в настройки."</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 373fe07..adcfad9 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1206,6 +1206,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"භාෂාව හා පිරිසැලසුම තේරීමට තට්ටු කරන්න"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"අනෙක් යෙදුම්වලට උඩින් <xliff:g id="NAME">%s</xliff:g> සංදර්ශනය කරමින්"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"අනෙක් යෙදුම්වලට උඩින් <xliff:g id="NAME">%s</xliff:g> දිස් වේ"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"ඔබට <xliff:g id="NAME">%s</xliff:g> මෙම විශේෂාංගය භාවිත කිරීමට අවශ්ය නැති නම්, සැකසීම් විවෘත කිරීමට තට්ටු කර එය ක්රියාවිරහිත කරන්න."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 4352a36..c413155 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1248,6 +1248,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Klepnutím vyberte jazyk a rozloženie"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁÄBCČDĎDZDŽEÉFGHCHIÍJKLĽMNŇOÓÔPRŔSŠTŤUÚVWXYÝZŽ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> sa zobrazuje cez iné aplikácie"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> sa zobrazuje cez iné aplikácie"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Ak nechcete, aby aplikácia <xliff:g id="NAME">%s</xliff:g> používala túto funkciu, klepnutím otvorte nastavenia a vypnite ju."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index c6f4404..fb24d43 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1248,6 +1248,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dotaknite se, če želite izbrati jezik in postavitev."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> prekriva druge aplikacije"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> prekriva druge aplikacije"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Če ne želite, da aplikacija <xliff:g id="NAME">%s</xliff:g> uporablja to funkcijo, se dotaknite, da odprete nastavitve, in funkcijo izklopite."</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 70a3efb..47d1d0c 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Trokit për të zgjedhur gjuhën dhe strukturën"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> afishohet mbi aplikacionet e tjera"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> shfaqet mbi apl. e tjera"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Nëse nuk dëshiron që <xliff:g id="NAME">%s</xliff:g> ta përdorë këtë funksion, trokit për të hapur cilësimet dhe për ta çaktivizuar."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index f46505bf..031291d 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1226,6 +1226,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Додирните да бисте изабрали језик и распоред"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Апликација <xliff:g id="NAME">%s</xliff:g> се приказује преко других апликација"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> се приказује преко других аплик."</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Ако не желите ову функцију за <xliff:g id="NAME">%s</xliff:g>, додирните да бисте отворили подешавања и искључили је."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index a3fb085..ffd4f11 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tryck om du vill välja språk och layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> visas över andra appar"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> visas över andra appar"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Om du inte vill att den här funktionen används för <xliff:g id="NAME">%s</xliff:g> öppnar du inställningarna genom att trycka. Sedan inaktiverar du funktionen."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index ce4a469..910949c 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1202,6 +1202,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Gonga ili uchague lugha na muundo"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> inachomoza juu ya programu zingine"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> inachomoza juu ya programu zingine."</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Ikiwa hutaki <xliff:g id="NAME">%s</xliff:g> kutumia kipengele hiki, gonga ili ufungue mipangilio na ukizime."</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index f45789b..41cf95b 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"மொழியையும் தளவமைப்பையும் தேர்ந்தெடுக்க, தட்டவும்"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> பிற பயன்பாடுகளின் மீது தோன்றுகிறது"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> பிற ஆப்ஸின் மீது தோன்றுகிறது"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> இந்த அம்சத்தைப் பயன்படுத்த வேண்டாம் என நினைத்தால், அமைப்புகளைத் திறந்து அதை முடக்க, தட்டவும்."</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 68065b9..6d43b2b 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"భాష మరియు లేఅవుట్ను ఎంచుకోవడానికి నొక్కండి"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ఇతర అనువర్తనాలలో చూపబడుతోంది"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ఇతర అనువర్తనాలలో చూపబడుతోంది"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ఈ లక్షణాన్ని ఉపయోగించకూడదు అని మీరు అనుకుంటే, సెట్టింగ్లను తెరవడానికి నొక్కి, దీన్ని ఆఫ్ చేయండి."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index eb9994a..6b2c4c6 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"แตะเพื่อเลือกภาษาและรูปแบบ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> แสดงทับแอปอื่นๆ"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> กำลังแสดงทับแอปอื่นๆ"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"หากคุณไม่ต้องการให้ <xliff:g id="NAME">%s</xliff:g> ใช้ฟีเจอร์นี้ ให้แตะเพื่อเปิดการตั้งค่าแล้วปิดฟีเจอร์"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index ee01ff2..7cc10be82 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"I-tap upang pumili ng wika at layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Ipinapakita sa itaas ng iba pang app ang <xliff:g id="NAME">%s</xliff:g>."</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"Nasa ibabaw ng ibang app ang <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Kung ayaw mong gamitin ng <xliff:g id="NAME">%s</xliff:g> ang feature na ito, i-tap upang buksan ang mga setting at i-off ito."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index bbae91a..2096a93 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dili ve düzeni seçmek için dokunun"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g>, diğer uygulamaların üzerinde görüntüleniyor"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>, diğer uygulamaların üzerinde gösteriliyor"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> uygulamasının bu özelliği kullanmasını istemiyorsanız dokunarak ayarları açın ve özelliği kapatın."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index f187c03..f635ec4 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1248,6 +1248,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Торкніться, щоб вибрати мову та розкладку"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Додаток <xliff:g id="NAME">%s</xliff:g> відображається поверх інших додатків"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> відображається поверх інших додатків"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Щоб у додатку <xliff:g id="NAME">%s</xliff:g> не працювала ця функція, вимкніть її в налаштуваннях."</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 310bddd..7f007be 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"زبان اور لے آؤٹ منتخب کرنے کیلئے تھپتھپائیں"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> کو دیگر ایپس پر دکھایا کیا جا رہا ہے"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> دیگر ایپس پر ڈسپلے ہو رہی ہے"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"اگر آپ نہیں چاہتے ہیں کہ <xliff:g id="NAME">%s</xliff:g> اس خصوصیت کا استعمال کرے تو ترتیبات کھولنے کیلئے تھپتھپائیں اور اسے بند کریں۔"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index bd53da5..4351ab2 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1205,6 +1205,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Til va sxemani belgilash uchun bosing"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> boshqa ilovalar ustidan ochilgan"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> boshqa ilovalar ustidan ochilgan"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ilovasi uchun bu funksiyani sozlamalar orqali o‘chirib qo‘yish mumkin."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 655bdc7..f134eca 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Nhấn để chọn ngôn ngữ và bố cục"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> hiển thị trên các ứng dụng khác"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> hiển thị trên ứng dụng khác"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Nếu bạn không muốn <xliff:g id="NAME">%s</xliff:g> sử dụng tính năng này, hãy nhấn để mở cài đặt và tắt tính năng này."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index c19e3d2..fda476d 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"点按即可选择语言和布局"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g>正在其他应用的上层显示内容"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>正在其他应用的上层显示内容"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"如果您不想让<xliff:g id="NAME">%s</xliff:g>使用此功能,请点按以打开设置,然后关闭此功能。"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 415c1ac..797a195 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"輕按即可選取語言和鍵盤配置"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"「<xliff:g id="NAME">%s</xliff:g>」目前可顯示在其他應用程式上面"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"「<xliff:g id="NAME">%s</xliff:g>」正在其他應用程式上顯示內容"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"如果您不想「<xliff:g id="NAME">%s</xliff:g>」使用此功能,請輕按以開啟設定,然後停用此功能。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 36f9a9e..9008d8e 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"輕觸即可選取語言和版面配置"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"「<xliff:g id="NAME">%s</xliff:g>」在其他應用程式上顯示內容"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"「<xliff:g id="NAME">%s</xliff:g>」正在其他應用程式上顯示內容"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"如果你不想讓「<xliff:g id="NAME">%s</xliff:g>」使用這項功能,請輕觸開啟設定頁面,然後停用此功能。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index ff35931..c1bff23 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1204,6 +1204,8 @@
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Thepha ukuze ukhethe ulimi nesakhiwo"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ukubonisa ngaphezu kwezinye izinhlelo zokusebenza"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ibonisa ngaphezu kwezinye izinhlelo zokusebenza"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Uma ungafuni ukuthi i-<xliff:g id="NAME">%s</xliff:g> isebenzise lesi sici, thepha ukuze uvule izilungiselelo bese usivale."</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8e6c402..241e565 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1099,6 +1099,11 @@
that can be set by the user. -->
<integer name="config_screenBrightnessDoze">1</integer>
+ <!-- Whether or not to skip the initial brightness ramps when the display transitions to
+ STATE_ON. Setting this to true will skip the brightness ramp to the last stored active
+ brightness value and will repeat for the following ramp if autobrightness is enabled. -->
+ <bool name="config_skipScreenOnBrightnessRamp">false</bool>
+
<!-- Allow automatic adjusting of the screen brightness while dozing in low power state. -->
<bool name="config_allowAutoBrightnessWhileDozing">false</bool>
@@ -2531,6 +2536,10 @@
<!-- The default vibration strength, must be between 1 and 255 inclusive. -->
<integer name="config_defaultVibrationAmplitude">255</integer>
+ <!-- If the device should still vibrate even in low power mode, for certain priority vibrations
+ (e.g. accessibility, alarms). This is mainly for Wear devices that don't have speakers. -->
+ <bool name="config_allowPriorityVibrationsInLowPowerMode">false</bool>
+
<!-- Number of retries Cell Data should attempt for a given error code before
restarting the modem.
Error codes not listed will not lead to modem restarts.
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 90ece60..3eebe7e 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -191,21 +191,15 @@
<!-- Notification title to tell the user that data service is blocked by access control. -->
<string name="RestrictedOnDataTitle">No data service</string>
- <!-- Notification title to tell the user that emergency service is blocked by access control. -->
- <string name="RestrictedOnEmergencyTitle">No emergency service</string>
+ <!-- Notification title to tell the user that emergency calling is blocked by access control. -->
+ <string name="RestrictedOnEmergencyTitle">No emergency calling</string>
<!-- Notification title to tell the user that normal service is blocked by access control. -->
<string name="RestrictedOnNormalTitle">No voice service</string>
<!-- Notification title to tell the user that all emergency and normal voice services are blocked by access control. -->
<string name="RestrictedOnAllVoiceTitle">No voice/emergency service</string>
- <!-- Notification content to tell the user that data service is blocked by access control. -->
- <string name="RestrictedOnDataContent">Your carrier has temporarily suspended data service at this location</string>
- <!-- Notification content to tell the user that emergency service is blocked by access control. -->
- <string name="RestrictedOnEmergencyContent">Your carrier has temporarily suspended emergency calls at this location</string>
- <!-- Notification content to tell the user that normal service is blocked by access control. -->
- <string name="RestrictedOnNormalContent">Your carrier has temporarily suspended voice calls at this location</string>
- <!-- Notification content to tell the user that all emergency and normal voice services are blocked by access control. -->
- <string name="RestrictedOnAllVoiceContent">Your carrier has temporarily suspended voice and emergency calls at this location</string>
+ <!-- Notification content to tell the user that voice/data/emergency service is blocked by access control. -->
+ <string name="RestrictedStateContent">Temporarily not offered by the mobile network at your location</string>
<!-- Displayed to tell the user that they should switch their network preference. -->
<string name="NetworkPreferenceSwitchTitle">Can\u2019t reach network</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index bfd40bd..7dd4022 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -521,10 +521,7 @@
<java-symbol type="string" name="RestrictedOnDataTitle" />
<java-symbol type="string" name="RestrictedOnEmergencyTitle" />
<java-symbol type="string" name="RestrictedOnNormalTitle" />
- <java-symbol type="string" name="RestrictedOnAllVoiceContent" />
- <java-symbol type="string" name="RestrictedOnDataContent" />
- <java-symbol type="string" name="RestrictedOnEmergencyContent" />
- <java-symbol type="string" name="RestrictedOnNormalContent" />
+ <java-symbol type="string" name="RestrictedStateContent" />
<java-symbol type="string" name="notification_channel_network_alert" />
<java-symbol type="string" name="notification_channel_call_forward" />
<java-symbol type="string" name="notification_channel_emergency_callback" />
@@ -1755,6 +1752,7 @@
<java-symbol type="bool" name="config_sf_limitedAlpha" />
<java-symbol type="bool" name="config_unplugTurnsOnScreen" />
<java-symbol type="bool" name="config_usbChargingMessage" />
+ <java-symbol type="bool" name="config_skipScreenOnBrightnessRamp" />
<java-symbol type="bool" name="config_allowAutoBrightnessWhileDozing" />
<java-symbol type="bool" name="config_allowTheaterModeWakeFromUnplug" />
<java-symbol type="bool" name="config_allowTheaterModeWakeFromGesture" />
@@ -1808,6 +1806,7 @@
<java-symbol type="dimen" name="default_minimal_size_pip_resizable_task" />
<java-symbol type="dimen" name="task_height_of_minimized_mode" />
<java-symbol type="fraction" name="config_screenAutoBrightnessDozeScaleFactor" />
+ <java-symbol type="bool" name="config_allowPriorityVibrationsInLowPowerMode" />
<java-symbol type="fraction" name="config_autoBrightnessAdjustmentMaxGamma" />
<java-symbol type="integer" name="config_autoBrightnessAmbientLightHorizon"/>
<java-symbol type="integer" name="config_autoBrightnessBrighteningLightDebounce"/>
@@ -3024,4 +3023,5 @@
<java-symbol type="bool" name="config_handleVolumeKeysInWindowManager" />
<java-symbol type="integer" name="config_inCallNotificationVolumeRelative" />
+ <java-symbol type="drawable" name="stat_sys_vitals" />
</resources>
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index e3b4740..f931d21 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1036,6 +1036,8 @@
// old shader's pointer may be reused by another shader allocation later
if (mShader != shader) {
mNativeShader = -1;
+ // Release any native references to the old shader content
+ nSetShader(mNativePaint, 0);
}
// Defer setting the shader natively until getNativeInstance() is called
mShader = shader;
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 00b5eda..90d6ab8 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -834,6 +834,16 @@
final Animator localAnimator = animator.clone();
final String targetName = mTargetNameMap.get(animator);
final Object target = mVectorDrawable.getTargetByName(targetName);
+ if (!mShouldIgnoreInvalidAnim) {
+ if (target == null) {
+ throw new IllegalStateException("Target with the name \"" + targetName
+ + "\" cannot be found in the VectorDrawable to be animated.");
+ } else if (!(target instanceof VectorDrawable.VectorDrawableState)
+ && !(target instanceof VectorDrawable.VObject)) {
+ throw new UnsupportedOperationException("Target should be either VGroup, VPath,"
+ + " or ConstantState, " + target.getClass() + " is not supported");
+ }
+ }
localAnimator.setTarget(target);
return localAnimator;
}
@@ -1321,16 +1331,10 @@
throw new IllegalArgumentException("ClipPath only supports PathData " +
"property");
}
-
}
} else if (target instanceof VectorDrawable.VectorDrawableState) {
createRTAnimatorForRootGroup(values, animator,
(VectorDrawable.VectorDrawableState) target, startTime);
- } else if (!mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) {
- // Should never get here
- throw new UnsupportedOperationException("Target should be either VGroup, VPath, " +
- "or ConstantState, " + target == null ? "Null target" : target.getClass() +
- " is not supported");
}
}
diff --git a/location/java/android/location/CountryDetector.java b/location/java/android/location/CountryDetector.java
index ce3c56f..ec6dfb7 100644
--- a/location/java/android/location/CountryDetector.java
+++ b/location/java/android/location/CountryDetector.java
@@ -18,6 +18,8 @@
import java.util.HashMap;
+import android.annotation.SystemService;
+import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
@@ -40,13 +42,10 @@
* To be notified of the future country change, use the
* {@link #addCountryListener}
* <p>
- * <p>
- * You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.COUNTRY_DETECTOR)}.
*
* @hide
*/
+@SystemService(Context.COUNTRY_DETECTOR)
public class CountryDetector {
/**
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index f9385c6..26ac2a2 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -20,7 +20,9 @@
import android.Manifest;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.annotation.TestApi;
import android.app.PendingIntent;
import android.content.Context;
@@ -47,11 +49,6 @@
* {@link Intent} when the device enters the proximity of a given
* geographical location.
*
- * <p>You do not
- * instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.LOCATION_SERVICE)}.
- *
* <p class="note">Unless noted, all Location API methods require
* the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} or
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permissions.
@@ -60,8 +57,8 @@
* return location results, but the update rate will be throttled and the exact
* location will be obfuscated to a coarse level of accuracy.
*/
-public class LocationManager
-{
+@SystemService(Context.LOCATION_SERVICE)
+public class LocationManager {
private static final String TAG = "LocationManager";
private final Context mContext;
@@ -831,6 +828,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestLocationUpdates(LocationRequest request, LocationListener listener,
Looper looper) {
checkListener(listener);
@@ -859,6 +857,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestLocationUpdates(LocationRequest request, PendingIntent intent) {
checkPendingIntent(intent);
requestLocationUpdates(request, null, null, intent);
@@ -1820,6 +1819,7 @@
*/
@Deprecated
@SystemApi
+ @SuppressLint("Doclava125")
public boolean addGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {
return false;
}
@@ -1857,6 +1857,7 @@
*/
@Deprecated
@SystemApi
+ @SuppressLint("Doclava125")
public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {
}
@@ -1877,6 +1878,7 @@
*/
@Deprecated
@SystemApi
+ @SuppressLint("Doclava125")
public boolean addGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {
return false;
}
@@ -1891,6 +1893,7 @@
*/
@Deprecated
@SystemApi
+ @SuppressLint("Doclava125")
public void removeGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 0b5dff2..20deeb16 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -19,9 +19,11 @@
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothDevice;
@@ -58,10 +60,8 @@
/**
* AudioManager provides access to volume and ringer mode control.
- * <p>
- * Use <code>Context.getSystemService(Context.AUDIO_SERVICE)</code> to get
- * an instance of this class.
*/
+@SystemService(Context.AUDIO_SERVICE)
public class AudioManager {
private Context mOriginalContext;
@@ -2827,6 +2827,7 @@
* {@link #SUCCESS} otherwise.
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public int registerAudioPolicy(@NonNull AudioPolicy policy) {
if (policy == null) {
throw new IllegalArgumentException("Illegal null AudioPolicy argument");
@@ -2852,6 +2853,7 @@
* @param policy the non-null {@link AudioPolicy} to unregister.
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public void unregisterAudioPolicyAsync(@NonNull AudioPolicy policy) {
if (policy == null) {
throw new IllegalArgumentException("Illegal null AudioPolicy argument");
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index 228a6de..dd731df 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -136,7 +136,13 @@
private void teardownConnection() {
if (mConnection != null) {
- mInputStream = null;
+ if (mInputStream != null) {
+ try {
+ mInputStream.close();
+ } catch (IOException e) {
+ }
+ mInputStream = null;
+ }
mConnection.disconnect();
mConnection = null;
@@ -298,8 +304,7 @@
mCurrentOffset = offset;
} catch (IOException e) {
mTotalSize = -1;
- mInputStream = null;
- mConnection = null;
+ teardownConnection();
mCurrentOffset = -1;
throw e;
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 44494a6..91dada7 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -20,6 +20,7 @@
import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.SystemService;
import android.app.ActivityThread;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -61,6 +62,7 @@
* <p>The media router API is not thread-safe; all interactions with it must be
* done from the main thread of the process.</p>
*/
+@SystemService(Context.MEDIA_ROUTER_SERVICE)
public class MediaRouter {
private static final String TAG = "MediaRouter";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index 07c8ae8..a015732 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -16,7 +16,9 @@
package android.media.midi;
+import android.annotation.SystemService;
import android.bluetooth.BluetoothDevice;
+import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
import android.os.Bundle;
@@ -28,13 +30,8 @@
/**
* This class is the public application interface to the MIDI service.
- *
- * <p>You can obtain an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- *
- * {@samplecode
- * MidiManager manager = (MidiManager) getSystemService(Context.MIDI_SERVICE);}
*/
+@SystemService(Context.MIDI_SERVICE)
public final class MidiManager {
private static final String TAG = "MidiManager";
diff --git a/media/java/android/media/projection/MediaProjectionManager.java b/media/java/android/media/projection/MediaProjectionManager.java
index f4a548b..9f2c08e 100644
--- a/media/java/android/media/projection/MediaProjectionManager.java
+++ b/media/java/android/media/projection/MediaProjectionManager.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemService;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@@ -33,14 +34,8 @@
/**
* Manages the retrieval of certain types of {@link MediaProjection} tokens.
- *
- * <p>
- * Get an instance of this class by calling {@link
- * android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with the argument {@link
- * android.content.Context#MEDIA_PROJECTION_SERVICE}.
- * </p>
*/
+@SystemService(Context.MEDIA_PROJECTION_SERVICE)
public final class MediaProjectionManager {
private static final String TAG = "MediaProjectionManager";
/** @hide */
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 83793ae..e02a4dc 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -18,7 +18,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.ComponentName;
import android.content.Context;
import android.media.AudioManager;
@@ -42,13 +44,11 @@
* Provides support for interacting with {@link MediaSession media sessions}
* that applications have published to express their ongoing media playback
* state.
- * <p>
- * Use <code>Context.getSystemService(Context.MEDIA_SESSION_SERVICE)</code> to
- * get an instance of this class.
*
* @see MediaSession
* @see MediaController
*/
+@SystemService(Context.MEDIA_SESSION_SERVICE)
public final class MediaSessionManager {
private static final String TAG = "SessionManager";
@@ -357,6 +357,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER)
public void setOnVolumeKeyLongPressListener(
OnVolumeKeyLongPressListener listener, @Nullable Handler handler) {
synchronized (mLock) {
@@ -392,6 +393,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.SET_MEDIA_KEY_LISTENER)
public void setOnMediaKeyListener(OnMediaKeyListener listener, @Nullable Handler handler) {
synchronized (mLock) {
try {
diff --git a/media/java/android/media/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
index d5296ae..a48abff 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerDetector.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
@@ -20,6 +20,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.SoundTrigger;
@@ -235,6 +236,7 @@
* {@link Callback}.
* @return Indicates whether the call succeeded or not.
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
public boolean startRecognition(@RecognitionFlags int recognitionFlags) {
if (DBG) {
Slog.d(TAG, "startRecognition()");
@@ -258,6 +260,7 @@
/**
* Stops recognition for the associated model.
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
public boolean stopRecognition() {
int status = STATUS_OK;
try {
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index fdd7fc2..7f8140a 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -18,7 +18,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.Context;
import android.hardware.soundtrigger.SoundTrigger;
import android.os.Handler;
@@ -39,6 +41,7 @@
* @hide
*/
@SystemApi
+@SystemService(Context.SOUND_TRIGGER_SERVICE)
public final class SoundTriggerManager {
private static final boolean DBG = false;
private static final String TAG = "SoundTriggerManager";
@@ -65,6 +68,7 @@
/**
* Updates the given sound trigger model.
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
public void updateModel(Model model) {
try {
mSoundTriggerService.updateSoundModel(model.getGenericSoundModel());
@@ -77,6 +81,7 @@
* Returns the sound trigger model represented by the given UUID. An instance of {@link Model}
* is returned.
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
public Model getModel(UUID soundModelId) {
try {
return new Model(mSoundTriggerService.getSoundModel(
@@ -89,6 +94,7 @@
/**
* Deletes the sound model represented by the provided UUID.
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
public void deleteModel(UUID soundModelId) {
try {
mSoundTriggerService.deleteSoundModel(new ParcelUuid(soundModelId));
@@ -110,6 +116,7 @@
* @return Instance of {@link SoundTriggerDetector} or null on error.
*/
@Nullable
+ @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
public SoundTriggerDetector createSoundTriggerDetector(UUID soundModelId,
@NonNull SoundTriggerDetector.Callback callback, @Nullable Handler handler) {
if (soundModelId == null) {
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 68ee02c..28fd338 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -21,6 +21,8 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.media.PlaybackParams;
@@ -57,9 +59,7 @@
/**
* Central system API to the overall TV input framework (TIF) architecture, which arbitrates
- * interaction between applications and the selected TV inputs. You can retrieve an instance of
- * this interface with {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.TV_INPUT_SERVICE)}.
+ * interaction between applications and the selected TV inputs.
*
* <p>There are three primary parties involved in the TV input framework (TIF) architecture:
*
@@ -78,6 +78,7 @@
* programs.
* </ul>
*/
+@SystemService(Context.TV_INPUT_SERVICE)
public final class TvInputManager {
private static final String TAG = "TvInputManager";
@@ -1516,6 +1517,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT)
public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId) {
try {
return mService.getAvailableTvStreamConfigList(inputId, mUserId);
@@ -1534,6 +1536,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT)
public boolean captureFrame(String inputId, Surface surface, TvStreamConfig config) {
try {
return mService.captureFrame(inputId, surface, config, mUserId);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
index 6678f8b..5680d9f 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
@@ -1139,9 +1139,18 @@
}
List<Integer> modeList = new ArrayList<Integer>();
for (int mode : modes) {
- modeList.add(mode);
+ // Skip vendor-added modes
+ if (mode <= CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE) {
+ modeList.add(mode);
+ }
}
checkTrueForKey(modesKey, "value is empty", !modeList.isEmpty());
+ modes = new int[modeList.size()];
+ for (int i = 0; i < modeList.size(); i++) {
+ modes[i] = modeList.get(i);
+ }
+
+ checkTrueForKey(modesKey, "value is empty", !modeList.isEmpty());
// All camera device must support ON
checkTrueForKey(modesKey, "values " + modeList.toString() + " must contain ON mode",
@@ -1227,7 +1236,17 @@
return new int[0];
}
- List<Integer> modesList = Arrays.asList(CameraTestUtils.toObject(afModes));
+ List<Integer> modesList = new ArrayList<Integer>();
+ for (int afMode : afModes) {
+ // Skip vendor-added AF modes
+ if (afMode > CameraCharacteristics.CONTROL_AF_MODE_EDOF) continue;
+ modesList.add(afMode);
+ }
+ afModes = new int[modesList.size()];
+ for (int i = 0; i < modesList.size(); i++) {
+ afModes[i] = modesList.get(i);
+ }
+
if (isHardwareLevelLimitedOrBetter()) {
// Some LEGACY mode devices do not support AF OFF
checkTrueForKey(key, " All camera devices must support OFF mode",
@@ -1417,6 +1436,16 @@
return fpsRanges;
}
+ public static String getAeModeName(int aeMode) {
+ return (aeMode >= AE_MODE_NAMES.length) ? String.format("VENDOR_AE_MODE_%d", aeMode) :
+ AE_MODE_NAMES[aeMode];
+ }
+
+ public static String getAfModeName(int afMode) {
+ return (afMode >= AF_MODE_NAMES.length) ? String.format("VENDOR_AF_MODE_%d", afMode) :
+ AF_MODE_NAMES[afMode];
+ }
+
/**
* Get the highest supported target FPS range.
* Prioritizes maximizing the min FPS, then the max FPS without lowering min FPS.
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 401a7bc..582b660 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -58,6 +58,7 @@
public class CaptivePortalLoginActivity extends Activity {
private static final String TAG = CaptivePortalLoginActivity.class.getSimpleName();
private static final boolean DBG = true;
+ private static final boolean VDBG = false;
private static final int SOCKET_TIMEOUT_MS = 10000;
@@ -311,6 +312,7 @@
private class MyWebViewClient extends WebViewClient {
private static final String INTERNAL_ASSETS = "file:///android_asset/";
+
private final String mBrowserBailOutToken = Long.toString(new Random().nextLong());
// How many Android device-independent-pixels per scaled-pixel
// dp/sp = (px/sp) / (px/dp) = (1/sp) / (1/dp)
@@ -363,12 +365,6 @@
testForCaptivePortal();
}
- // Convert Android device-independent-pixels (dp) to HTML size.
- private String dp(int dp) {
- // HTML px's are scaled just like dp's, so just add "px" suffix.
- return Integer.toString(dp) + "px";
- }
-
// Convert Android scaled-pixels (sp) to HTML size.
private String sp(int sp) {
// Convert sp to dp's.
@@ -376,25 +372,11 @@
// Apply a scale factor to make things look right.
dp *= 1.3;
// Convert dp's to HTML size.
- return dp((int)dp);
+ // HTML px's are scaled just like dp's, so just add "px" suffix.
+ return Integer.toString((int)dp) + "px";
}
// A web page consisting of a large broken lock icon to indicate SSL failure.
- private final String SSL_ERROR_HTML = "<html><head><style>" +
- "body { margin-left:" + dp(48) + "; margin-right:" + dp(48) + "; " +
- "margin-top:" + dp(96) + "; background-color:#fafafa; }" +
- "img { width:" + dp(48) + "; height:" + dp(48) + "; }" +
- "div.warn { font-size:" + sp(16) + "; margin-top:" + dp(16) + "; " +
- " opacity:0.87; line-height:1.28; }" +
- "div.example { font-size:" + sp(14) + "; margin-top:" + dp(16) + "; " +
- " opacity:0.54; line-height:1.21905; }" +
- "a { font-size:" + sp(14) + "; text-decoration:none; text-transform:uppercase; " +
- " margin-top:" + dp(24) + "; display:inline-block; color:#4285F4; " +
- " height:" + dp(48) + "; font-weight:bold; }" +
- "</style></head><body><p><img src=quantum_ic_warning_amber_96.png><br>" +
- "<div class=warn>%s</div>" +
- "<div class=example>%s</div>" +
- "<a href=%s>%s</a></body></html>";
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
@@ -402,10 +384,63 @@
// Only show host to avoid leaking private info.
Uri.parse(error.getUrl()).getHost() + " certificate: " +
error.getCertificate() + "); displaying SSL warning.");
- final String html = String.format(SSL_ERROR_HTML, getString(R.string.ssl_error_warning),
- getString(R.string.ssl_error_example), mBrowserBailOutToken,
- getString(R.string.ssl_error_continue));
- view.loadDataWithBaseURL(INTERNAL_ASSETS, html, "text/HTML", "UTF-8", null);
+ final String sslErrorPage = makeSslErrorPage();
+ if (VDBG) {
+ Log.d(TAG, sslErrorPage);
+ }
+ view.loadDataWithBaseURL(INTERNAL_ASSETS, sslErrorPage, "text/HTML", "UTF-8", null);
+ }
+
+ private String makeSslErrorPage() {
+ final String warningMsg = getString(R.string.ssl_error_warning);
+ final String exampleMsg = getString(R.string.ssl_error_example);
+ final String continueMsg = getString(R.string.ssl_error_continue);
+ return String.join("\n",
+ "<html>",
+ "<head>",
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">",
+ " <style>",
+ " body {",
+ " background-color:#fafafa;",
+ " margin:auto;",
+ " width:80%;",
+ " margin-top: 96px",
+ " }",
+ " img {",
+ " height:48px;",
+ " width:48px;",
+ " }",
+ " div.warn {",
+ " font-size:" + sp(16) + ";",
+ " line-height:1.28;",
+ " margin-top:16px;",
+ " opacity:0.87;",
+ " }",
+ " div.example {",
+ " font-size:" + sp(14) + ";",
+ " line-height:1.21905;",
+ " margin-top:16px;",
+ " opacity:0.54;",
+ " }",
+ " a {",
+ " color:#4285F4;",
+ " display:inline-block;",
+ " font-size:" + sp(14) + ";",
+ " font-weight:bold;",
+ " height:48px;",
+ " margin-top:24px;",
+ " text-decoration:none;",
+ " text-transform:uppercase;",
+ " }",
+ " </style>",
+ "</head>",
+ "<body>",
+ " <p><img src=quantum_ic_warning_amber_96.png><br>",
+ " <div class=warn>" + warningMsg + "</div>",
+ " <div class=example>" + exampleMsg + "</div>",
+ " <a href=" + mBrowserBailOutToken + ">" + continueMsg + "</a>",
+ "</body>",
+ "</html>");
}
@Override
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index b7e3684..c51854d 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -144,7 +144,7 @@
<string name="choose_profile" msgid="6921016979430278661">"Seleccionar perfil"</string>
<string name="category_personal" msgid="1299663247844969448">"Personal"</string>
<string name="category_work" msgid="8699184680584175622">"Trabajo"</string>
- <string name="development_settings_title" msgid="215179176067683667">"Opciones de desarrollo"</string>
+ <string name="development_settings_title" msgid="215179176067683667">"Opciones para desarrolladores"</string>
<string name="development_settings_enable" msgid="542530994778109538">"Habilitar opciones para desarrolladores"</string>
<string name="development_settings_summary" msgid="1815795401632854041">"Establecer opciones de desarrollo de aplicaciones"</string>
<string name="development_settings_not_available" msgid="4308569041701535607">"Las opciones de desarrollador no están disponibles para este usuario"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 4921be1..8f7a3dd 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -840,6 +840,16 @@
<!-- Summary for switch preference to denote it is switched off [CHAR LIMIT=50] -->
<string name="disabled_by_admin">Disabled by admin</string>
+ <!-- [CHAR LIMIT=25] Manage applications, text telling using an application is disabled. -->
+ <string name="disabled">Disabled</string>
+ <!-- Summary of app trusted to install apps [CHAR LIMIT=45] -->
+ <string name="external_source_trusted">Allowed</string>
+ <!-- Summary of app not trusted to install apps [CHAR LIMIT=45] -->
+ <string name="external_source_untrusted">Not allowed</string>
+
+ <!-- Title for settings screen for controlling apps that can install other apps on device [CHAR LIMIT=50] -->
+ <string name="install_other_apps">Install unknown apps</string>
+
<!-- Option in navigation drawer that leads to Settings main screen [CHAR LIMIT=30] -->
<string name="home">Settings Home</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java b/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java
index 82da9a3..e4e0f7f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java
@@ -26,13 +26,13 @@
private int mLastDensity;
public InterestingConfigChanges() {
- this(0);
+ this(ActivityInfo.CONFIG_LOCALE
+ | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_SCREEN_LAYOUT
+ | ActivityInfo.CONFIG_ASSETS_PATHS);
}
- public InterestingConfigChanges(int extraFlags) {
- mFlags = extraFlags | ActivityInfo.CONFIG_LOCALE
- | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_SCREEN_LAYOUT
- | ActivityInfo.CONFIG_ASSETS_PATHS;
+ public InterestingConfigChanges(int flags) {
+ mFlags = flags;
}
public boolean applyNewConfig(Resources res) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index b3565ea..623d1a6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -335,6 +335,7 @@
if (security != SECURITY_NONE) {
builder.append(',').append(securityToString(security, pskType));
}
+ builder.append(",mRssi=").append(mRssi);
builder.append(",level=").append(getLevel());
if (mRankingScore != Integer.MIN_VALUE) {
builder.append(",rankingScore=").append(mRankingScore);
@@ -745,8 +746,12 @@
visibility.append(" rssi=").append(mInfo.getRssi());
visibility.append(" ");
visibility.append(" score=").append(mInfo.score);
- visibility.append(" rankingScore=").append(getRankingScore());
- visibility.append(" badge=").append(getBadge());
+ if (mRankingScore != Integer.MIN_VALUE) {
+ visibility.append(" rankingScore=").append(getRankingScore());
+ }
+ if (mBadge != NetworkBadging.BADGING_NONE) {
+ visibility.append(" badge=").append(getBadge());
+ }
visibility.append(String.format(" tx=%.1f,", mInfo.txSuccessRate));
visibility.append(String.format("%.1f,", mInfo.txRetriesRate));
visibility.append(String.format("%.1f ", mInfo.txBadRate));
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java
new file mode 100644
index 0000000..159b2a1
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.settingslib.wifi;
+
+import android.content.Context;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.net.wifi.hotspot2.PasspointConfiguration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provide utility functions for retrieving saved Wi-Fi configurations.
+ */
+public class WifiSavedConfigUtils {
+ /**
+ * Returns all the saved configurations on the device, including both Wi-Fi networks and
+ * Passpoint profiles, represented by {@link AccessPoint}.
+ *
+ * @param context The application context
+ * @param wifiManager An instance of {@link WifiManager}
+ * @return List of {@link AccessPoint}
+ */
+ public static List<AccessPoint> getAllConfigs(Context context, WifiManager wifiManager) {
+ List<AccessPoint> savedConfigs = new ArrayList<>();
+ List<WifiConfiguration> savedNetworks = wifiManager.getConfiguredNetworks();
+ for (WifiConfiguration network : savedNetworks) {
+ // Configuration for Passpoint network is configured temporary by WifiService for
+ // connection attempt only. The underlying configuration is saved as Passpoint
+ // configuration, which will be retrieved with WifiManager#getPasspointConfiguration
+ // call below.
+ if (network.isPasspoint()) {
+ continue;
+ }
+ // Ephemeral networks are not saved to the persistent storage, ignore them.
+ if (network.isEphemeral()) {
+ continue;
+ }
+ savedConfigs.add(new AccessPoint(context, network));
+ }
+ try {
+ List<PasspointConfiguration> savedPasspointConfigs =
+ wifiManager.getPasspointConfigurations();
+ for (PasspointConfiguration config : savedPasspointConfigs) {
+ savedConfigs.add(new AccessPoint(context, config));
+ }
+ } catch (UnsupportedOperationException e) {
+ // Passpoint not supported.
+ }
+ return savedConfigs;
+ }
+}
+
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 7a63b8a..40a59cf 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -95,8 +95,6 @@
private WifiTrackerNetworkCallback mNetworkCallback;
- private int mNumSavedNetworks;
-
@GuardedBy("mLock")
private boolean mRegistered;
@@ -138,8 +136,6 @@
private final NetworkScoreManager mNetworkScoreManager;
private final WifiNetworkScoreCache mScoreCache;
- private boolean mNetworkScoringUiEnabled;
- private final ContentObserver mObserver;
@GuardedBy("mLock")
private final Set<NetworkKey> mRequestedScores = new ArraySet<>();
@@ -227,16 +223,6 @@
updateNetworkScores();
}
});
-
- mObserver = new ContentObserver(mWorkHandler) {
- @Override
- public void onChange(boolean selfChange) {
- mNetworkScoringUiEnabled =
- Settings.Global.getInt(
- mContext.getContentResolver(),
- Settings.Global.NETWORK_SCORING_UI_ENABLED, 0) == 1;
- }
- };
}
/**
@@ -310,12 +296,6 @@
synchronized (mLock) {
registerScoreCache();
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.NETWORK_SCORING_UI_ENABLED),
- false /* notifyForDescendants */,
- mObserver);
- mObserver.onChange(false /* selfChange */); // Set mScoringUiEnabled
-
resumeScanning();
if (!mRegistered) {
mContext.registerReceiver(mReceiver, mFilter);
@@ -362,7 +342,6 @@
}
unregisterAndClearScoreCache();
pauseScanning();
- mContext.getContentResolver().unregisterContentObserver(mObserver);
mWorkHandler.removePendingMessages();
mMainHandler.removePendingMessages();
@@ -399,9 +378,11 @@
/**
* Returns the number of saved networks on the device, regardless of whether the WifiTracker
* is tracking saved networks.
+ * TODO(b/62292448): remove this function and update callsites to use WifiSavedConfigUtils
+ * directly.
*/
public int getNumSavedNetworks() {
- return mNumSavedNetworks;
+ return WifiSavedConfigUtils.getAllConfigs(mContext, mWifiManager).size();
}
public boolean isConnected() {
@@ -499,12 +480,10 @@
final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
if (configs != null) {
- mNumSavedNetworks = 0;
for (WifiConfiguration config : configs) {
if (config.selfAdded && config.numAssociation == 0) {
continue;
}
- mNumSavedNetworks++;
AccessPoint accessPoint = getCachedOrCreate(config, cachedAccessPoints);
if (mLastInfo != null && mLastNetworkInfo != null) {
accessPoint.update(connectionConfig, mLastInfo, mLastNetworkInfo);
@@ -582,7 +561,7 @@
requestScoresForNetworkKeys(scoresToRequest);
for (AccessPoint ap : accessPoints) {
- ap.update(mScoreCache, mNetworkScoringUiEnabled);
+ ap.update(mScoreCache, false /* mNetworkScoringUiEnabled */);
}
// Pre-sort accessPoints to speed preference insertion
@@ -680,7 +659,7 @@
updated = true;
if (previouslyConnected != ap.isActive()) reorder = true;
}
- if (ap.update(mScoreCache, mNetworkScoringUiEnabled)) {
+ if (ap.update(mScoreCache, false /* mNetworkScoringUiEnabled */)) {
reorder = true;
updated = true;
}
@@ -703,7 +682,8 @@
synchronized (mLock) {
boolean updated = false;
for (int i = 0; i < mInternalAccessPoints.size(); i++) {
- if (mInternalAccessPoints.get(i).update(mScoreCache, mNetworkScoringUiEnabled)) {
+ if (mInternalAccessPoints.get(i).update(
+ mScoreCache, false /* mNetworkScoringUiEnabled */)) {
updated = true;
}
}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index d4ce40c..c526432 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -410,6 +410,7 @@
validConfig.BSSID = BSSID_1;
WifiConfiguration selfAddedNoAssociation = new WifiConfiguration();
+ selfAddedNoAssociation.ephemeral = true;
selfAddedNoAssociation.selfAdded = true;
selfAddedNoAssociation.numAssociation = 0;
selfAddedNoAssociation.SSID = SSID_2;
@@ -472,7 +473,7 @@
}
@Test
- public void scoreCacheUpdateScoresShouldChangeSortOrder() throws InterruptedException {
+ public void scoreCacheUpdateScoresShouldNotChangeSortOrder() throws InterruptedException {
WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
List<AccessPoint> aps = tracker.getAccessPoints();
assertTrue(aps.size() == 2);
@@ -483,8 +484,8 @@
aps = tracker.getAccessPoints();
assertTrue(aps.size() == 2);
- assertEquals(aps.get(0).getSsidStr(), SSID_2);
- assertEquals(aps.get(1).getSsidStr(), SSID_1);
+ assertEquals(aps.get(0).getSsidStr(), SSID_1);
+ assertEquals(aps.get(1).getSsidStr(), SSID_2);
}
@Test
@@ -510,7 +511,8 @@
}
@Test
- public void scoreCacheUpdateScoresShouldInsertBadgeIntoAccessPoint() throws InterruptedException {
+ public void scoreCacheUpdateScoresShouldNotInsertBadgeIntoAccessPoint()
+ throws InterruptedException {
WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
updateScoresAndWaitForAccessPointsChangedCallback();
@@ -518,9 +520,9 @@
for (AccessPoint ap : aps) {
if (ap.getSsidStr().equals(SSID_1)) {
- assertEquals(BADGE_1, ap.getBadge());
+ assertEquals(NetworkBadging.BADGING_NONE, ap.getBadge());
} else if (ap.getSsidStr().equals(SSID_2)) {
- assertEquals(BADGE_2, ap.getBadge());
+ assertEquals(NetworkBadging.BADGING_NONE, ap.getBadge());
}
}
}
@@ -746,4 +748,4 @@
verifyNoMoreInteractions(mockWifiListener);
}
-}
\ No newline at end of file
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 455d9cb..f5d7dd8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2212,11 +2212,7 @@
throw new IllegalStateException("Key is corrupted", e);
}
- // Mac the package name and each of the signatures.
- final String packageName = callingPkg.packageName;
- byte[] packageNameBytes = packageName.getBytes(StandardCharsets.UTF_8);
- m.update(getLengthPrefix(packageNameBytes), 0, 4);
- m.update(packageNameBytes);
+ // Mac each of the developer signatures.
for (int i = 0; i < callingPkg.signatures.length; i++) {
byte[] sig = callingPkg.signatures[i].toByteArray();
m.update(getLengthPrefix(sig), 0, 4);
@@ -2231,7 +2227,7 @@
final String uid = Integer.toString(callingPkg.applicationInfo.uid);
final SettingsState ssaidSettings = getSettingsLocked(SETTINGS_TYPE_SSAID, userId);
final boolean success = ssaidSettings.insertSettingLocked(uid, ssaid, null, true,
- packageName);
+ callingPkg.packageName);
if (!success) {
throw new IllegalStateException("Ssaid settings not accessible");
diff --git a/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml b/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml
index 3fb86d0..1b6fa4c 100644
--- a/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml
@@ -16,5 +16,5 @@
-->
<resources>
- <dimen name="widget_big_font_size">64dp</dimen>
+ <dimen name="widget_big_font_size">72dp</dimen>
</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml b/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml
index 3fb86d0..1b6fa4c 100644
--- a/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml
@@ -16,5 +16,5 @@
-->
<resources>
- <dimen name="widget_big_font_size">64dp</dimen>
+ <dimen name="widget_big_font_size">72dp</dimen>
</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 3ca6e69..41c723e 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -41,7 +41,7 @@
<!-- Default clock parameters -->
<dimen name="bottom_text_spacing_digital">-1dp</dimen>
<dimen name="widget_label_font_size">14sp</dimen>
- <dimen name="widget_big_font_size">64dp</dimen>
+ <dimen name="widget_big_font_size">72dp</dimen>
<!-- The y translation to apply at the start in appear animations. -->
<dimen name="appear_y_translation_start">32dp</dimen>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 66c5dd5..97376c3 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -35,7 +35,7 @@
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="24dp"
+ android:layout_height="32dp"
android:layout_alignParentEnd="true"
android:clipChildren="false"
android:clipToPadding="false"
diff --git a/packages/SystemUI/res/layout/status_bar_alarm_group.xml b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
index 78b580f..3528f9e 100644
--- a/packages/SystemUI/res/layout/status_bar_alarm_group.xml
+++ b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
@@ -30,7 +30,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
- android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
+ android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
android:textSize="@dimen/qs_time_collapsed_size"
android:gravity="center_vertical"
systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 3fce776..32f3ca5 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minute"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minute"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 uur"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 uur"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ONTDOEN"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Sluimer vir <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Batterygebruik"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 1c1fbbc..8281bf9 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -589,8 +589,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"١٥ دقيقة"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"٣۰ دقيقة"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"ساعة واحدة"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"ساعتان"</string>
<string name="snooze_undo" msgid="6074877317002985129">"تراجع"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"تم تأجيل الإشعار لمدة <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"استخدام البطارية"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 24b71e7..40bd32a 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 dəqiqə"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 dəqiqə"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 saat"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 saat"</string>
<string name="snooze_undo" msgid="6074877317002985129">"GERİ QAYTARIN"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> üçün təxirə salınıb"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Batareya istifadəsi"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index f460730..6e27760 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -577,8 +577,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuta"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minuta"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 sat"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 sata"</string>
<string name="snooze_undo" msgid="6074877317002985129">"OPOZOVI"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Odloženo je za <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Potrošnja baterije"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index dfad96c..1096141 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -583,8 +583,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 хвілін"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 хвілін"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 гадзіна"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 гадзіны"</string>
<string name="snooze_undo" msgid="6074877317002985129">"АДРАБІЦЬ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Адкладзена на <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Выкарыстанне зараду"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index be327135..00a1a17 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 минути"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 минути"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 час"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 часа"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ОТМЯНА"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Отложено за <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Ползв. на батерията"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 822652b..65ea6b1 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"১৫ মিনিট"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"৩০ মিনিট"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"১ ঘণ্টা"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"২ ঘণ্টা"</string>
<string name="snooze_undo" msgid="6074877317002985129">"পূর্বাবস্থায় ফিরুন"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> পরে আবার মনে করানো হবে"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ব্যাটারির ব্যবহার"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index e4e02d7..e420ae3 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -579,8 +579,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuta"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minuta"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 sat"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 sata"</string>
<string name="snooze_undo" msgid="6074877317002985129">"OPOZOVI"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Odgođeno za <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Potrošnja baterije"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index c9254ef..d8292ec 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -62,7 +62,7 @@
<string name="always_use_accessory" msgid="1210954576979621596">"Utilitza de manera predet. per a l\'accessori USB"</string>
<string name="usb_debugging_title" msgid="4513918393387141949">"Vols permetre la depuració USB?"</string>
<string name="usb_debugging_message" msgid="2220143855912376496">"L\'empremta digital de la clau de l\'RSA de l\'equip és:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
- <string name="usb_debugging_always" msgid="303335496705863070">"Dóna sempre permís des d\'aquest equip"</string>
+ <string name="usb_debugging_always" msgid="303335496705863070">"Dona sempre permís des d\'aquest equip"</string>
<string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"No es permet la depuració USB"</string>
<string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"L\'usuari que té iniciada la sessió al dispositiu en aquest moment no pot activar la depuració USB. Per utilitzar aquesta funció, cal canviar a l\'usuari administrador."</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Zoom per omplir pantalla"</string>
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuts"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minuts"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 hores"</string>
<string name="snooze_undo" msgid="6074877317002985129">"DESFÉS"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"S\'ha posposat <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Ús de la bateria"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 2ad9dba..84ee9ee 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -583,8 +583,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minut"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minut"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hodina"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 hodiny"</string>
<string name="snooze_undo" msgid="6074877317002985129">"VRÁTIT ZPĚT"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Odloženo o <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Využití baterie"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index e2852dd..3fb7acf 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutter"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutter"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 time"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 timer"</string>
<string name="snooze_undo" msgid="6074877317002985129">"FORTRYD"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Udsat i <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Batteriforbrug"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index b0b4323..0697ead 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 Minuten"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 Minuten"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 Stunde"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 Stunden"</string>
<string name="snooze_undo" msgid="6074877317002985129">"RÜCKGÄNGIG"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Erinnerung in <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Akkunutzung"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 5d87034..094fd84 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 λεπτά"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 λεπτά"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ώρα"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ώρες"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ΑΝΑΙΡΕΣΗ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Σε αφύπνιση για <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Χρήση της μπαταρίας"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 05c4130..35263c2 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutes"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutes"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hour"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 hours"</string>
<string name="snooze_undo" msgid="6074877317002985129">"UNDO"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Snoozed for <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 05c4130..35263c2 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutes"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutes"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hour"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 hours"</string>
<string name="snooze_undo" msgid="6074877317002985129">"UNDO"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Snoozed for <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 05c4130..35263c2 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutes"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutes"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hour"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 hours"</string>
<string name="snooze_undo" msgid="6074877317002985129">"UNDO"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Snoozed for <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 07b564d..3b77658 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 horas"</string>
<string name="snooze_undo" msgid="6074877317002985129">"DESHACER"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Posponer <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Uso de la batería"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 3bf6a8c..adba00a 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 horas"</string>
<string name="snooze_undo" msgid="6074877317002985129">"DESHACER"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Volverá a mostrarse en <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Uso de la batería"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 26b4603..f4605e0 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutit"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutit"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"Üks tund"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"kaks tundi"</string>
<string name="snooze_undo" msgid="6074877317002985129">"VÕTA TAGASI"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Edasi lükatud <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Akukasutus"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 86fd3b2..1919df3 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutu"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutu"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ordu"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ordu"</string>
<string name="snooze_undo" msgid="6074877317002985129">"DESEGIN"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g>z atzeratu da"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Bateriaren erabilera"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 5570f9e..b16ff8e 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"۱۵ دقیقه"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"۳۰ دقیقه"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"۱ ساعت"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"۲ ساعت"</string>
<string name="snooze_undo" msgid="6074877317002985129">"واگرد"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> به تعویق افتاد"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"مصرف باتری"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index c60c4c4..f4e5616 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuuttia"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minuuttia"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 tunti"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 tuntia"</string>
<string name="snooze_undo" msgid="6074877317002985129">"KUMOA"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Torkku: <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Akun käyttö"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 10b0cba..827958c 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutes"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutes"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 heure"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 heures"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ANNULER"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Reporté pour <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Utilisation de la pile"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 862d13f..e78c892 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutes"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutes"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 heure"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 heures"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ANNULER"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Répétée après <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Utilisation batterie"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 0cb91b4..3cd4e71 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 horas"</string>
<string name="snooze_undo" msgid="6074877317002985129">"DESFACER"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Adiouse <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Uso de batería"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 7f718d9..2cb19ed 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 મિનિટ"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 મિનિટ"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 કલાક"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 કલાક"</string>
<string name="snooze_undo" msgid="6074877317002985129">"પૂર્વવત્ કરો"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> માટે સ્નૂઝ કરો"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"બૅટરી વપરાશ"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 613d8d3..e5c013f 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 मिनट"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 मिनट"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 घंटा"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 घंटे"</string>
<string name="snooze_undo" msgid="6074877317002985129">"पहले जैसा करें"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> के लिए याद दिलाया गया"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"बैटरी उपयोग"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index e716f5d..e71a6a6 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -577,8 +577,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuta"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minuta"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 sat"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 sata"</string>
<string name="snooze_undo" msgid="6074877317002985129">"PONIŠTI"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Odgođeno <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Potrošnja baterije"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index fe1b12b..05dd386 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 perc"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 perc"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 óra"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 óra"</string>
<string name="snooze_undo" msgid="6074877317002985129">"VISSZAVONÁS"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Elhalasztva: <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Akkumulátorhasználat"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index bdceafe..12c4b60 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 րոպե"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 րոպե"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ժամ"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ժամ"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ՀԵՏԱՐԿԵԼ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Հետաձգվել է <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>ով"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Մարտկոցի օգտագործում"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 2853d9d..5f72bb2 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 menit"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 menit"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 jam"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 jam"</string>
<string name="snooze_undo" msgid="6074877317002985129">"URUNG"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Ditunda selama <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Pemakaian baterai"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index f56720a..ce665e2 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 mínútur"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 mínútur"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 klukkustund"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 klukkustundir"</string>
<string name="snooze_undo" msgid="6074877317002985129">"AFTURKALLA"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Þaggað í <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Rafhlöðunotkun"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index cfe5deb..5ff02b0 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuti"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minuti"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ora"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ore"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ANNULLA"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Posticipato di <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Utilizzo batteria"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 4b1236e..b3a8146 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -581,8 +581,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 דקות"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 דקות"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"שעה אחת"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"שעתיים"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ביטול"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"נדחה לטיפול בעוד <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"שימוש בסוללה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 4c7c85e..f63af80 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15分"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30分"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1時間"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2時間"</string>
<string name="snooze_undo" msgid="6074877317002985129">"元に戻す"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"スヌーズ: <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"電池の使用状況"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index d8cbc19..5efe0ab 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 წუთი"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 წუთი"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 საათი"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 საათი"</string>
<string name="snooze_undo" msgid="6074877317002985129">"მოქმედების გაუქმება"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"ჩაჩუმებული იქნება <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ბატარეის მოხმარება"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index f71601e..9478a96 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 минут"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 минут"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 сағат"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 сағат"</string>
<string name="snooze_undo" msgid="6074877317002985129">"КЕРІ ҚАЙТАРУ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> кідіртілді"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Батареяны пайдалану"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 9aed689..6954d2b 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 នាទី"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 នាទី"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ម៉ោង"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ម៉ោង"</string>
<string name="snooze_undo" msgid="6074877317002985129">"មិនធ្វើវិញ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"បានផ្អាករយៈពេល <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ការប្រើប្រាស់ថ្ម"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index cd85f74..096416e 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 ನಿಮಿಷಗಳು"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 ನಿಮಿಷಗಳು"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ಗಂಟೆ"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ಗಂಟೆಗಳು"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ರದ್ದುಮಾಡಿ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ಗೆ ಸ್ನೂಜ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ಬ್ಯಾಟರಿ ಬಳಕೆ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index a237ba9..cf5fc2c 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15분"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30분"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1시간"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2시간"</string>
<string name="snooze_undo" msgid="6074877317002985129">"실행취소"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> 동안 일시 중지됨"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"배터리 사용량"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 1127c24..aceb1c2 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 мүнөт"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 мүнөт"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 саат"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 саат"</string>
<string name="snooze_undo" msgid="6074877317002985129">"КАЙТАРУУ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> тындырылды"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Батарея колдонулушу"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 42baec6..d7f1200 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 ນາທີ"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 ນາທີ"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ຊົ່ວໂມງ"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ຊົ່ວໂມງ"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ຍົກເລີກ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"ເລື່ອນໄປ <xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ນາທີແລ້ວ"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ການໃຊ້ແບັດເຕີຣີ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index ce403ef..8b03861 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -581,8 +581,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 min."</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 min."</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 val."</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 val."</string>
<string name="snooze_undo" msgid="6074877317002985129">"ANULIUOTI"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Nustatyta snausti <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Akum. energ. vartoj."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 28758ca..26f4370 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -577,8 +577,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minūtes"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minūtes"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 stunda"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 stundas"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ATSAUKT"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Atlikts: <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Akumulatora lietojums"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 3355090..4d4e227 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 минути"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 минути"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 час"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 часа"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ВРАТИ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Одложено за <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Користење батерија"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index a41e305..67d7404 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 മിനിറ്റ്"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 മിനിറ്റ്"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"ഒരു മണിക്കൂർ"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 മണിക്കൂർ"</string>
<string name="snooze_undo" msgid="6074877317002985129">"പഴയപടിയാക്കുക"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> സമയത്തേക്ക് സ്നൂസ് ചെയ്തു"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ബാറ്ററി ഉപയോഗം"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 3a33cd6..ea5ab82 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 минут"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 минут"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 цаг"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 цаг"</string>
<string name="snooze_undo" msgid="6074877317002985129">"БУЦААХ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g>-д түр хойшлуулсан"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Тэжээл ашиглалт"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index ad107d8..fd6b0c3 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 मिनिटे"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 मिनिटे"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 तास"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 तास"</string>
<string name="snooze_undo" msgid="6074877317002985129">"पूर्ववत करा"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> साठी स्नूझ करा"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"बॅटरी वापर"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 898cdfc..46fcf43 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minit"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minit"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 jam"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 jam"</string>
<string name="snooze_undo" msgid="6074877317002985129">"BUAT ASAL"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Ditunda selama <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Penggunaan bateri"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 346bbe2..dd7e923 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"၁၅ မိနစ်"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"၃၀ မိနစ်"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"၁ နာရီ"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"၂ နာရီ"</string>
<string name="snooze_undo" msgid="6074877317002985129">"တစ်ဆင့် နောက်ပြန်ပြန်ပါ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ဆိုင်းငံ့ရန်"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ဘက်ထရီ အသုံးပြုမှု"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index a13c097..3fdc266 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutter"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutter"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 time"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 timer"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ANGRE"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Slumrer i <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Batteribruk"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index c8cd383..038587e 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"१५ मिनेट"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"३० मिनेट"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"१ घन्टा"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"२ घन्टा"</string>
<string name="snooze_undo" msgid="6074877317002985129">"अनडू गर्नुहोस्"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> का लागि स्नुज गरियो"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ब्याट्री उपयोग"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 78077e9..040f0a8 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuten"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minuten"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 uur"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 uur"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ONGEDAAN MAKEN"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Snoozefunctie <xliff:g id="TIME_AMOUNT">%1$s</xliff:g> actief"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Accugebruik"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 07a0e82..12b1dcb 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 ਮਿੰਟ"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 ਮਿੰਟ"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ਘੰਟਾ"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ਘੰਟੇ"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ਅਣਕੀਤਾ ਕਰੋ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ਲਈ ਸਨੂਜ਼ ਕੀਤਾ ਗਿਆ"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ਬੈਟਰੀ ਵਰਤੋਂ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 03b5ed9..fd59150 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -581,8 +581,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 min"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 min"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 godz."</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 godziny"</string>
<string name="snooze_undo" msgid="6074877317002985129">"COFNIJ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Odłożono na <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Wykorzystanie baterii"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 8ef330b..7cd023c 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"Uma hora"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 horas"</string>
<string name="snooze_undo" msgid="6074877317002985129">"DESFAZER"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Adiada para <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Uso da bateria"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 49f1480..fe0859e 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 horas"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ANULAR"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Suspensa por <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Utiliz. da bateria"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 8ef330b..7cd023c 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"Uma hora"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 horas"</string>
<string name="snooze_undo" msgid="6074877317002985129">"DESFAZER"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Adiada para <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Uso da bateria"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 29bc5bf..3fd6b9b 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -579,8 +579,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minute"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 de minute"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 oră"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ore"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ANULAȚI"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Amânată <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Utilizarea bateriei"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index e593f89..2fa3ad2 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -583,8 +583,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 минут"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 минут"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 час"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 часа"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ОТМЕНИТЬ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Отложено на <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Уровень заряда"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 991be52..c8865ae 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"මිනිත්තු 15"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"මිනිත්තු 30"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"පැය 1"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"පැය 2"</string>
<string name="snooze_undo" msgid="6074877317002985129">"අස් කරන්න"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g>ක් මදක් නතර කරන ලදී"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"බැටරි භාවිතය"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 33793ce..9d5eb79 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -583,8 +583,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minút"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minút"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hod."</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 hodiny"</string>
<string name="snooze_undo" msgid="6074877317002985129">"SPÄŤ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Stlmené na <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Využitie batérie"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 9e03e42..8289516 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -583,8 +583,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minut"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minut"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ura"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 uri"</string>
<string name="snooze_undo" msgid="6074877317002985129">"RAZVELJAVI"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Preloženo za <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Poraba akumulatorja"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index cbdb5b2..15cc542 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuta"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minuta"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 orë"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 orë"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ZHBËJ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"U shty për <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Përdorimi i baterisë"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 5c47907..4ef7267 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -577,8 +577,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 минута"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 минута"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 сат"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 сата"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ОПОЗОВИ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Одложено је за <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Потрошња батерије"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 967e3a5..a479bea 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuter"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minuter"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 timme"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 timmar"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ÅNGRA"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Snoozad i <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Batteriförbrukning"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 8222074..adbf29b 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"Dakika 15"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"Dakika 30"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"Saa 1"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"Saa 2"</string>
<string name="snooze_undo" msgid="6074877317002985129">"TENDUA"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Imeahirishwa kwa <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Matumizi ya betri"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index eb672e1..ea75cec 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 நிமிடங்கள்"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 நிமிடங்கள்"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 மணிநேரம்"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 மணிநேரம்"</string>
<string name="snooze_undo" msgid="6074877317002985129">"செயல்தவிர்"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"உறக்கநிலையில் வைத்திருந்த நேரம்: <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"பேட்டரி உபயோகம்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index b5470e7..97763d4 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 నిమిషాలు"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 నిమిషాలు"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 గంట"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 గంటలు"</string>
<string name="snooze_undo" msgid="6074877317002985129">"చర్య రద్దు చేయి"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> వరకు తాత్కాలికంగా ఆపివేయబడింది"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"బ్యాటరీ వినియోగం"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index f47cfa9..28957c5 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 นาที"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 นาที"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ชั่วโมง"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ชั่วโมง"</string>
<string name="snooze_undo" msgid="6074877317002985129">"เลิกทำ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"ปิดเสียงเตือนชั่วคราวไว้เป็นเวลา <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"การใช้งานแบตเตอรี่"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 3304ab7..4788a0e 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuto"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minuto"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 oras"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 oras"</string>
<string name="snooze_undo" msgid="6074877317002985129">"I-UNDO"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Na-snooze ng <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Paggamit ng baterya"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 944316c..903f2c8 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 dakika"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 dakika"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 saat"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 saat"</string>
<string name="snooze_undo" msgid="6074877317002985129">"GERİ AL"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> süreyle ertelendi"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Pil kullanımı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 5636a87..937822c 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -583,8 +583,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 хвилин"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 хвилин"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 годину"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 години"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ВІДМІНИТИ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Відкладено на <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Використання заряду"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 7a5f1c7..23a0626 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 منٹ"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 منٹ"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 گھنٹہ"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 گھنٹے"</string>
<string name="snooze_undo" msgid="6074877317002985129">"کالعدم کریں"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> کیلئے اسنوز کیا گیا"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"بیٹری کا استعمال"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 262225c..530b317 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 daqiqa"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 daqiqa"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 soat"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 soat"</string>
<string name="snooze_undo" msgid="6074877317002985129">"BEKOR QILISH"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> muddatga kechiktirildi"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Batareya sarfi"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 1d125f6..29c70c6 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 phút"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 phút"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 giờ"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 giờ"</string>
<string name="snooze_undo" msgid="6074877317002985129">"HOÀN TÁC"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Báo lại sau <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Mức sử dụng pin"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 600e17d..33dc240 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 分钟"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 分钟"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 小时"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 小时"</string>
<string name="snooze_undo" msgid="6074877317002985129">"撤消"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"已延后 <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"电池使用情况"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 109c33e..cab3aea 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -575,8 +575,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 分鐘"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 分鐘"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 小時"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 小時"</string>
<string name="snooze_undo" msgid="6074877317002985129">"復原"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"已延後 <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"電池用量"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 353d985..9526426 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 分鐘"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 分鐘"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 小時"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 小時"</string>
<string name="snooze_undo" msgid="6074877317002985129">"復原"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"已延後 <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"電池用量"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index d81c320..80ce905 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -573,8 +573,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 amaminithi"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 amaminithi"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ihora"</string>
- <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
- <skip />
+ <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 amahora"</string>
<string name="snooze_undo" msgid="6074877317002985129">"HLEHLISA"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Kusnuzwe u-<xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Ukusetshenziswa kwebhethri"</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 44da876..d98b789 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -155,16 +155,16 @@
<style name="TextAppearance.StatusBar.Expanded.Clock">
<item name="android:textSize">@dimen/qs_time_expanded_size</item>
- <item name="android:fontFamily">sans-serif-condensed</item>
+ <item name="android:fontFamily">sans-serif-medium</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:textStyle">normal</item>
</style>
<style name="TextAppearance.StatusBar.Expanded.Date">
- <item name="android:textSize">@dimen/qs_date_collapsed_size</item>
+ <item name="android:textSize">@dimen/qs_time_expanded_size</item>
<item name="android:textStyle">normal</item>
- <item name="android:textColor">?android:attr/textColorSecondary</item>
- <item name="android:fontFamily">sans-serif-condensed</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:fontFamily">sans-serif</item>
</style>
<style name="TextAppearance.StatusBar.Expanded.AboveDateTime">
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 0cf8ff0..8ba33c3 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -264,6 +264,9 @@
mProviders.put(AccessibilityManagerWrapper.class,
() -> new AccessibilityManagerWrapper(mContext));
+ mProviders.put(ForegroundServiceController.class,
+ () -> new ForegroundServiceControllerImpl(mContext));
+
mProviders.put(UiOffloadThread.class, UiOffloadThread::new);
// Put all dependencies above here so the factory can override them if it wants.
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
new file mode 100644
index 0000000..a2c9ab4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.service.notification.StatusBarNotification;
+
+public interface ForegroundServiceController {
+ /**
+ * @param sbn notification that was just posted
+ * @param importance
+ */
+ void addNotification(StatusBarNotification sbn, int importance);
+
+ /**
+ * @param sbn notification that was just changed in some way
+ * @param newImportance
+ */
+ void updateNotification(StatusBarNotification sbn, int newImportance);
+
+ /**
+ * @param sbn notification that was just canceled
+ */
+ boolean removeNotification(StatusBarNotification sbn);
+
+ /**
+ * @param userId
+ * @return true if this user has services missing notifications and therefore needs a
+ * disclosure notification.
+ */
+ boolean isDungeonNeededForUser(int userId);
+
+ /**
+ * @param sbn
+ * @return true if sbn is the system-provided "dungeon" (list of running foreground services).
+ */
+ boolean isDungeonNotification(StatusBarNotification sbn);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
new file mode 100644
index 0000000..c930d56
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.service.notification.StatusBarNotification;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto;
+
+import java.util.Arrays;
+
+/**
+ * Foreground service controller, a/k/a Dianne's Dungeon.
+ */
+public class ForegroundServiceControllerImpl
+ implements ForegroundServiceController {
+ private static final String TAG = "FgServiceController";
+ private static final boolean DBG = false;
+
+ private final SparseArray<UserServices> mUserServices = new SparseArray<>();
+ private final Object mMutex = new Object();
+
+ public ForegroundServiceControllerImpl(Context context) {
+ }
+
+ @Override
+ public boolean isDungeonNeededForUser(int userId) {
+ synchronized (mMutex) {
+ final UserServices services = mUserServices.get(userId);
+ if (services == null) return false;
+ return services.isDungeonNeeded();
+ }
+ }
+
+ @Override
+ public void addNotification(StatusBarNotification sbn, int importance) {
+ updateNotification(sbn, importance);
+ }
+
+ @Override
+ public boolean removeNotification(StatusBarNotification sbn) {
+ synchronized (mMutex) {
+ final UserServices userServices = mUserServices.get(sbn.getUserId());
+ if (userServices == null) {
+ if (DBG) {
+ Log.w(TAG, String.format(
+ "user %d with no known notifications got removeNotification for %s",
+ sbn.getUserId(), sbn));
+ }
+ return false;
+ }
+ if (isDungeonNotification(sbn)) {
+ // if you remove the dungeon entirely, we take that to mean there are
+ // no running services
+ userServices.setRunningServices(null);
+ return true;
+ } else {
+ // this is safe to call on any notification, not just FLAG_FOREGROUND_SERVICE
+ return userServices.removeNotification(sbn.getPackageName(), sbn.getKey());
+ }
+ }
+ }
+
+ @Override
+ public void updateNotification(StatusBarNotification sbn, int newImportance) {
+ synchronized (mMutex) {
+ UserServices userServices = mUserServices.get(sbn.getUserId());
+ if (userServices == null) {
+ userServices = new UserServices();
+ mUserServices.put(sbn.getUserId(), userServices);
+ }
+
+ if (isDungeonNotification(sbn)) {
+ final Bundle extras = sbn.getNotification().extras;
+ if (extras != null) {
+ final String[] svcs = extras.getStringArray(Notification.EXTRA_FOREGROUND_APPS);
+ userServices.setRunningServices(svcs); // null ok
+ }
+ } else {
+ userServices.removeNotification(sbn.getPackageName(), sbn.getKey());
+ if (0 != (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE)
+ && newImportance > NotificationManager.IMPORTANCE_MIN) {
+ userServices.addNotification(sbn.getPackageName(), sbn.getKey());
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean isDungeonNotification(StatusBarNotification sbn) {
+ return sbn.getId() == SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES
+ && sbn.getTag() == null
+ && sbn.getPackageName().equals("android");
+ }
+
+ /**
+ * Struct to track relevant packages and notifications for a userid's foreground services.
+ */
+ private static class UserServices {
+ private String[] mRunning = null;
+ private ArrayMap<String, ArraySet<String>> mNotifications = new ArrayMap<>(1);
+ public void setRunningServices(String[] pkgs) {
+ mRunning = pkgs != null ? Arrays.copyOf(pkgs, pkgs.length) : null;
+ }
+ public void addNotification(String pkg, String key) {
+ if (mNotifications.get(pkg) == null) {
+ mNotifications.put(pkg, new ArraySet<String>());
+ }
+ mNotifications.get(pkg).add(key);
+ }
+ public boolean removeNotification(String pkg, String key) {
+ final boolean found;
+ final ArraySet<String> keys = mNotifications.get(pkg);
+ if (keys == null) {
+ found = false;
+ } else {
+ found = keys.remove(key);
+ if (keys.size() == 0) {
+ mNotifications.remove(pkg);
+ }
+ }
+ return found;
+ }
+ public boolean isDungeonNeeded() {
+ if (mRunning != null) {
+ for (String pkg : mRunning) {
+ final ArraySet<String> set = mNotifications.get(pkg);
+ if (set == null || set.size() == 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 09fdf5a..3b81cc4 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -92,7 +92,9 @@
mAssistDisclosure = new AssistDisclosure(context, new Handler());
registerVoiceInteractionSessionListener();
- mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION);
+ mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION
+ | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE
+ | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
onConfigurationChanged(context.getResources().getConfiguration());
}
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 8ac97f3..ee155d9 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -49,7 +49,8 @@
private final HashMap<String, ArrayList<FragmentListener>> mListeners = new HashMap<>();
private final View mRootView;
private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
- ActivityInfo.CONFIG_FONT_SCALE);
+ ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
+ | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
private final FragmentService mManager;
private final PluginFragmentManager mPlugins = new PluginFragmentManager();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 3532f41..2d5d198 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -194,6 +194,12 @@
mKeyguardViewMediator.startKeyguardExitAnimation(startTime, fadeoutDuration);
Trace.endSection();
}
+
+ @Override
+ public void onShortPowerPressedGoHome() {
+ checkPermission();
+ mKeyguardViewMediator.onShortPowerPressedGoHome();
+ }
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index b977dd4..f745956 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2013,6 +2013,10 @@
Trace.endSection();
}
+ public void onShortPowerPressedGoHome() {
+ // do nothing
+ }
+
public ViewMediatorCallback getViewMediatorCallback() {
return mViewMediatorCallback;
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 5414aad..f98310d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -239,7 +239,11 @@
}
}
- loadConfigurationsAndApply(mContext.getResources().getConfiguration());
+ // Initialize the last orientation and apply the current configuration
+ Configuration initialConfig = mContext.getResources().getConfiguration();
+ mLastOrientation = initialConfig.orientation;
+ loadConfigurationsAndApply(initialConfig);
+
mMediaSessionManager =
(MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index 682c56c..488fc03 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -18,12 +18,14 @@
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_DATE;
+import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
import android.os.UserManager;
@@ -42,6 +44,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.keyguard.KeyguardStatusView;
+import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
@@ -423,6 +426,13 @@
@Override
public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
+ if (picture != null &&
+ UserManager.get(mContext).isGuestUser(ActivityManager.getCurrentUser())) {
+ picture = picture.getConstantState().newDrawable().mutate();
+ picture.setColorFilter(
+ Utils.getColorAttr(mContext, android.R.attr.colorForeground),
+ Mode.SRC_IN);
+ }
mMultiUserAvatar.setImageDrawable(picture);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index ecbc4f7..9557262 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -140,7 +140,8 @@
if (mState.value) {
mController.setZen(ZEN_MODE_OFF, null, TAG);
} else {
- mController.setZen(ZEN_MODE_ALARMS, null, TAG);
+ int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS);
+ mController.setZen(zen, null, TAG);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 7697061..ba3bcc7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -514,6 +514,9 @@
RecentsActivityLaunchState launchState = config.getLaunchState();
launchState.reset();
}
+
+ // Force a gc to attempt to clean up bitmap references more quickly (b/38258699)
+ Recents.getSystemServices().gc();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index cbfa0e5..1f13830 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -362,6 +362,19 @@
}
/**
+ * Requests a gc() from the background thread.
+ */
+ public void gc() {
+ BackgroundThread.getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ System.gc();
+ System.runFinalization();
+ }
+ });
+ }
+
+ /**
* @return whether the provided {@param className} is blacklisted
*/
public boolean isBlackListedActivity(String className) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java
index 5e87e2a..716d1bc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java
@@ -54,7 +54,6 @@
public static final int FOCUS_STATE = 8;
private SparseLongArray mPropStartDelay;
- private SparseLongArray mPropInitialPlayTime;
private SparseLongArray mPropDuration;
private SparseArray<Interpolator> mPropInterpolators;
private Animator.AnimatorListener mListener;
@@ -122,10 +121,6 @@
animator.setStartDelay(getStartDelay(propertyType));
animator.setDuration(getDuration(propertyType));
animator.setInterpolator(getInterpolator(propertyType));
- long initialPlayTime = getInitialPlayTime(propertyType);
- if (initialPlayTime != 0) {
- animator.setCurrentPlayTime(initialPlayTime);
- }
return animator;
}
@@ -141,17 +136,6 @@
}
/**
- * Sets a initial play time for a specific property.
- */
- public AnimationProps setInitialPlayTime(@PropType int propertyType, int initialPlayTime) {
- if (mPropInitialPlayTime == null) {
- mPropInitialPlayTime = new SparseLongArray();
- }
- mPropInitialPlayTime.append(propertyType, initialPlayTime);
- return this;
- }
-
- /**
* Returns the start delay for a specific property.
*/
public long getStartDelay(@PropType int propertyType) {
@@ -217,20 +201,6 @@
}
/**
- * Returns the initial play time for a specific property, falling back to the general initial
- * play time if there is no specific property interpolator.
- */
- public long getInitialPlayTime(@PropType int propertyType) {
- if (mPropInitialPlayTime != null) {
- if (mPropInitialPlayTime.indexOfKey(propertyType) != -1) {
- return mPropInitialPlayTime.get(propertyType);
- }
- return mPropInitialPlayTime.get(ALL, 0);
- }
- return 0;
- }
-
- /**
* Sets an animator listener for this animation.
*/
public AnimationProps setListener(Animator.AnimatorListener listener) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java
new file mode 100644
index 0000000..e32da2d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.views;
+
+import android.view.animation.PathInterpolator;
+
+/**
+ * A helper interpolator to stagger the entrance animation in recents by offsetting the start time
+ */
+public class RecentsEntrancePathInterpolator extends PathInterpolator {
+ final float mStartOffsetFraction;
+
+ /**
+ * Create an interpolator for a cubic Bezier curve with an offset play time. The end points
+ * <code>(0, 0)</code> and <code>(1, 1)</code> are assumed.
+ *
+ * @param controlX1 The x coordinate of the first control point of the cubic Bezier.
+ * @param controlY1 The y coordinate of the first control point of the cubic Bezier.
+ * @param controlX2 The x coordinate of the second control point of the cubic Bezier.
+ * @param controlY2 The y coordinate of the second control point of the cubic Bezier.
+ * @param startOffsetFraction The fraction from 0 to 1 to start the animation from
+ */
+ public RecentsEntrancePathInterpolator(float controlX1, float controlY1, float controlX2,
+ float controlY2, float startOffsetFraction) {
+ super(controlX1, controlY1, controlX2, controlY2);
+ mStartOffsetFraction = startOffsetFraction;
+ }
+
+ @Override
+ public float getInterpolation(float t) {
+ return super.getInterpolation(t + mStartOffsetFraction);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index f1314aba..0fc68e6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -82,8 +82,6 @@
private static final int ENTER_FROM_HOME_ALPHA_DURATION = 100;
public static final int ENTER_FROM_HOME_TRANSLATION_DURATION = 300;
- private static final Interpolator ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR =
- Interpolators.LINEAR_OUT_SLOW_IN;
private static final Interpolator ENTER_FROM_HOME_ALPHA_INTERPOLATOR = Interpolators.LINEAR;
public static final int EXIT_TO_HOME_TRANSLATION_DURATION = 200;
@@ -260,17 +258,18 @@
} else if (launchState.launchedFromHome) {
// Animate the tasks up, but offset the animations to be relative to the front-most
// task animation
+ final float startOffsetFraction = (float) (Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS,
+ taskIndexFromFront) * mEnterAndExitFromHomeTranslationOffset) /
+ ENTER_FROM_HOME_TRANSLATION_DURATION;
AnimationProps taskAnimation = new AnimationProps()
- .setInitialPlayTime(AnimationProps.BOUNDS,
- Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS, taskIndexFromFront) *
- mEnterAndExitFromHomeTranslationOffset)
.setStartDelay(AnimationProps.ALPHA,
Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS, taskIndexFromFront) *
FRAME_OFFSET_MS)
.setDuration(AnimationProps.BOUNDS, ENTER_FROM_HOME_TRANSLATION_DURATION)
.setDuration(AnimationProps.ALPHA, ENTER_FROM_HOME_ALPHA_DURATION)
.setInterpolator(AnimationProps.BOUNDS,
- ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR)
+ new RecentsEntrancePathInterpolator(0f, 0f, 0.2f, 1f,
+ startOffsetFraction))
.setInterpolator(AnimationProps.ALPHA, ENTER_FROM_HOME_ALPHA_INTERPOLATOR)
.setListener(postAnimationTrigger.decrementOnAnimationEnd());
postAnimationTrigger.increment();
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index 0b09acc..3b37437 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -91,6 +91,9 @@
}
private void removeDivider() {
+ if (mView != null) {
+ mView.onDividerRemoved();
+ }
mWindowManager.remove();
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 9e2ec57..6dc7870 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -162,6 +162,9 @@
private DividerState mState;
private final SurfaceFlingerVsyncChoreographer mSfChoreographer;
+ // The view is removed or in the process of been removed from the system.
+ private boolean mRemoved;
+
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -323,6 +326,11 @@
EventBus.getDefault().unregister(this);
}
+ void onDividerRemoved() {
+ mRemoved = true;
+ mHandler.removeMessages(MSG_RESIZE_STACK);
+ }
+
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
if (mStableInsets.left != insets.getStableInsetLeft()
@@ -917,6 +925,10 @@
}
public void resizeStack(int position, int taskPosition, SnapTarget taskSnapTarget) {
+ if (mRemoved) {
+ // This divider view has been removed so shouldn't have any additional influence.
+ return;
+ }
calculateBoundsForPosition(position, mDockSide, mDockedRect);
if (mDockedRect.equals(mLastResizeRect) && !mEntranceAnimationRunning) {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
index a2c782e..578a18a 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
@@ -142,7 +142,9 @@
Intent intent = new Intent(mContext, ForcedResizableInfoActivity.class);
ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchTaskId(pendingRecord.taskId);
- options.setTaskOverlay(true, false /* canResume */);
+ // Set as task overlay and allow to resume, so that when an app enters split-screen and
+ // becomes paused, the overlay will still be shown.
+ options.setTaskOverlay(true, true /* canResume */);
intent.putExtra(EXTRA_FORCED_RESIZEABLE_REASON, pendingRecord.reason);
mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index a81b140..1c1be98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -357,15 +357,21 @@
updateShelfIconColor();
}
- private void updateShelfIconColor() {
+ @VisibleForTesting
+ void updateShelfIconColor() {
StatusBarIconView expandedIcon = mEntry.expandedIcon;
boolean isPreL = Boolean.TRUE.equals(expandedIcon.getTag(R.id.icon_is_pre_L));
boolean colorize = !isPreL || NotificationUtils.isGrayscale(expandedIcon,
NotificationColorUtil.getInstance(mContext));
int color = StatusBarIconView.NO_COLOR;
if (colorize) {
- color = mEntry.getContrastedColor(mContext, mIsLowPriority && !isExpanded(),
- getBackgroundColorWithoutTint());
+ NotificationHeaderView header = getVisibleNotificationHeader();
+ if (header != null) {
+ color = header.getOriginalIconColor();
+ } else {
+ color = mEntry.getContrastedColor(mContext, mIsLowPriority && !isExpanded(),
+ getBackgroundColorWithoutTint());
+ }
}
expandedIcon.setStaticDrawableColor(color);
}
@@ -1389,6 +1395,7 @@
if (mIsSummaryWithChildren) {
mChildrenContainer.setDark(dark, fade, delay);
}
+ updateShelfIconColor();
}
public boolean isExpandable() {
@@ -1728,6 +1735,7 @@
NotificationContentView showingLayout = getShowingLayout();
showingLayout.updateBackgroundColor(animated);
mPrivateLayout.updateExpandButtons(isExpandable());
+ updateShelfIconColor();
showingLayout.setDark(isDark(), false /* animate */, 0 /* delay */);
mShowingPublicInitialized = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index baf0c2c..c432ea8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -49,11 +49,11 @@
*/
public class NotificationContentView extends FrameLayout {
- private static final int VISIBLE_TYPE_CONTRACTED = 0;
- private static final int VISIBLE_TYPE_EXPANDED = 1;
- private static final int VISIBLE_TYPE_HEADSUP = 2;
+ public static final int VISIBLE_TYPE_CONTRACTED = 0;
+ public static final int VISIBLE_TYPE_EXPANDED = 1;
+ public static final int VISIBLE_TYPE_HEADSUP = 2;
private static final int VISIBLE_TYPE_SINGLELINE = 3;
- private static final int VISIBLE_TYPE_AMBIENT = 4;
+ public static final int VISIBLE_TYPE_AMBIENT = 4;
private static final int VISIBLE_TYPE_AMBIENT_SINGLELINE = 5;
public static final int UNDEFINED = -1;
@@ -928,7 +928,7 @@
}
}
- private NotificationViewWrapper getVisibleWrapper(int visibleType) {
+ public NotificationViewWrapper getVisibleWrapper(int visibleType) {
switch (visibleType) {
case VISIBLE_TYPE_EXPANDED:
return mExpandedWrapper;
@@ -1085,16 +1085,16 @@
mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
updateAllSingleLineViews();
if (mContractedChild != null) {
- mContractedWrapper.notifyContentUpdated(entry.row);
+ mContractedWrapper.onContentUpdated(entry.row);
}
if (mExpandedChild != null) {
- mExpandedWrapper.notifyContentUpdated(entry.row);
+ mExpandedWrapper.onContentUpdated(entry.row);
}
if (mHeadsUpChild != null) {
- mHeadsUpWrapper.notifyContentUpdated(entry.row);
+ mHeadsUpWrapper.onContentUpdated(entry.row);
}
if (mAmbientChild != null) {
- mAmbientWrapper.notifyContentUpdated(entry.row);
+ mAmbientWrapper.onContentUpdated(entry.row);
}
applyRemoteInput(entry);
updateLegacy();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 1844946..58844ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -24,6 +24,8 @@
import android.content.pm.PackageManager;
import android.content.Context;
import android.graphics.drawable.Icon;
+import android.os.AsyncTask;
+import android.os.Bundle;
import android.os.RemoteException;
import android.os.SystemClock;
import android.service.notification.NotificationListenerService;
@@ -38,8 +40,11 @@
import android.Manifest;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.NotificationColorUtil;
+import com.android.systemui.Dependency;
+import com.android.systemui.ForegroundServiceController;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -141,12 +146,12 @@
// Construct the icon.
icon = new StatusBarIconView(context,
- sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), n);
+ sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
icon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
// Construct the expanded icon.
expandedIcon = new StatusBarIconView(context,
- sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), n);
+ sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
expandedIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
final StatusBarIcon ic = new StatusBarIcon(
sbn.getUser(),
@@ -182,9 +187,11 @@
* @param n the notification to read the icon from.
* @throws InflationException
*/
- public void updateIcons(Context context, Notification n) throws InflationException {
+ public void updateIcons(Context context, StatusBarNotification sbn)
+ throws InflationException {
if (icon != null) {
// Update the icon
+ Notification n = sbn.getNotification();
final StatusBarIcon ic = new StatusBarIcon(
notification.getUser(),
notification.getPackageName(),
@@ -192,8 +199,8 @@
n.iconLevel,
n.number,
StatusBarIconView.contentDescForNotification(context, n));
- icon.setNotification(n);
- expandedIcon.setNotification(n);
+ icon.setNotification(sbn);
+ expandedIcon.setNotification(sbn);
if (!icon.set(ic) || !expandedIcon.set(ic)) {
throw new InflationException("Couldn't update icon: " + ic);
}
@@ -339,6 +346,7 @@
mEntries.put(entry.notification.getKey(), entry);
}
mGroupManager.onEntryAdded(entry);
+
updateRankingAndSort(mRankingMap);
}
@@ -466,6 +474,10 @@
Collections.sort(mSortedAndFiltered, mRankingComparator);
}
+ /**
+ * @param sbn
+ * @return true if this notification should NOT be shown right now
+ */
public boolean shouldFilterOut(StatusBarNotification sbn) {
if (!(mEnvironment.isDeviceProvisioned() ||
showNotificationEvenIfUnprovisioned(sbn))) {
@@ -487,6 +499,13 @@
&& mGroupManager.isChildInGroupWithSummary(sbn)) {
return true;
}
+
+ final ForegroundServiceController fsc = Dependency.get(ForegroundServiceController.class);
+ if (fsc.isDungeonNotification(sbn) && !fsc.isDungeonNeededForUser(sbn.getUserId())) {
+ // this is a foreground-service disclosure for a user that does not need to show one
+ return true;
+ }
+
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 8368143..bbcbfd6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -456,9 +456,8 @@
}
int shelfColor = icon.getStaticDrawableColor();
if (!noIcon && shelfColor != StatusBarIconView.NO_COLOR) {
- int notificationColor
- = row.getVisibleNotificationHeader().getOriginalNotificationColor();
- shelfColor = NotificationUtils.interpolateColors(notificationColor, shelfColor,
+ int iconColor = row.getVisibleNotificationHeader().getOriginalIconColor();
+ shelfColor = NotificationUtils.interpolateColors(iconColor, shelfColor,
iconState.iconAppearAmount);
}
iconState.iconColor = shelfColor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 85475b6..3c7ddb5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -34,6 +34,7 @@
import android.graphics.drawable.Icon;
import android.os.Parcelable;
import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.FloatProperty;
@@ -99,7 +100,7 @@
private int mNumberX;
private int mNumberY;
private String mNumberText;
- private Notification mNotification;
+ private StatusBarNotification mNotification;
private final boolean mBlocked;
private int mDensity;
private float mIconScale = 1.0f;
@@ -127,11 +128,11 @@
};
private final NotificationIconDozeHelper mDozer;
- public StatusBarIconView(Context context, String slot, Notification notification) {
- this(context, slot, notification, false);
+ public StatusBarIconView(Context context, String slot, StatusBarNotification sbn) {
+ this(context, slot, sbn, false);
}
- public StatusBarIconView(Context context, String slot, Notification notification,
+ public StatusBarIconView(Context context, String slot, StatusBarNotification sbn,
boolean blocked) {
super(context);
mDozer = new NotificationIconDozeHelper(context);
@@ -141,7 +142,7 @@
mNumberPain.setTextAlign(Paint.Align.CENTER);
mNumberPain.setColor(context.getColor(R.drawable.notification_number_text_color));
mNumberPain.setAntiAlias(true);
- setNotification(notification);
+ setNotification(sbn);
maybeUpdateIconScaleDimens();
setScaleType(ScaleType.CENTER);
mDensity = context.getResources().getDisplayMetrics().densityDpi;
@@ -207,9 +208,11 @@
}
}
- public void setNotification(Notification notification) {
+ public void setNotification(StatusBarNotification notification) {
mNotification = notification;
- setContentDescription(notification);
+ if (notification != null) {
+ setContentDescription(notification.getNotification());
+ }
}
public StatusBarIconView(Context context, AttributeSet attrs) {
@@ -315,6 +318,10 @@
return true;
}
+ public Icon getSourceIcon() {
+ return mIcon.icon;
+ }
+
private Drawable getIcon(StatusBarIcon icon) {
return getIcon(getContext(), icon);
}
@@ -354,7 +361,7 @@
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
if (mNotification != null) {
- event.setParcelableData(mNotification);
+ event.setParcelableData(mNotification.getNotification());
}
}
@@ -456,6 +463,10 @@
+ " notification=" + mNotification + ")";
}
+ public StatusBarNotification getNotification() {
+ return mNotification;
+ }
+
public String getSlot() {
return mSlot;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java
index 7a34b6e..cf12e94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java
@@ -36,8 +36,8 @@
}
@Override
- public void notifyContentUpdated(ExpandableNotificationRow row) {
- super.notifyContentUpdated(row);
+ public void onContentUpdated(ExpandableNotificationRow row) {
+ super.onContentUpdated(row);
updateImageTag(row.getStatusBarNotification());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java
index 9476eed..20a3d8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java
@@ -41,11 +41,11 @@
}
@Override
- public void notifyContentUpdated(ExpandableNotificationRow row) {
+ public void onContentUpdated(ExpandableNotificationRow row) {
// Reinspect the notification. Before the super call, because the super call also updates
// the transformation types and we need to have our values set by then.
resolveViews(row.getStatusBarNotification());
- super.notifyContentUpdated(row);
+ super.onContentUpdated(row);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
index 0b9244a..15cca5f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -128,8 +128,8 @@
}
@Override
- public void notifyContentUpdated(ExpandableNotificationRow row) {
- super.notifyContentUpdated(row);
+ public void onContentUpdated(ExpandableNotificationRow row) {
+ super.onContentUpdated(row);
mIsLowPriority = row.isLowPriority();
mTransformLowPriorityTitle = !row.isChildInGroup() && !row.isSummaryWithChildren();
ArraySet<View> previousViews = mTransformationHelper.getAllTransformingViews();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
index 4b08f2b..7eaa290 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
@@ -36,7 +36,6 @@
import com.android.systemui.util.Assert;
import java.util.HashMap;
-import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
@@ -207,7 +206,8 @@
};
applyRemoteView(result, reInflateFlags, flag, row, redactAmbient,
isNewView, remoteViewClickHandler, callback, entry, privateLayout,
- privateLayout.getContractedChild(),
+ privateLayout.getContractedChild(), privateLayout.getVisibleWrapper(
+ NotificationContentView.VISIBLE_TYPE_CONTRACTED),
runningInflations, applyCallback);
}
@@ -229,7 +229,9 @@
};
applyRemoteView(result, reInflateFlags, flag, row,
redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
- privateLayout, privateLayout.getExpandedChild(), runningInflations,
+ privateLayout, privateLayout.getExpandedChild(),
+ privateLayout.getVisibleWrapper(
+ NotificationContentView.VISIBLE_TYPE_EXPANDED), runningInflations,
applyCallback);
}
}
@@ -252,7 +254,9 @@
};
applyRemoteView(result, reInflateFlags, flag, row,
redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
- privateLayout, privateLayout.getHeadsUpChild(), runningInflations,
+ privateLayout, privateLayout.getHeadsUpChild(),
+ privateLayout.getVisibleWrapper(
+ NotificationContentView.VISIBLE_TYPE_HEADSUP), runningInflations,
applyCallback);
}
}
@@ -274,8 +278,9 @@
};
applyRemoteView(result, reInflateFlags, flag, row,
redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
- publicLayout, publicLayout.getContractedChild(), runningInflations,
- applyCallback);
+ publicLayout, publicLayout.getContractedChild(),
+ publicLayout.getVisibleWrapper(NotificationContentView.VISIBLE_TYPE_CONTRACTED),
+ runningInflations, applyCallback);
}
flag = FLAG_REINFLATE_AMBIENT_VIEW;
@@ -296,7 +301,8 @@
};
applyRemoteView(result, reInflateFlags, flag, row,
redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
- newParent, newParent.getAmbientChild(), runningInflations,
+ newParent, newParent.getAmbientChild(), newParent.getVisibleWrapper(
+ NotificationContentView.VISIBLE_TYPE_AMBIENT), runningInflations,
applyCallback);
}
@@ -316,6 +322,7 @@
RemoteViews.OnClickHandler remoteViewClickHandler,
@Nullable final InflationCallback callback, NotificationData.Entry entry,
NotificationContentView parentLayout, View existingView,
+ NotificationViewWrapper existingWrapper,
final HashMap<Integer, CancellationSignal> runningInflations,
ApplyCallback applyCallback) {
RemoteViews.OnViewAppliedListener listener
@@ -326,6 +333,8 @@
if (isNewView) {
v.setIsRootNamespace(true);
applyCallback.setResultView(v);
+ } else if (existingWrapper != null) {
+ existingWrapper.onReinflated();
}
runningInflations.remove(inflationId);
finishIfDone(result, reInflateFlags, runningInflations, callback, row,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
index 8596cb3..eb211a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.notification;
import android.content.Context;
-import android.service.notification.StatusBarNotification;
import android.view.View;
import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -40,11 +39,11 @@
}
@Override
- public void notifyContentUpdated(ExpandableNotificationRow row) {
+ public void onContentUpdated(ExpandableNotificationRow row) {
// Reinspect the notification. Before the super call, because the super call also updates
// the transformation types and we need to have our values set by then.
resolveViews();
- super.notifyContentUpdated(row);
+ super.onContentUpdated(row);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
index 9631556..f6ee1ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
@@ -70,11 +70,11 @@
}
@Override
- public void notifyContentUpdated(ExpandableNotificationRow row) {
+ public void onContentUpdated(ExpandableNotificationRow row) {
// Reinspect the notification. Before the super call, because the super call also updates
// the transformation types and we need to have our values set by then.
resolveViews();
- super.notifyContentUpdated(row);
+ super.onContentUpdated(row);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index f0b6b2e..abb4cf6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -133,11 +133,11 @@
}
@Override
- public void notifyContentUpdated(ExpandableNotificationRow row) {
+ public void onContentUpdated(ExpandableNotificationRow row) {
// Reinspect the notification. Before the super call, because the super call also updates
// the transformation types and we need to have our values set by then.
resolveTemplateViews(row.getStatusBarNotification());
- super.notifyContentUpdated(row);
+ super.onContentUpdated(row);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index 5cc39cc..4b73613 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -66,6 +66,7 @@
mView = view;
mRow = row;
mDozer = createDozer(ctx);
+ onReinflated();
}
protected NotificationDozeHelper createDozer(Context ctx) {
@@ -92,12 +93,15 @@
* Notifies this wrapper that the content of the view might have changed.
* @param row the row this wrapper is attached to
*/
- public void notifyContentUpdated(ExpandableNotificationRow row) {
+ public void onContentUpdated(ExpandableNotificationRow row) {
mDarkInitialized = false;
- Drawable background = mView.getBackground();
+ }
+
+ public void onReinflated() {
if (shouldClearBackgroundOnReapply()) {
mBackgroundColor = 0;
}
+ Drawable background = mView.getBackground();
if (background instanceof ColorDrawable) {
mBackgroundColor = ((ColorDrawable) background).getColor();
mView.setBackground(null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 52838b0..5bfdd1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -4,11 +4,15 @@
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
+import android.graphics.drawable.Icon;
import android.support.annotation.NonNull;
+import android.support.v4.util.ArrayMap;
+import android.support.v4.util.ArraySet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
+import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -180,14 +184,54 @@
}
}
+ // In case we are changing the suppression of a group, the replacement shouldn't flicker
+ // and it should just be replaced instead. We therefore look for notifications that were
+ // just replaced by the child or vice-versa to suppress this.
+ ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons = new ArrayMap<>();
ArrayList<View> toRemove = new ArrayList<>();
for (int i = 0; i < hostLayout.getChildCount(); i++) {
View child = hostLayout.getChildAt(i);
+ if (!(child instanceof StatusBarIconView)) {
+ continue;
+ }
if (!toShow.contains(child)) {
- toRemove.add(child);
+ boolean iconWasReplaced = false;
+ StatusBarIconView removedIcon = (StatusBarIconView) child;
+ String removedGroupKey = removedIcon.getNotification().getGroupKey();
+ for (int j = 0; j < toShow.size(); j++) {
+ StatusBarIconView candidate = toShow.get(j);
+ if (candidate.getSourceIcon().sameAs((removedIcon.getSourceIcon()))
+ && candidate.getNotification().getGroupKey().equals(removedGroupKey)) {
+ if (!iconWasReplaced) {
+ iconWasReplaced = true;
+ } else {
+ iconWasReplaced = false;
+ break;
+ }
+ }
+ }
+ if (iconWasReplaced) {
+ ArrayList<StatusBarIcon> statusBarIcons = replacingIcons.get(removedGroupKey);
+ if (statusBarIcons == null) {
+ statusBarIcons = new ArrayList<>();
+ replacingIcons.put(removedGroupKey, statusBarIcons);
+ }
+ statusBarIcons.add(removedIcon.getStatusBarIcon());
+ }
+ toRemove.add(removedIcon);
}
}
+ // removing all duplicates
+ ArrayList<String> duplicates = new ArrayList<>();
+ for (String key : replacingIcons.keySet()) {
+ ArrayList<StatusBarIcon> statusBarIcons = replacingIcons.get(key);
+ if (statusBarIcons.size() != 1) {
+ duplicates.add(key);
+ }
+ }
+ replacingIcons.removeAll(duplicates);
+ hostLayout.setReplacingIcons(replacingIcons);
final int toRemoveCount = toRemove.size();
for (int i = 0; i < toRemoveCount; i++) {
@@ -217,6 +261,7 @@
hostLayout.addView(expected, i);
}
hostLayout.setChangingViewPositions(false);
+ hostLayout.setReplacingIcons(null);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index f94bb0c..a4fadc4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -21,9 +21,13 @@
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.drawable.Icon;
+import android.support.v4.util.ArrayMap;
+import android.support.v4.util.ArraySet;
import android.util.AttributeSet;
import android.view.View;
+import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;
@@ -33,6 +37,7 @@
import com.android.systemui.statusbar.stack.StackStateAnimator;
import com.android.systemui.statusbar.stack.ViewState;
+import java.util.ArrayList;
import java.util.HashMap;
/**
@@ -117,6 +122,7 @@
private float mVisualOverflowAdaption;
private boolean mDisallowNextAnimation;
private boolean mAnimationsEnabled = true;
+ private ArrayMap<String, ArrayList<StatusBarIcon>> mReplacingIcons;
public NotificationIconContainer(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -183,11 +189,17 @@
@Override
public void onViewAdded(View child) {
super.onViewAdded(child);
+ boolean isReplacingIcon = isReplacingIcon(child);
if (!mChangingViewPositions) {
- mIconStates.put(child, new IconState());
+ IconState v = new IconState();
+ if (isReplacingIcon) {
+ v.justAdded = false;
+ v.justReplaced = true;
+ }
+ mIconStates.put(child, v);
}
int childIndex = indexOfChild(child);
- if (childIndex < getChildCount() - 1
+ if (childIndex < getChildCount() - 1 && !isReplacingIcon
&& mIconStates.get(getChildAt(childIndex + 1)).iconAppearAmount > 0.0f) {
if (mAddAnimationStartIndex < 0) {
mAddAnimationStartIndex = childIndex;
@@ -200,13 +212,34 @@
}
}
+ private boolean isReplacingIcon(View child) {
+ if (mReplacingIcons == null) {
+ return false;
+ }
+ if (!(child instanceof StatusBarIconView)) {
+ return false;
+ }
+ StatusBarIconView iconView = (StatusBarIconView) child;
+ Icon sourceIcon = iconView.getSourceIcon();
+ String groupKey = iconView.getNotification().getGroupKey();
+ ArrayList<StatusBarIcon> statusBarIcons = mReplacingIcons.get(groupKey);
+ if (statusBarIcons != null) {
+ StatusBarIcon replacedIcon = statusBarIcons.get(0);
+ if (sourceIcon.sameAs(replacedIcon.icon)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public void onViewRemoved(View child) {
super.onViewRemoved(child);
if (child instanceof StatusBarIconView) {
+ boolean isReplacingIcon = isReplacingIcon(child);
final StatusBarIconView icon = (StatusBarIconView) child;
if (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
- && child.getVisibility() == VISIBLE) {
+ && child.getVisibility() == VISIBLE && isReplacingIcon) {
int animationStartIndex = findFirstViewIndexAfter(icon.getTranslationX());
if (mAddAnimationStartIndex < 0) {
mAddAnimationStartIndex = animationStartIndex;
@@ -216,9 +249,11 @@
}
if (!mChangingViewPositions) {
mIconStates.remove(child);
- addTransientView(icon, 0);
- icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, true /* animate */,
- () -> removeTransientView(icon));
+ if (!isReplacingIcon) {
+ addTransientView(icon, 0);
+ icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, true /* animate */,
+ () -> removeTransientView(icon));
+ }
}
}
}
@@ -473,11 +508,16 @@
mAnimationsEnabled = enabled;
}
+ public void setReplacingIcons(ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons) {
+ mReplacingIcons = replacingIcons;
+ }
+
public class IconState extends ViewState {
public float iconAppearAmount = 1.0f;
public float clampedAppearAmount = 1.0f;
public int visibleState;
public boolean justAdded = true;
+ private boolean justReplaced;
public boolean needsCannedAnimation;
public boolean useFullTransitionAmount;
public boolean useLinearTransitionAmount;
@@ -496,9 +536,9 @@
&& !mDisallowNextAnimation
&& !noAnimations;
if (animationsAllowed) {
- if (justAdded) {
+ if (justAdded || justReplaced) {
super.applyToView(icon);
- if (iconAppearAmount != 0.0f) {
+ if (justAdded && iconAppearAmount != 0.0f) {
icon.setAlpha(0.0f);
icon.setVisibleState(StatusBarIconView.STATE_HIDDEN,
false /* animate */);
@@ -557,6 +597,7 @@
}
}
justAdded = false;
+ justReplaced = false;
needsCannedAnimation = false;
justUndarkened = false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 4e28e90..f4f48a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -36,11 +36,17 @@
import android.animation.AnimatorListenerAdapter;
import android.annotation.NonNull;
import android.app.ActivityManager;
+import android.app.ActivityManager.StackId;
import android.app.ActivityOptions;
+import android.app.INotificationManager;
+import android.app.KeyguardManager;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.app.RemoteInput;
import android.app.StatusBarManager;
+import android.app.TaskStackBuilder;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
@@ -49,8 +55,11 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
+import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -75,7 +84,9 @@
import android.metrics.LogMaker;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
@@ -83,54 +94,73 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.os.SystemService;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.Vibrator;
import android.provider.Settings;
+import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.view.ContextThemeWrapper;
import android.view.Display;
+import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.ThreadedRenderer;
import android.view.View;
+import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewStub;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.DateTimeView;
import android.widget.ImageView;
+import android.widget.RemoteViews;
import android.widget.TextView;
+import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.NotificationMessagingUtil;
+import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.ActivityStarterDelegate;
+import com.android.systemui.DejankUtils;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.EventLogTags;
+import com.android.systemui.ForegroundServiceController;
import com.android.systemui.Interpolators;
import com.android.systemui.Prefs;
import com.android.systemui.R;
+import com.android.systemui.RecentsComponent;
+import com.android.systemui.SwipeHelper;
+import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.assist.AssistManager;
@@ -141,12 +171,14 @@
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.PluginFragmentListener;
import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
@@ -194,11 +226,15 @@
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.PreviewInflater;
+import com.android.systemui.statusbar.policy.RemoteInputView;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout
+ .OnChildLocationsChangedListener;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
+import com.android.systemui.util.NotificationChannels;
import com.android.systemui.util.leak.LeakDetector;
import com.android.systemui.volume.VolumeComponent;
@@ -209,48 +245,10 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import android.app.ActivityManager.StackId;
-import android.app.INotificationManager;
-import android.app.KeyguardManager;
-import android.app.NotificationChannel;
-import android.app.RemoteInput;
-import android.app.TaskStackBuilder;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.UserInfo;
-import android.os.Build;
-import android.os.Handler;
-import android.service.notification.NotificationListenerService;
-import android.service.vr.IVrManager;
-import android.service.vr.IVrStateCallbacks;
-import android.text.TextUtils;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.util.SparseBooleanArray;
-import android.view.IWindowManager;
-import android.view.ViewAnimationUtils;
-import android.view.accessibility.AccessibilityManager;
-import android.widget.RemoteViews;
-import android.widget.Toast;
-
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.systemui.DejankUtils;
-import com.android.systemui.RecentsComponent;
-import com.android.systemui.SwipeHelper;
-import com.android.systemui.SystemUI;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.statusbar.policy.RemoteInputView;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
-import com.android.systemui.util.NotificationChannels;
-
import java.util.HashSet;
+import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.Set;
import java.util.Stack;
@@ -473,6 +471,7 @@
int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
private final Rect mLastFullscreenStackBounds = new Rect();
private final Rect mLastDockedStackBounds = new Rect();
+ private final Rect mTmpRect = new Rect();
// last value sent to window manager
private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE;
@@ -718,6 +717,7 @@
private ConfigurationListener mConfigurationListener;
private boolean mReinflateNotificationsOnUserSwitched;
private HashMap<String, Entry> mPendingNotifications = new HashMap<>();
+ private ForegroundServiceController mForegroundServiceController;
private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
final int N = array.size();
@@ -761,6 +761,8 @@
mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
mSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
+ mForegroundServiceController = Dependency.get(ForegroundServiceController.class);
+
mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
mDisplay = mWindowManager.getDefaultDisplay();
updateDisplaySize();
@@ -1370,20 +1372,33 @@
int numChildren = mStackScroller.getChildCount();
final ArrayList<View> viewsToHide = new ArrayList<View>(numChildren);
+ final ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>(numChildren);
for (int i = 0; i < numChildren; i++) {
final View child = mStackScroller.getChildAt(i);
if (child instanceof ExpandableNotificationRow) {
- if (mStackScroller.canChildBeDismissed(child)) {
- if (child.getVisibility() == View.VISIBLE) {
- viewsToHide.add(child);
- }
- }
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ boolean parentVisible = false;
+ boolean hasClipBounds = child.getClipBounds(mTmpRect);
+ if (mStackScroller.canChildBeDismissed(child)) {
+ viewsToRemove.add(row);
+ if (child.getVisibility() == View.VISIBLE
+ && (!hasClipBounds || mTmpRect.height() > 0)) {
+ viewsToHide.add(child);
+ parentVisible = true;
+ }
+ } else if (child.getVisibility() == View.VISIBLE
+ && (!hasClipBounds || mTmpRect.height() > 0)) {
+ parentVisible = true;
+ }
List<ExpandableNotificationRow> children = row.getNotificationChildren();
- if (row.areChildrenExpanded() && children != null) {
+ if (children != null) {
for (ExpandableNotificationRow childRow : children) {
- if (mStackScroller.canChildBeDismissed(childRow)) {
- if (childRow.getVisibility() == View.VISIBLE) {
+ viewsToRemove.add(childRow);
+ if (parentVisible && row.areChildrenExpanded()
+ && mStackScroller.canChildBeDismissed(childRow)) {
+ hasClipBounds = childRow.getClipBounds(mTmpRect);
+ if (childRow.getVisibility() == View.VISIBLE
+ && (!hasClipBounds || mTmpRect.height() > 0)) {
viewsToHide.add(childRow);
}
}
@@ -1391,7 +1406,7 @@
}
}
}
- if (viewsToHide.isEmpty()) {
+ if (viewsToRemove.isEmpty()) {
animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
return;
}
@@ -1400,6 +1415,13 @@
@Override
public void run() {
mStackScroller.setDismissAllInProgress(false);
+ for (ExpandableNotificationRow rowToRemove : viewsToRemove) {
+ if (mStackScroller.canChildBeDismissed(rowToRemove)) {
+ removeNotification(rowToRemove.getEntry().key, null);
+ } else {
+ rowToRemove.resetTranslation();
+ }
+ }
try {
mBarService.onClearAllNotifications(mCurrentUserId);
} catch (Exception ex) { }
@@ -1578,6 +1600,10 @@
}
}
abortExistingInflation(key);
+
+ mForegroundServiceController.addNotification(notification,
+ mNotificationData.getImportance(key));
+
mPendingNotifications.put(key, shadeEntry);
}
@@ -1716,6 +1742,10 @@
return;
}
+ if (entry != null) {
+ mForegroundServiceController.removeNotification(entry.notification);
+ }
+
if (entry != null && entry.row != null) {
entry.row.setRemoved();
mStackScroller.cleanUpViewState(entry.row);
@@ -3547,6 +3577,12 @@
// Do it after DismissAction has been processed to conserve the needed ordering.
mHandler.post(this::runPostCollapseRunnables);
}
+ } else if (isInLaunchTransition() && mNotificationPanel.isLaunchTransitionFinished()) {
+
+ // We are not dismissing the shade, but the launch transition is already finished,
+ // so nobody will call readyForKeyguardDone anymore. Post it such that
+ // keyguardDonePending gets called first.
+ mHandler.post(mStatusBarKeyguardViewManager::readyForKeyguardDone);
}
return deferred;
}, cancelAction, afterKeyguardGone);
@@ -6085,6 +6121,9 @@
}
public boolean isLockscreenPublicMode(int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ return mLockscreenPublicMode.get(mCurrentUserId, false);
+ }
return mLockscreenPublicMode.get(userId, false);
}
@@ -6763,9 +6802,12 @@
entry.notification = notification;
mGroupManager.onEntryUpdated(entry, oldNotification);
- entry.updateIcons(mContext, n);
+ entry.updateIcons(mContext, notification);
inflateViews(entry, mStackScroller);
+ mForegroundServiceController.updateNotification(notification,
+ mNotificationData.getImportance(key));
+
boolean shouldPeek = shouldPeek(entry, notification);
boolean alertAgain = alertAgain(entry, n);
@@ -6783,6 +6825,7 @@
boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
}
+
setAreThereNotifications();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 236e008..f58a91b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -722,6 +722,10 @@
}
@Override
+ public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
+ }
+
+ @Override
public void reportActivityRelaunched() {
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index ff06b5b..b6964a03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -297,7 +297,7 @@
} else {
header.reapply(getContext(), mNotificationHeader);
}
- mNotificationHeaderWrapper.notifyContentUpdated(mContainingNotification);
+ mNotificationHeaderWrapper.onContentUpdated(mContainingNotification);
recreateLowPriorityHeader(builder);
recreateAmbientHeader(builder);
updateHeaderVisibility(false /* animate */);
@@ -316,14 +316,14 @@
mNotificationHeaderAmbient = (ViewGroup) header.apply(getContext(), this);
mNotificationHeaderWrapperAmbient = NotificationViewWrapper.wrap(getContext(),
mNotificationHeaderAmbient, mContainingNotification);
- mNotificationHeaderWrapperAmbient.notifyContentUpdated(mContainingNotification);
+ mNotificationHeaderWrapperAmbient.onContentUpdated(mContainingNotification);
addView(mNotificationHeaderAmbient, 0);
invalidate();
} else {
header.reapply(getContext(), mNotificationHeaderAmbient);
}
resetHeaderVisibilityIfNeeded(mNotificationHeaderAmbient, calculateDesiredHeader());
- mNotificationHeaderWrapperAmbient.notifyContentUpdated(mContainingNotification);
+ mNotificationHeaderWrapperAmbient.onContentUpdated(mContainingNotification);
}
/**
@@ -354,7 +354,7 @@
} else {
header.reapply(getContext(), mNotificationHeaderLowPriority);
}
- mNotificationHeaderWrapperLowPriority.notifyContentUpdated(mContainingNotification);
+ mNotificationHeaderWrapperLowPriority.onContentUpdated(mContainingNotification);
resetHeaderVisibilityIfNeeded(mNotificationHeaderLowPriority, calculateDesiredHeader());
} else {
removeView(mNotificationHeaderLowPriority);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index e86a34a..f6d36e8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -60,7 +60,8 @@
private final Context mContext;
private final VolumeDialogControllerImpl mController;
private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
- ActivityInfo.CONFIG_FONT_SCALE);
+ ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
+ | ActivityInfo.CONFIG_ASSETS_PATHS);
private final Extension mExtension;
private VolumeDialog mDialog;
private VolumePolicy mVolumePolicy = new VolumePolicy(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
new file mode 100644
index 0000000..1f5255a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.annotation.UserIdInt;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import com.android.internal.messages.nano.SystemMessageProto;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ForegroundServiceControllerTest extends SysuiTestCase {
+ public static @UserIdInt int USERID_ONE = 10; // UserManagerService.MIN_USER_ID;
+ public static @UserIdInt int USERID_TWO = USERID_ONE + 1;
+
+ private ForegroundServiceController fsc;
+
+ @Before
+ public void setUp() throws Exception {
+ fsc = new ForegroundServiceControllerImpl(mContext);
+ }
+
+ @Test
+ public void testNotificationCRUD() {
+ StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, "com.example.app1");
+ StatusBarNotification sbn_user2_app2_fg = makeMockFgSBN(USERID_TWO, "com.example.app2");
+ StatusBarNotification sbn_user1_app3_fg = makeMockFgSBN(USERID_ONE, "com.example.app3");
+ StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, "com.example.app1",
+ 5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+ StatusBarNotification sbn_user2_app1 = makeMockSBN(USERID_TWO, "com.example.app1",
+ 5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+
+ assertFalse(fsc.removeNotification(sbn_user1_app3_fg));
+ assertFalse(fsc.removeNotification(sbn_user2_app2_fg));
+ assertFalse(fsc.removeNotification(sbn_user1_app1_fg));
+ assertFalse(fsc.removeNotification(sbn_user1_app1));
+ assertFalse(fsc.removeNotification(sbn_user2_app1));
+
+ fsc.addNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
+ fsc.addNotification(sbn_user2_app2_fg, NotificationManager.IMPORTANCE_DEFAULT);
+ fsc.addNotification(sbn_user1_app3_fg, NotificationManager.IMPORTANCE_DEFAULT);
+ fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+ fsc.addNotification(sbn_user2_app1, NotificationManager.IMPORTANCE_DEFAULT);
+
+ // these are never added to the tracker
+ assertFalse(fsc.removeNotification(sbn_user1_app1));
+ assertFalse(fsc.removeNotification(sbn_user2_app1));
+
+ fsc.updateNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+ fsc.updateNotification(sbn_user2_app1, NotificationManager.IMPORTANCE_DEFAULT);
+ // should still not be there
+ assertFalse(fsc.removeNotification(sbn_user1_app1));
+ assertFalse(fsc.removeNotification(sbn_user2_app1));
+
+ fsc.updateNotification(sbn_user2_app2_fg, NotificationManager.IMPORTANCE_DEFAULT);
+ fsc.updateNotification(sbn_user1_app3_fg, NotificationManager.IMPORTANCE_DEFAULT);
+ fsc.updateNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
+
+ assertTrue(fsc.removeNotification(sbn_user1_app3_fg));
+ assertFalse(fsc.removeNotification(sbn_user1_app3_fg));
+
+ assertTrue(fsc.removeNotification(sbn_user2_app2_fg));
+ assertFalse(fsc.removeNotification(sbn_user2_app2_fg));
+
+ assertTrue(fsc.removeNotification(sbn_user1_app1_fg));
+ assertFalse(fsc.removeNotification(sbn_user1_app1_fg));
+
+ assertFalse(fsc.removeNotification(sbn_user1_app1));
+ assertFalse(fsc.removeNotification(sbn_user2_app1));
+ }
+
+ @Test
+ public void testDungeonPredicate() {
+ StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, "com.example.app1",
+ 5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+ StatusBarNotification sbn_user1_dungeon = makeMockSBN(USERID_ONE, "android",
+ SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES,
+ null, Notification.FLAG_NO_CLEAR);
+
+ assertTrue(fsc.isDungeonNotification(sbn_user1_dungeon));
+ assertFalse(fsc.isDungeonNotification(sbn_user1_app1));
+ }
+
+ @Test
+ public void testDungeonCRUD() {
+ StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, "com.example.app1",
+ 5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+ StatusBarNotification sbn_user1_dungeon = makeMockSBN(USERID_ONE, "android",
+ SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES,
+ null, Notification.FLAG_NO_CLEAR);
+
+ fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+ fsc.addNotification(sbn_user1_dungeon, NotificationManager.IMPORTANCE_DEFAULT);
+
+ fsc.removeNotification(sbn_user1_dungeon);
+ assertFalse(fsc.removeNotification(sbn_user1_app1));
+ }
+
+ @Test
+ public void testNeedsDungeonAfterRemovingUnrelatedNotification() {
+ final String PKG1 = "com.example.app100";
+
+ StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, PKG1,
+ 5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+ StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, PKG1);
+
+ // first add a normal notification
+ fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+ // nothing required yet
+ assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+ // now the app starts a fg service
+ fsc.addNotification(makeMockDungeon(USERID_ONE, new String[]{ PKG1 }),
+ NotificationManager.IMPORTANCE_DEFAULT);
+ assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+ // add the fg notification
+ fsc.addNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
+ assertFalse(fsc.isDungeonNeededForUser(USERID_ONE)); // app1 has got it covered
+ // remove the boring notification
+ fsc.removeNotification(sbn_user1_app1);
+ assertFalse(fsc.isDungeonNeededForUser(USERID_ONE)); // app1 has STILL got it covered
+ assertTrue(fsc.removeNotification(sbn_user1_app1_fg));
+ assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+ }
+
+ @Test
+ public void testSimpleAddRemove() {
+ final String PKG1 = "com.example.app1";
+ final String PKG2 = "com.example.app2";
+
+ StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, PKG1,
+ 5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+ fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+
+ // no services are "running"
+ fsc.addNotification(makeMockDungeon(USERID_ONE, null),
+ NotificationManager.IMPORTANCE_DEFAULT);
+
+ assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+ assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+ fsc.updateNotification(makeMockDungeon(USERID_ONE, new String[]{PKG1}),
+ NotificationManager.IMPORTANCE_DEFAULT);
+ assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+ assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+ // switch to different package
+ fsc.updateNotification(makeMockDungeon(USERID_ONE, new String[]{PKG2}),
+ NotificationManager.IMPORTANCE_DEFAULT);
+ assertTrue(fsc.isDungeonNeededForUser(USERID_ONE));
+ assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+ fsc.updateNotification(makeMockDungeon(USERID_TWO, new String[]{PKG1}),
+ NotificationManager.IMPORTANCE_DEFAULT);
+ assertTrue(fsc.isDungeonNeededForUser(USERID_ONE));
+ assertTrue(fsc.isDungeonNeededForUser(USERID_TWO)); // finally user2 needs one too
+
+ fsc.updateNotification(makeMockDungeon(USERID_ONE, new String[]{PKG2, PKG1}),
+ NotificationManager.IMPORTANCE_DEFAULT);
+ assertTrue(fsc.isDungeonNeededForUser(USERID_ONE));
+ assertTrue(fsc.isDungeonNeededForUser(USERID_TWO));
+
+ fsc.removeNotification(makeMockDungeon(USERID_ONE, null /*unused*/));
+ assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+ assertTrue(fsc.isDungeonNeededForUser(USERID_TWO));
+
+ fsc.removeNotification(makeMockDungeon(USERID_TWO, null /*unused*/));
+ assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+ assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+ }
+
+ @Test
+ public void testDungeonBasic() {
+ final String PKG1 = "com.example.app0";
+
+ StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, PKG1,
+ 5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+ StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, PKG1);
+
+ fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT); // not fg
+ fsc.addNotification(makeMockDungeon(USERID_ONE, new String[]{ PKG1 }),
+ NotificationManager.IMPORTANCE_DEFAULT);
+ assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+ fsc.addNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
+ assertFalse(fsc.isDungeonNeededForUser(USERID_ONE)); // app1 has got it covered
+ assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+ // let's take out the other notification and see what happens.
+
+ fsc.removeNotification(sbn_user1_app1);
+ assertFalse(fsc.isDungeonNeededForUser(USERID_ONE)); // still covered by sbn_user1_app1_fg
+ assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+ // let's attempt to downgrade the notification from FLAG_FOREGROUND and see what we get
+ StatusBarNotification sbn_user1_app1_fg_sneaky = makeMockFgSBN(USERID_ONE, PKG1);
+ sbn_user1_app1_fg_sneaky.getNotification().flags = 0;
+ fsc.updateNotification(sbn_user1_app1_fg_sneaky, NotificationManager.IMPORTANCE_DEFAULT);
+ assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+ assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+ // ok, ok, we'll put it back
+ sbn_user1_app1_fg_sneaky.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
+ fsc.updateNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
+ assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+ assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+ assertTrue(fsc.removeNotification(sbn_user1_app1_fg_sneaky));
+ assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+ assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+ // now let's test an upgrade
+ fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+ assertTrue(fsc.isDungeonNeededForUser(USERID_ONE));
+ assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+ sbn_user1_app1.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
+ fsc.updateNotification(sbn_user1_app1,
+ NotificationManager.IMPORTANCE_DEFAULT); // this is now a fg notification
+
+ assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+ assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+
+ // remove it, make sure we're out of compliance again
+ assertTrue(fsc.removeNotification(sbn_user1_app1)); // was fg, should return true
+ assertFalse(fsc.removeNotification(sbn_user1_app1));
+ assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+ assertTrue(fsc.isDungeonNeededForUser(USERID_ONE));
+
+ // finally, let's turn off the service
+ fsc.addNotification(makeMockDungeon(USERID_ONE, null),
+ NotificationManager.IMPORTANCE_DEFAULT);
+
+ assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+ assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+ }
+
+ private StatusBarNotification makeMockSBN(int userid, String pkg, int id, String tag,
+ int flags) {
+ final Notification n = mock(Notification.class);
+ n.flags = flags;
+ return makeMockSBN(userid, pkg, id, tag, n);
+ }
+ private StatusBarNotification makeMockSBN(int userid, String pkg, int id, String tag,
+ Notification n) {
+ final StatusBarNotification sbn = mock(StatusBarNotification.class);
+ when(sbn.getNotification()).thenReturn(n);
+ when(sbn.getId()).thenReturn(id);
+ when(sbn.getPackageName()).thenReturn(pkg);
+ when(sbn.getTag()).thenReturn(null);
+ when(sbn.getUserId()).thenReturn(userid);
+ when(sbn.getUser()).thenReturn(new UserHandle(userid));
+ when(sbn.getKey()).thenReturn("MOCK:"+userid+"|"+pkg+"|"+id+"|"+tag);
+ return sbn;
+ }
+ private StatusBarNotification makeMockFgSBN(int userid, String pkg) {
+ return makeMockSBN(userid, pkg, 1000, "foo", Notification.FLAG_FOREGROUND_SERVICE);
+ }
+ private StatusBarNotification makeMockDungeon(int userid, String[] pkgs) {
+ final Notification n = mock(Notification.class);
+ n.flags = Notification.FLAG_ONGOING_EVENT;
+ final Bundle extras = new Bundle();
+ if (pkgs != null) extras.putStringArray(Notification.EXTRA_FOREGROUND_APPS, pkgs);
+ n.extras = extras;
+ final StatusBarNotification sbn = makeMockSBN(userid, "android",
+ SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES,
+ null, n);
+ sbn.getNotification().extras = extras;
+ return sbn;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
index 1161987..2e547e1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
@@ -18,6 +18,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
@@ -87,5 +88,18 @@
verify(mockContainer).reInflateViews(any(), any());
}
+ @Test
+ public void testIconColorShouldBeUpdatedWhenSensitive() throws Exception {
+ ExpandableNotificationRow row = spy(mNotificationTestHelper.createRow());
+ row.setSensitive(true, true);
+ row.setHideSensitive(true, false, 0, 0);
+ verify(row).updateShelfIconColor();
+ }
+ @Test
+ public void testIconColorShouldBeUpdatedWhenSettingDark() throws Exception {
+ ExpandableNotificationRow row = spy(mNotificationTestHelper.createRow());
+ row.setDark(true, false, 0);
+ verify(row).updateShelfIconColor();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
index fc9b608..917a9f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
@@ -53,11 +53,14 @@
RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.custom_view_dark);
View v = views.apply(mContext, null);
NotificationViewWrapper wrap = NotificationCustomViewWrapper.wrap(mContext, v, mRow);
- wrap.notifyContentUpdated(mRow);
- Assert.assertTrue(wrap.getCustomBackgroundColor() != 0);
+ wrap.onContentUpdated(mRow);
+ Assert.assertTrue("No background set, when applying custom background view",
+ wrap.getCustomBackgroundColor() != 0);
views.reapply(mContext, v);
- wrap.notifyContentUpdated(mRow);
- Assert.assertTrue(wrap.getCustomBackgroundColor() != 0);
+ wrap.onReinflated();
+ wrap.onContentUpdated(mRow);
+ Assert.assertTrue("Reapplying a custom remote view lost it's background!",
+ wrap.getCustomBackgroundColor() != 0);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
index ebeb24c8..9da28a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
@@ -24,6 +24,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationTestHelper;
import org.junit.Before;
import org.junit.Test;
@@ -35,7 +36,9 @@
@Test
public void constructor_doesntUseViewContext() throws Exception {
- new TestableNotificationViewWrapper(mContext, null /* view */, null /* row */);
+ new TestableNotificationViewWrapper(mContext,
+ new View(mContext),
+ new NotificationTestHelper(getContext()).createRow());
}
static class TestableNotificationViewWrapper extends NotificationViewWrapper {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 55ec307..db6647c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -72,7 +72,7 @@
NotificationData mNotificationData;
PowerManager mPowerManager;
SystemServicesProxy mSystemServicesProxy;
-
+ NotificationPanelView mNotificationPanelView;
private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
@Before
@@ -85,6 +85,7 @@
mHeadsUpManager = mock(HeadsUpManager.class);
mNotificationData = mock(NotificationData.class);
mSystemServicesProxy = mock(SystemServicesProxy.class);
+ mNotificationPanelView = mock(NotificationPanelView.class);
IPowerManager powerManagerService = mock(IPowerManager.class);
HandlerThread handlerThread = new HandlerThread("TestThread");
handlerThread.start();
@@ -95,7 +96,7 @@
mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager, mUnlockMethodCache,
mKeyguardIndicationController, mStackScroller, mHeadsUpManager,
- mNotificationData, mPowerManager, mSystemServicesProxy);
+ mNotificationData, mPowerManager, mSystemServicesProxy, mNotificationPanelView);
doAnswer(invocation -> {
OnDismissAction onDismissAction = (OnDismissAction) invocation.getArguments()[0];
@@ -287,7 +288,7 @@
public TestableStatusBar(StatusBarKeyguardViewManager man,
UnlockMethodCache unlock, KeyguardIndicationController key,
NotificationStackScrollLayout stack, HeadsUpManager hum, NotificationData nd,
- PowerManager pm, SystemServicesProxy ssp) {
+ PowerManager pm, SystemServicesProxy ssp, NotificationPanelView panelView) {
mStatusBarKeyguardViewManager = man;
mUnlockMethodCache = unlock;
mKeyguardIndicationController = key;
@@ -297,6 +298,7 @@
mUseHeadsUp = true;
mPowerManager = pm;
mSystemServicesProxy = ssp;
+ mNotificationPanel = panelView;
}
@Override
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index f37bfac..3dd75bb 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3962,6 +3962,16 @@
// OS: O
APP_TRANSITION_BIND_APPLICATION_DELAY_MS = 945;
+ // FIELD - The group ID of a notification.
+ // Type: string
+ // OS: O
+ FIELD_NOTIFICATION_GROUP_ID = 946;
+
+ // FIELD - If the notification is a group summary: 1.
+ // Type: int encoded boolean
+ // OS: O
+ FIELD_NOTIFICATION_GROUP_SUMMARY = 947;
+
// ---- End O Constants, all O constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 980a7d4..073d7b2 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -774,20 +774,29 @@
break;
}
- final AutofillValue currentValue = viewState.getCurrentValue();
- if (currentValue == null || currentValue.isEmpty()) {
- if (sDebug) {
- Slog.d(TAG, "showSaveLocked(): empty value for required " + id );
+ AutofillValue value = viewState.getCurrentValue();
+ if (value == null || value.isEmpty()) {
+ final AutofillValue initialValue = getValueFromContexts(id);
+ if (initialValue != null) {
+ if (sDebug) {
+ Slog.d(TAG, "Value of required field " + id + " didn't change; "
+ + "using initial value (" + initialValue + ") instead");
+ }
+ value = initialValue;
+ } else {
+ if (sDebug) {
+ Slog.d(TAG, "showSaveLocked(): empty value for required " + id );
+ }
+ allRequiredAreNotEmpty = false;
+ break;
}
- allRequiredAreNotEmpty = false;
- break;
}
final AutofillValue filledValue = viewState.getAutofilledValue();
- if (!currentValue.equals(filledValue)) {
+ if (!value.equals(filledValue)) {
if (sDebug) {
Slog.d(TAG, "showSaveLocked(): found a change on required " + id + ": "
- + filledValue + " => " + currentValue);
+ + filledValue + " => " + value);
}
atLeastOneChanged = true;
}
@@ -845,6 +854,31 @@
}
/**
+ * Gets the latest non-empty value for the given id in the autofill contexts.
+ */
+ @Nullable
+ private AutofillValue getValueFromContexts(AutofillId id) {
+ AutofillValue value = null;
+ final int numContexts = mContexts.size();
+ for (int i = 0; i < numContexts; i++) {
+ final FillContext context = mContexts.get(i);
+ // TODO: create a function that gets just one node so it doesn't create an array
+ // unnecessarily
+ final ViewNode[] nodes = context.findViewNodesByAutofillIds(id);
+ if (nodes != null) {
+ AutofillValue candidate = nodes[0].getAutofillValue();
+ if (sDebug) {
+ Slog.d(TAG, "getValueFromContexts(" + id + ") at " + i + ": " + candidate);
+ }
+ if (candidate != null && !candidate.isEmpty()) {
+ value = candidate;
+ }
+ }
+ }
+ return value;
+ }
+
+ /**
* Calls service when user requested save.
*/
void callSaveLocked() {
@@ -1009,7 +1043,7 @@
|| action == ACTION_VIEW_ENTERED) {
if (sVerbose) Slog.v(TAG, "Creating viewState for " + id + " on " + action);
boolean isIgnored = isIgnoredLocked(id);
- viewState = new ViewState(this, id, value, this,
+ viewState = new ViewState(this, id, this,
isIgnored ? ViewState.STATE_IGNORED : ViewState.STATE_INITIAL);
mViewStates.put(id, viewState);
if (isIgnored) {
@@ -1307,7 +1341,7 @@
if (viewState != null) {
viewState.setState(state);
} else {
- viewState = new ViewState(this, id, null, this, state);
+ viewState = new ViewState(this, id, this, state);
if (sVerbose) {
Slog.v(TAG, "Adding autofillable view with id " + id + " and state " + state);
}
@@ -1370,10 +1404,16 @@
}
}
+ @Override
+ public String toString() {
+ return "Session: [id=" + id + ", pkg=" + mPackageName + "]";
+ }
+
void dumpLocked(String prefix, PrintWriter pw) {
final String prefix2 = prefix + " ";
pw.print(prefix); pw.print("id: "); pw.println(id);
pw.print(prefix); pw.print("uid: "); pw.println(uid);
+ pw.print(prefix); pw.print("mPackagename: "); pw.println(mPackageName);
pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
pw.print(prefix); pw.print("mResponses: ");
if (mResponses == null) {
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index cd8f4a5..51659bb 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -74,16 +74,14 @@
private final Session mSession;
private FillResponse mResponse;
- private AutofillValue mInitialValue;
private AutofillValue mCurrentValue;
private AutofillValue mAutofilledValue;
private Rect mVirtualBounds;
private int mState;
- ViewState(Session session, AutofillId id, AutofillValue value, Listener listener, int state) {
+ ViewState(Session session, AutofillId id, Listener listener, int state) {
mSession = session;
this.id = id;
- mInitialValue = value;
mListener = listener;
mState = state;
}
@@ -118,11 +116,6 @@
}
@Nullable
- AutofillValue getInitialValue() {
- return mInitialValue;
- }
-
- @Nullable
FillResponse getResponse() {
return mResponse;
}
@@ -189,8 +182,8 @@
@Override
public String toString() {
- return "ViewState: [id=" + id + ", initialValue=" + mInitialValue
- + ", currentValue=" + mCurrentValue + ", autofilledValue=" + mAutofilledValue
+ return "ViewState: [id=" + id + ", currentValue=" + mCurrentValue
+ + ", autofilledValue=" + mAutofilledValue
+ ", bounds=" + mVirtualBounds + ", state=" + getStateAsString() + "]";
}
@@ -207,7 +200,6 @@
pw.println(mResponse.getRequestId());
}
}
- pw.print(prefix); pw.print("initialValue:" ); pw.println(mInitialValue);
pw.print(prefix); pw.print("currentValue:" ); pw.println(mCurrentValue);
pw.print(prefix); pw.print("autofilledValue:" ); pw.println(mAutofilledValue);
pw.print(prefix); pw.print("virtualBounds:" ); pw.println(mVirtualBounds);
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index c3d55054..8ffe8f5 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -332,6 +332,10 @@
@android.annotation.UiThread
private void hideSaveUiUiThread(@Nullable AutoFillUiCallback callback) {
+ if (sVerbose) {
+ Slog.v(TAG, "hideSaveUiUiThread(): mSaveUi=" + mSaveUi + ", callback=" + callback
+ + ", mCallback=" + mCallback);
+ }
if (mSaveUi != null && (callback == null || callback == mCallback)) {
mSaveUi.destroy();
mSaveUi = null;
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index d566d3d..e9c98e9 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -398,6 +398,12 @@
} catch (WindowManager.BadTokenException e) {
if (sDebug) Slog.d(TAG, "Filed with with token " + params.token + " gone.");
mCallback.onDestroy();
+ } catch (IllegalStateException e) {
+ // WM throws an ISE if mContentView was added twice; this should never happen -
+ // since show() and hide() are always called in the UIThread - but when it does,
+ // it should not crash the system.
+ Slog.e(TAG, "Exception showing window " + params, e);
+ mCallback.onDestroy();
}
}
@@ -405,10 +411,18 @@
* Hides the window.
*/
void hide() {
- if (mShowing) {
- mContentView.setOnTouchListener(null);
- mWm.removeView(mContentView);
- mShowing = false;
+ try {
+ if (mShowing) {
+ mContentView.setOnTouchListener(null);
+ mWm.removeView(mContentView);
+ mShowing = false;
+ }
+ } catch (IllegalStateException e) {
+ // WM might thrown an ISE when removing the mContentView; this should never
+ // happen - since show() and hide() are always called in the UIThread - but if it
+ // does, it should not crash the system.
+ Slog.e(TAG, "Exception hiding window ", e);
+ mCallback.onDestroy();
}
}
@@ -489,7 +503,7 @@
final String value = item.getValue();
// No value, i.e. null, matches any filter
if (value == null
- || value.toLowerCase().contains(constraintLowerCase)) {
+ || value.toLowerCase().startsWith(constraintLowerCase)) {
filteredItems.add(item);
}
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index d25ffce..491af91 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -17,6 +17,7 @@
package com.android.server.autofill.ui;
import static com.android.server.autofill.Helper.sDebug;
+import static com.android.server.autofill.Helper.sVerbose;
import android.annotation.NonNull;
import android.app.Dialog;
@@ -63,7 +64,7 @@
@Override
public void onSave() {
- if (sDebug) Slog.d(TAG, "onSave(): " + mDone);
+ if (sDebug) Slog.d(TAG, "OneTimeListener.onSave(): " + mDone);
if (mDone) {
return;
}
@@ -73,7 +74,7 @@
@Override
public void onCancel(IntentSender listener) {
- if (sDebug) Slog.d(TAG, "onCancel(): " + mDone);
+ if (sDebug) Slog.d(TAG, "OneTimeListener.onCancel(): " + mDone);
if (mDone) {
return;
}
@@ -83,7 +84,7 @@
@Override
public void onDestroy() {
- if (sDebug) Slog.d(TAG, "onDestroy(): " + mDone);
+ if (sDebug) Slog.d(TAG, "OneTimeListener.onDestroy(): " + mDone);
if (mDone) {
return;
}
@@ -158,9 +159,8 @@
subTitleView.setVisibility(View.VISIBLE);
}
- Slog.i(TAG, "Showing save dialog: " + mTitle);
if (sDebug) {
- Slog.d(TAG, "SubTitle: " + mSubTitle);
+ Slog.d(TAG, "on constructor: title=" + mTitle + ", subTitle=" + mSubTitle);
}
final TextView noButton = view.findViewById(R.id.autofill_save_no);
@@ -169,15 +169,15 @@
} else {
noButton.setText(R.string.autofill_save_no);
}
- noButton.setOnClickListener((v) -> mListener.onCancel(
- info.getNegativeActionListener()));
+ View.OnClickListener cancelListener =
+ (v) -> mListener.onCancel(info.getNegativeActionListener());
+ noButton.setOnClickListener(cancelListener);
final View yesButton = view.findViewById(R.id.autofill_save_yes);
yesButton.setOnClickListener((v) -> mListener.onSave());
final View closeButton = view.findViewById(R.id.autofill_save_close);
- closeButton.setOnClickListener((v) -> mListener.onCancel(
- info.getNegativeActionListener()));
+ closeButton.setOnClickListener(cancelListener);
mDialog = new Dialog(context, R.style.Theme_DeviceDefault_Light_Panel);
mDialog.setContentView(view);
@@ -195,13 +195,16 @@
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.accessibilityTitle = context.getString(R.string.autofill_save_accessibility_title);
+ Slog.i(TAG, "Showing save dialog: " + mTitle);
mDialog.show();
}
void destroy() {
+ if (sDebug) Slog.d(TAG, "destroy()");
throwIfDestroyed();
mListener.onDestroy();
mHandler.removeCallbacksAndMessages(mListener);
+ if (sVerbose) Slog.v(TAG, "destroy(): dismissing dialog");
mDialog.dismiss();
mDestroyed = true;
}
@@ -212,6 +215,11 @@
}
}
+ @Override
+ public String toString() {
+ return mTitle == null ? "NO TITLE" : mTitle.toString();
+ }
+
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("title: "); pw.println(mTitle);
pw.print(prefix); pw.print("subtitle: "); pw.println(mSubTitle);
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 03e9dd2..16e63b3 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -73,6 +73,7 @@
private final LinkedList<VibrationInfo> mPreviousVibrations;
private final int mPreviousVibrationsLimit;
+ private final boolean mAllowPriorityVibrationsInLowPowerMode;
private final boolean mSupportsAmplitudeControl;
private final int mDefaultVibrationAmplitude;
private final VibrationEffect[] mFallbackEffects;
@@ -213,6 +214,9 @@
mDefaultVibrationAmplitude = mContext.getResources().getInteger(
com.android.internal.R.integer.config_defaultVibrationAmplitude);
+ mAllowPriorityVibrationsInLowPowerMode = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_allowPriorityVibrationsInLowPowerMode);
+
mPreviousVibrations = new LinkedList<>();
IntentFilter filter = new IntentFilter();
@@ -456,7 +460,7 @@
}
private void startVibrationLocked(final Vibration vib) {
- if (mLowPowerMode && vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
+ if (!isAllowedToVibrate(vib)) {
if (DEBUG) {
Slog.e(TAG, "Vibrate ignored, low power mode");
}
@@ -505,6 +509,26 @@
}
}
+ private boolean isAllowedToVibrate(Vibration vib) {
+ if (!mLowPowerMode) {
+ return true;
+ }
+ if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
+ return true;
+ }
+ if (!mAllowPriorityVibrationsInLowPowerMode) {
+ return false;
+ }
+ if (vib.mUsageHint == AudioAttributes.USAGE_ALARM ||
+ vib.mUsageHint == AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY ||
+ vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST) {
+
+ return true;
+ }
+
+ return false;
+ }
+
private boolean shouldVibrateForRingtone() {
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
int ringerMode = audioManager.getRingerModeInternal();
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index feb9ce4..b18fa32 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -76,6 +76,7 @@
"/system/bin/sdcard",
"/system/bin/surfaceflinger",
"media.extractor", // system/bin/mediaextractor
+ "media.codec", // vendor/bin/hw/android.hardware.media.omx@1.0-service
"com.android.bluetooth", // Bluetooth service
};
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 36c3f7d..f0b1b3b 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -23,8 +23,10 @@
import android.accounts.AccountAuthenticatorResponse;
import android.accounts.AccountManager;
import android.accounts.AccountManagerInternal;
+import android.accounts.AccountManagerResponse;
import android.accounts.AuthenticatorDescription;
import android.accounts.CantAddAccountActivity;
+import android.accounts.ChooseAccountActivity;
import android.accounts.GrantCredentialsPermissionActivity;
import android.accounts.IAccountAuthenticator;
import android.accounts.IAccountAuthenticatorResponse;
@@ -71,6 +73,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
+import android.os.Parcelable;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
@@ -748,6 +751,11 @@
}
}
+ private boolean isVisible(int visibility) {
+ return visibility == AccountManager.VISIBILITY_VISIBLE ||
+ visibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE;
+ }
+
/**
* Updates visibility for given account name and package.
*
@@ -800,8 +808,10 @@
if (notify) {
for (Entry<String, Integer> packageToVisibility : packagesToVisibility
.entrySet()) {
- if (shouldNotifyOnVisibilityChange(packageToVisibility.getValue(),
- resolveAccountVisibility(account, packageName, accounts))) {
+ int oldVisibility = packageToVisibility.getValue();
+ int currentVisibility =
+ resolveAccountVisibility(account, packageName, accounts);
+ if (isVisible(oldVisibility) != isVisible(currentVisibility)) {
notifyPackage(packageToVisibility.getKey(), accounts);
}
}
@@ -1178,8 +1188,7 @@
for (Entry<String, Integer> packageToVisibility :
packagesToVisibility.entrySet()) {
- if (shouldNotifyOnVisibilityChange(packageToVisibility.getValue(),
- AccountManager.VISIBILITY_NOT_VISIBLE)) {
+ if (isVisible(packageToVisibility.getValue())) {
notifyPackage(packageToVisibility.getKey(), accounts);
}
}
@@ -1215,14 +1224,6 @@
}
}
- private boolean shouldNotifyOnVisibilityChange(int oldVisibility, int newVisibility) {
- boolean oldVisible = (oldVisibility == AccountManager.VISIBILITY_VISIBLE) ||
- (oldVisibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
- boolean newVisible = (newVisibility == AccountManager.VISIBILITY_VISIBLE) ||
- (newVisibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
- return oldVisible == newVisible;
- }
-
private SparseBooleanArray getUidsOfInstalledOrUpdatedPackagesAsUser(int userId) {
// Get the UIDs of all apps that might have data on the device. We want
// to preserve user data if the app might otherwise be storing data.
@@ -4042,6 +4043,7 @@
private volatile int mCurrentAccount = 0;
private final int mCallingUid;
private final String mPackageName;
+ private final boolean mIncludeManagedNotVisible;
public GetAccountsByTypeAndFeatureSession(
UserAccounts accounts,
@@ -4049,19 +4051,21 @@
String type,
String[] features,
int callingUid,
- String packageName) {
+ String packageName,
+ boolean includeManagedNotVisible) {
super(accounts, response, type, false /* expectActivityLaunch */,
true /* stripAuthTokenFromResult */, null /* accountName */,
false /* authDetailsRequired */);
mCallingUid = callingUid;
mFeatures = features;
mPackageName = packageName;
+ mIncludeManagedNotVisible = includeManagedNotVisible;
}
@Override
public void run() throws RemoteException {
mAccountsOfType = getAccountsFromCache(mAccounts, mAccountType,
- mCallingUid, mPackageName, false /* include managed not visible*/);
+ mCallingUid, mPackageName, mIncludeManagedNotVisible);
// check whether each account matches the requested features
mAccountsWithFeatures = new ArrayList<>(mAccountsOfType.length);
mCurrentAccount = 0;
@@ -4422,10 +4426,120 @@
&& (type != null && !isAccountManagedByCaller(type, callingUid, userId))) {
return EMPTY_ACCOUNT_ARRAY;
}
+ if (!UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) && type == null) {
+ return getAccountsAsUserForPackage(type, userId,
+ packageName, packageUid, opPackageName, false /* includeUserManagedNotVisible */);
+ }
return getAccountsAsUserForPackage(type, userId,
packageName, packageUid, opPackageName, true /* includeUserManagedNotVisible */);
}
+ private boolean needToStartChooseAccountActivity(Account[] accounts, String callingPackage) {
+ if (accounts.length < 1) return false;
+ if (accounts.length > 1) return true;
+ Account account = accounts[0];
+ UserAccounts userAccounts = getUserAccounts(UserHandle.getCallingUserId());
+ int visibility = resolveAccountVisibility(account, callingPackage, userAccounts);
+ if (visibility == AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE) return true;
+ return false;
+ }
+
+ private void startChooseAccountActivityWithAccounts(
+ IAccountManagerResponse response, Account[] accounts) {
+ Intent intent = new Intent(mContext, ChooseAccountActivity.class);
+ intent.putExtra(AccountManager.KEY_ACCOUNTS, accounts);
+ intent.putExtra(AccountManager.KEY_ACCOUNT_MANAGER_RESPONSE,
+ new AccountManagerResponse(response));
+
+ mContext.startActivityAsUser(intent, UserHandle.of(UserHandle.getCallingUserId()));
+ }
+
+ private void handleGetAccountsResult(
+ IAccountManagerResponse response,
+ Account[] accounts,
+ String callingPackage) {
+
+ if (needToStartChooseAccountActivity(accounts, callingPackage)) {
+ startChooseAccountActivityWithAccounts(response, accounts);
+ return;
+ }
+ if (accounts.length == 1) {
+ Bundle bundle = new Bundle();
+ bundle.putString(AccountManager.KEY_ACCOUNT_NAME, accounts[0].name);
+ bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, accounts[0].type);
+ onResult(response, bundle);
+ return;
+ }
+ // No qualified account exists, return an empty Bundle.
+ onResult(response, new Bundle());
+ }
+
+ @Override
+ public void getAccountByTypeAndFeatures(
+ IAccountManagerResponse response,
+ String accountType,
+ String[] features,
+ String opPackageName) {
+
+ int callingUid = Binder.getCallingUid();
+ mAppOpsManager.checkPackage(callingUid, opPackageName);
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "getAccount: accountType " + accountType
+ + ", response " + response
+ + ", features " + Arrays.toString(features)
+ + ", caller's uid " + callingUid
+ + ", pid " + Binder.getCallingPid());
+ }
+ if (response == null) throw new IllegalArgumentException("response is null");
+ if (accountType == null) throw new IllegalArgumentException("accountType is null");
+
+ int userId = UserHandle.getCallingUserId();
+
+ long identityToken = clearCallingIdentity();
+ try {
+ UserAccounts userAccounts = getUserAccounts(userId);
+ if (ArrayUtils.isEmpty(features)) {
+ Account[] accountsWithManagedNotVisible = getAccountsFromCache(
+ userAccounts, accountType, callingUid, opPackageName,
+ true /* include managed not visible */);
+ handleGetAccountsResult(
+ response, accountsWithManagedNotVisible, opPackageName);
+ return;
+ }
+
+ IAccountManagerResponse retrieveAccountsResponse =
+ new IAccountManagerResponse.Stub() {
+ @Override
+ public void onResult(Bundle value) throws RemoteException {
+ Parcelable[] parcelables = value.getParcelableArray(
+ AccountManager.KEY_ACCOUNTS);
+ Account[] accounts = new Account[parcelables.length];
+ for (int i = 0; i < parcelables.length; i++) {
+ accounts[i] = (Account) parcelables[i];
+ }
+ handleGetAccountsResult(
+ response, accounts, opPackageName);
+ }
+
+ @Override
+ public void onError(int errorCode, String errorMessage)
+ throws RemoteException {
+ // Will not be called in this case.
+ }
+ };
+ new GetAccountsByTypeAndFeatureSession(
+ userAccounts,
+ retrieveAccountsResponse,
+ accountType,
+ features,
+ callingUid,
+ opPackageName,
+ true /* include managed not visible */).bind();
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
+ }
+
@Override
public void getAccountsByFeatures(
IAccountManagerResponse response,
@@ -4458,6 +4572,7 @@
}
return;
}
+
long identityToken = clearCallingIdentity();
try {
UserAccounts userAccounts = getUserAccounts(userId);
@@ -4475,7 +4590,8 @@
type,
features,
callingUid,
- opPackageName).bind();
+ opPackageName,
+ false /* include managed not visible */).bind();
} finally {
restoreCallingIdentity(identityToken);
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 2680b425..c417484 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -162,7 +162,7 @@
/**
* Information about an app that is currently running one or more foreground services.
- * (This mapps directly to the running apps we show in the notification.)
+ * (This maps directly to the running apps we show in the notification.)
*/
static final class ActiveForegroundApp {
String mPackageName;
@@ -813,6 +813,8 @@
String title;
String msg;
String[] pkgs;
+ final long nowElapsed = SystemClock.elapsedRealtime();
+ long oldestStartTime = nowElapsed;
if (active.size() == 1) {
intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", active.get(0).mPackageName, null));
@@ -820,11 +822,13 @@
R.string.foreground_service_app_in_background, active.get(0).mLabel);
msg = context.getString(R.string.foreground_service_tap_for_details);
pkgs = new String[] { active.get(0).mPackageName };
+ oldestStartTime = active.get(0).mStartTime;
} else {
intent = new Intent(Settings.ACTION_FOREGROUND_SERVICES_SETTINGS);
pkgs = new String[active.size()];
for (int i = 0; i < active.size(); i++) {
pkgs[i] = active.get(i).mPackageName;
+ oldestStartTime = Math.min(oldestStartTime, active.get(i).mStartTime);
}
intent.putExtra("packages", pkgs);
title = context.getString(
@@ -841,9 +845,10 @@
new Notification.Builder(context,
SystemNotificationChannels.FOREGROUND_SERVICE)
.addExtras(notificationBundle)
- .setSmallIcon(R.drawable.ic_check_circle_24px)
+ .setSmallIcon(R.drawable.stat_sys_vitals)
.setOngoing(true)
- .setShowWhen(false)
+ .setShowWhen(oldestStartTime < nowElapsed)
+ .setWhen(System.currentTimeMillis() - (nowElapsed - oldestStartTime))
.setColor(context.getColor(
com.android.internal.R.color.system_notification_accent_color))
.setContentTitle(title)
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f3ecfeb..c958313 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -19158,10 +19158,11 @@
final Uri data = intent.getData();
final String ssp;
if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
- final ApplicationInfo aInfo =
- getPackageManagerInternalLocked().getApplicationInfo(
- ssp,
- userId);
+ ApplicationInfo aInfo = null;
+ try {
+ aInfo = AppGlobals.getPackageManager()
+ .getApplicationInfo(ssp, 0 /*flags*/, userId);
+ } catch (RemoteException ignore) {}
if (aInfo == null) {
Slog.w(TAG, "Dropping ACTION_PACKAGE_REPLACED for non-existent pkg:"
+ " ssp=" + ssp + " data=" + data);
@@ -24281,7 +24282,6 @@
}
void updateApplicationInfoLocked(@NonNull List<String> packagesToUpdate, int userId) {
- final PackageManagerInternal packageManager = getPackageManagerInternalLocked();
final boolean updateFrameworkRes = packagesToUpdate.contains("android");
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
final ProcessRecord app = mLruProcesses.get(i);
@@ -24298,8 +24298,8 @@
final String packageName = app.pkgList.keyAt(j);
if (updateFrameworkRes || packagesToUpdate.contains(packageName)) {
try {
- final ApplicationInfo ai = packageManager.getApplicationInfo(
- packageName, app.userId);
+ final ApplicationInfo ai = AppGlobals.getPackageManager()
+ .getApplicationInfo(packageName, 0 /*flags*/, app.userId);
if (ai != null) {
app.thread.scheduleApplicationInfoChanged(ai);
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 9698a8f..ec6a4f6 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1426,7 +1426,7 @@
pendingOptions.getStartX(), pendingOptions.getStartY(),
pendingOptions.getOnAnimationStartListener(),
scaleUp);
- if (intent.getSourceBounds() == null) {
+ if (intent.getSourceBounds() == null && buffer != null) {
intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
pendingOptions.getStartY(),
pendingOptions.getStartX() + buffer.getWidth(),
diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
index ea9ff59..8297169 100644
--- a/services/core/java/com/android/server/am/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
@@ -16,7 +16,6 @@
package com.android.server.am;
-import android.app.ActivityManager;
import android.app.ActivityManager.TaskSnapshot;
import android.app.ITaskStackListener;
import android.app.ActivityManager.TaskDescription;
@@ -31,27 +30,27 @@
import java.util.ArrayList;
class TaskChangeNotificationController {
- static final int LOG_STACK_STATE_MSG = 1;
- static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG = 2;
- static final int NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG = 3;
- static final int NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG = 4;
- static final int NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG = 5;
- static final int NOTIFY_FORCED_RESIZABLE_MSG = 6;
- static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 7;
- static final int NOTIFY_TASK_ADDED_LISTENERS_MSG = 8;
- static final int NOTIFY_TASK_REMOVED_LISTENERS_MSG = 9;
- static final int NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG = 10;
- static final int NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG = 11;
- static final int NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS = 12;
- static final int NOTIFY_TASK_REMOVAL_STARTED_LISTENERS = 13;
- static final int NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG = 14;
- static final int NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG = 15;
- static final int NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG = 16;
- static final int NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG = 17;
- static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG = 18;
+ private static final int LOG_STACK_STATE_MSG = 1;
+ private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG = 2;
+ private static final int NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG = 3;
+ private static final int NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG = 4;
+ private static final int NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG = 5;
+ private static final int NOTIFY_FORCED_RESIZABLE_MSG = 6;
+ private static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 7;
+ private static final int NOTIFY_TASK_ADDED_LISTENERS_MSG = 8;
+ private static final int NOTIFY_TASK_REMOVED_LISTENERS_MSG = 9;
+ private static final int NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG = 10;
+ private static final int NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG = 11;
+ private static final int NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS = 12;
+ private static final int NOTIFY_TASK_REMOVAL_STARTED_LISTENERS = 13;
+ private static final int NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG = 14;
+ private static final int NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG = 15;
+ private static final int NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG = 16;
+ private static final int NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG = 17;
+ private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG = 18;
// Delay in notifying task stack change listeners (in millis)
- static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
+ private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
private final ActivityManagerService mService;
private final ActivityStackSupervisor mStackSupervisor;
@@ -242,7 +241,7 @@
}
}
- void forAllRemoteListeners(TaskStackConsumer callback, Message message) {
+ private void forAllRemoteListeners(TaskStackConsumer callback, Message message) {
synchronized (mService) {
for (int i = mRemoteTaskStackListeners.beginBroadcast() - 1; i >= 0; i--) {
try {
@@ -256,7 +255,7 @@
}
}
- void forAllLocalListeners(TaskStackConsumer callback, Message message) {
+ private void forAllLocalListeners(TaskStackConsumer callback, Message message) {
synchronized (mService) {
for (int i = mLocalTaskStackListeners.size() - 1; i >= 0; i--) {
try {
@@ -329,8 +328,9 @@
void notifyActivityDismissingDockedStack() {
mHandler.removeMessages(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
- final Message message = mHandler.obtainMessage(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
- forAllLocalListeners(mNotifyActivityDismissingDockedStack, message);
+ final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
+ forAllLocalListeners(mNotifyActivityDismissingDockedStack, msg);
+ msg.sendToTarget();
}
void notifyActivityForcedResizable(int taskId, int reason, String packageName) {
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 901092e..3f825c5 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -18,7 +18,13 @@
import static android.hardware.usb.UsbManager.USB_CONNECTED;
import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_UNSPECIFIED;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
import static com.android.server.ConnectivityService.SHORT_ARG;
@@ -799,48 +805,73 @@
}
private void handleWifiApAction(Intent intent) {
- final int curState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
+ final int curState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
+ final String ifname = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME);
+ final int ipmode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, IFACE_IP_MODE_UNSPECIFIED);
+
synchronized (Tethering.this.mPublicSync) {
switch (curState) {
case WifiManager.WIFI_AP_STATE_ENABLING:
// We can see this state on the way to both enabled and failure states.
break;
case WifiManager.WIFI_AP_STATE_ENABLED:
- // When the AP comes up and we've been requested to tether it, do so.
- // Otherwise, assume it's a local-only hotspot request.
- final int state = mWifiTetherRequested
- ? IControlsTethering.STATE_TETHERED
- : IControlsTethering.STATE_LOCAL_ONLY;
- tetherMatchingInterfaces(state, ConnectivityManager.TETHERING_WIFI);
+ enableWifiIpServingLocked(ifname, ipmode);
break;
case WifiManager.WIFI_AP_STATE_DISABLED:
case WifiManager.WIFI_AP_STATE_DISABLING:
case WifiManager.WIFI_AP_STATE_FAILED:
default:
- if (DBG) {
- Log.d(TAG, "Canceling WiFi tethering request - AP_STATE=" +
- curState);
- }
- // Tell appropriate interface state machines that they should tear
- // themselves down.
- for (int i = 0; i < mTetherStates.size(); i++) {
- TetherInterfaceStateMachine tism =
- mTetherStates.valueAt(i).stateMachine;
- if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
- tism.sendMessage(
- TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
- break; // There should be at most one of these.
- }
- }
- // Regardless of whether we requested this transition, the AP has gone
- // down. Don't try to tether again unless we're requested to do so.
- mWifiTetherRequested = false;
- break;
+ disableWifiIpServingLocked(curState);
+ break;
}
}
}
}
+ // TODO: Pass in the interface name and, if non-empty, only turn down IP
+ // serving on that one interface.
+ private void disableWifiIpServingLocked(int apState) {
+ if (DBG) Log.d(TAG, "Canceling WiFi tethering request - AP_STATE=" + apState);
+
+ // Tell appropriate interface state machines that they should tear
+ // themselves down.
+ for (int i = 0; i < mTetherStates.size(); i++) {
+ TetherInterfaceStateMachine tism = mTetherStates.valueAt(i).stateMachine;
+ if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
+ tism.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
+ break; // There should be at most one of these.
+ }
+ }
+ // Regardless of whether we requested this transition, the AP has gone
+ // down. Don't try to tether again unless we're requested to do so.
+ mWifiTetherRequested = false;
+ }
+
+ private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {
+ // Map wifiIpMode values to IControlsTethering serving states, inferring
+ // from mWifiTetherRequested as a final "best guess".
+ final int ipServingMode;
+ switch (wifiIpMode) {
+ case IFACE_IP_MODE_TETHERED:
+ ipServingMode = IControlsTethering.STATE_TETHERED;
+ break;
+ case IFACE_IP_MODE_LOCAL_ONLY:
+ ipServingMode = IControlsTethering.STATE_LOCAL_ONLY;
+ break;
+ default:
+ mLog.e("Cannot enable IP serving in unknown WiFi mode: " + wifiIpMode);
+ return;
+ }
+
+ if (!TextUtils.isEmpty(ifname)) {
+ changeInterfaceState(ifname, ipServingMode);
+ } else {
+ mLog.e(String.format(
+ "Cannot enable IP serving in mode %s on missing interface name",
+ ipServingMode));
+ }
+ }
+
// TODO: Consider renaming to something more accurate in its description.
// This method:
// - allows requesting either tethering or local hotspot serving states
@@ -873,22 +904,26 @@
return;
}
+ changeInterfaceState(chosenIface, requestedState);
+ }
+
+ private void changeInterfaceState(String ifname, int requestedState) {
final int result;
switch (requestedState) {
case IControlsTethering.STATE_UNAVAILABLE:
case IControlsTethering.STATE_AVAILABLE:
- result = untether(chosenIface);
+ result = untether(ifname);
break;
case IControlsTethering.STATE_TETHERED:
case IControlsTethering.STATE_LOCAL_ONLY:
- result = tether(chosenIface, requestedState);
+ result = tether(ifname, requestedState);
break;
default:
Log.wtf(TAG, "Unknown interface state: " + requestedState);
return;
}
if (result != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
- Log.e(TAG, "unable start or stop tethering on iface " + chosenIface);
+ Log.e(TAG, "unable start or stop tethering on iface " + ifname);
return;
}
}
@@ -1470,10 +1505,10 @@
final String iface = who.interfaceName();
switch (mode) {
case IControlsTethering.STATE_TETHERED:
- mgr.updateInterfaceIpState(iface, WifiManager.IFACE_IP_MODE_TETHERED);
+ mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_TETHERED);
break;
case IControlsTethering.STATE_LOCAL_ONLY:
- mgr.updateInterfaceIpState(iface, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
+ mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_LOCAL_ONLY);
break;
default:
Log.wtf(TAG, "Unknown active serving mode: " + mode);
@@ -1491,7 +1526,7 @@
if (who.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
if (who.lastError() != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
getWifiManager().updateInterfaceIpState(
- who.interfaceName(), WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
+ who.interfaceName(), IFACE_IP_MODE_CONFIGURATION_ERROR);
}
}
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 6941193..e87d860 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -77,6 +77,9 @@
public TetheringConfiguration(Context ctx) {
tetherableUsbRegexs = ctx.getResources().getStringArray(
com.android.internal.R.array.config_tether_usb_regexs);
+ // TODO: Evaluate deleting this altogether now that Wi-Fi always passes
+ // us an interface name. Careful consideration needs to be given to
+ // implications for Settings and for provisioning checks.
tetherableWifiRegexs = ctx.getResources().getStringArray(
com.android.internal.R.array.config_tether_wifi_regexs);
tetherableBluetoothRegexs = ctx.getResources().getStringArray(
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 1504538..3ca65cd 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1858,7 +1858,7 @@
account.account.name, account.userId, account.account.type);
pw.println("=======================================================================");
- final PrintTable table = new PrintTable(12);
+ final PrintTable table = new PrintTable(13);
table.set(0, 0,
"Authority", // 0
"Syncable", // 1
@@ -1871,7 +1871,8 @@
"User", // 8
"Tot", // 9
"Time", // 10
- "Last Sync" // 11
+ "Last Sync", // 11
+ "Etc" // 12
);
final List<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> sorted =
@@ -1921,6 +1922,7 @@
}
}
+ row1 = row;
if (status.lastSuccessTime != 0) {
table.set(row1++, 11, SyncStorageEngine.SOURCES[status.lastSuccessSource]
+ " " + "SUCCESS");
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 9dc317a..e82724d 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -104,6 +104,11 @@
// Trigger proximity if distance is less than 5 cm.
private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
+ // State machine constants for tracking initial brightness ramp skipping when enabled.
+ private static final int RAMP_STATE_SKIP_NONE = 0;
+ private static final int RAMP_STATE_SKIP_INITIAL = 1;
+ private static final int RAMP_STATE_SKIP_AUTOBRIGHT = 2;
+
private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;
private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
@@ -239,6 +244,9 @@
// Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_SCREEN_* fields.
private int mReportedScreenStateToPolicy;
+ // If the last recorded screen state was dozing or not.
+ private boolean mDozing;
+
// Remembers whether certain kinds of brightness adjustments
// were recently applied so that we can decide how to transition.
private boolean mAppliedAutoBrightness;
@@ -249,6 +257,15 @@
private final int mBrightnessRampRateFast;
private final int mBrightnessRampRateSlow;
+ // Whether or not to skip the initial brightness ramps into STATE_ON.
+ private final boolean mSkipScreenOnBrightnessRamp;
+
+ // A record of state for skipping brightness ramps.
+ private int mSkipRampState = RAMP_STATE_SKIP_NONE;
+
+ // The first autobrightness value set when entering RAMP_STATE_SKIP_INITIAL.
+ private int mInitialAutoBrightness;
+
// The controller for the automatic brightness level.
private AutomaticBrightnessController mAutomaticBrightnessController;
@@ -312,6 +329,8 @@
com.android.internal.R.integer.config_brightness_ramp_rate_fast);
mBrightnessRampRateSlow = resources.getInteger(
com.android.internal.R.integer.config_brightness_ramp_rate_slow);
+ mSkipScreenOnBrightnessRamp = resources.getBoolean(
+ com.android.internal.R.bool.config_skipScreenOnBrightnessRamp);
int lightSensorRate = resources.getInteger(
com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
@@ -731,8 +750,29 @@
// Animate the screen brightness when the screen is on or dozing.
// Skip the animation when the screen is off or suspended or transition to/from VR.
if (!mPendingScreenOff) {
+ if (mSkipScreenOnBrightnessRamp) {
+
+ if (state == Display.STATE_ON) {
+ if (mSkipRampState == RAMP_STATE_SKIP_NONE && mDozing) {
+ mInitialAutoBrightness = brightness;
+ mSkipRampState = RAMP_STATE_SKIP_INITIAL;
+ } else if (mSkipRampState == RAMP_STATE_SKIP_INITIAL
+ && mUseSoftwareAutoBrightnessConfig
+ && brightness != mInitialAutoBrightness) {
+ mSkipRampState = RAMP_STATE_SKIP_AUTOBRIGHT;
+ } else if (mSkipRampState == RAMP_STATE_SKIP_AUTOBRIGHT) {
+ mSkipRampState = RAMP_STATE_SKIP_NONE;
+ }
+ } else {
+ mSkipRampState = RAMP_STATE_SKIP_NONE;
+ }
+ }
+
boolean wasOrWillBeInVr = (state == Display.STATE_VR || oldState == Display.STATE_VR);
- if ((state == Display.STATE_ON || state == Display.STATE_DOZE) && !wasOrWillBeInVr) {
+ if ((state == Display.STATE_ON
+ && mSkipRampState == RAMP_STATE_SKIP_NONE
+ || state == Display.STATE_DOZE)
+ && !wasOrWillBeInVr) {
animateScreenBrightness(brightness,
slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
} else {
@@ -790,6 +830,9 @@
mUnfinishedBusiness = false;
mCallbacks.releaseSuspendBlocker();
}
+
+ // Record if dozing for future comparison.
+ mDozing = state != Display.STATE_ON;
}
@Override
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index 9862516..e2fd0ac 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -369,8 +369,8 @@
mPendingBacklight = backlight;
boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;
- mStateChangeInProgress = stateChanged;
- mBacklightChangeInProgress = backlightChanged;
+ mStateChangeInProgress = stateChanged || mStateChangeInProgress;
+ mBacklightChangeInProgress = backlightChanged || mBacklightChangeInProgress;
if (!changeInProgress) {
mLock.notifyAll();
diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java
index d574265..b3cf57b 100644
--- a/services/core/java/com/android/server/display/NightDisplayService.java
+++ b/services/core/java/com/android/server/display/NightDisplayService.java
@@ -285,12 +285,6 @@
if (mIsActivated == null || mIsActivated != activated) {
Slog.i(TAG, activated ? "Turning on night display" : "Turning off night display");
- if (mIsActivated != null) {
- Secure.putLongForUser(getContext().getContentResolver(),
- Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, System.currentTimeMillis(),
- mCurrentUser);
- }
-
mIsActivated = activated;
if (mAutoMode != null) {
@@ -430,19 +424,6 @@
outTemp[10] = blue;
}
- private Calendar getLastActivatedTime() {
- final ContentResolver cr = getContext().getContentResolver();
- final long lastActivatedTimeMillis = Secure.getLongForUser(
- cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1, mCurrentUser);
- if (lastActivatedTimeMillis < 0) {
- return null;
- }
-
- final Calendar lastActivatedTime = Calendar.getInstance();
- lastActivatedTime.setTimeInMillis(lastActivatedTimeMillis);
- return lastActivatedTime;
- }
-
private abstract class AutoMode implements NightDisplayController.Callback {
public abstract void onStart();
@@ -522,7 +503,7 @@
mStartTime = mController.getCustomStartTime();
mEndTime = mController.getCustomEndTime();
- mLastActivatedTime = getLastActivatedTime();
+ mLastActivatedTime = mController.getLastActivatedTime();
// Force an update to initialize state.
updateActivated();
@@ -538,7 +519,7 @@
@Override
public void onActivated(boolean activated) {
- mLastActivatedTime = getLastActivatedTime();
+ mLastActivatedTime = mController.getLastActivatedTime();
updateNextAlarm(activated, Calendar.getInstance());
}
@@ -579,7 +560,7 @@
}
boolean activate = state.isNight();
- final Calendar lastActivatedTime = getLastActivatedTime();
+ final Calendar lastActivatedTime = mController.getLastActivatedTime();
if (lastActivatedTime != null) {
final Calendar now = Calendar.getInstance();
final Calendar sunrise = state.sunrise();
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 1b984a4..dbccc07 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -86,7 +86,6 @@
private boolean mCurrentDreamCanDoze;
private boolean mCurrentDreamIsDozing;
private boolean mCurrentDreamIsWaking;
- private Runnable mStopDreamRunnable;
private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
@@ -350,11 +349,6 @@
private void startDreamLocked(final ComponentName name,
final boolean isTest, final boolean canDoze, final int userId) {
- if (mStopDreamRunnable != null) {
- mHandler.removeCallbacks(mStopDreamRunnable);
- mStopDreamRunnable = null;
- }
-
if (Objects.equal(mCurrentDreamName, name)
&& mCurrentDreamIsTest == isTest
&& mCurrentDreamCanDoze == canDoze
@@ -392,15 +386,13 @@
mCurrentDreamIsWaking = true;
}
- mStopDreamRunnable = new Runnable() {
+ mHandler.post(new Runnable() {
@Override
public void run() {
Slog.i(TAG, "Performing gentle wake from dream.");
mController.stopDream(immediate);
- mStopDreamRunnable = null;
}
- };
- mHandler.post(mStopDreamRunnable);
+ });
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 13bde3c..19d5f3c 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -149,6 +149,7 @@
import android.widget.Toast;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
@@ -231,7 +232,6 @@
static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_NOTIFICATION;
- static final boolean ENABLE_BLOCKED_NOTIFICATIONS = true;
static final boolean ENABLE_BLOCKED_TOASTS = true;
// When #matchesCallFilter is called from the ringer, wait at most
@@ -689,6 +689,7 @@
}
};
+ @GuardedBy("mNotificationLock")
private void clearSoundLocked() {
mSoundNotificationKey = null;
long identity = Binder.clearCallingIdentity();
@@ -703,6 +704,7 @@
}
}
+ @GuardedBy("mNotificationLock")
private void clearVibrateLocked() {
mVibrateNotificationKey = null;
long identity = Binder.clearCallingIdentity();
@@ -713,6 +715,7 @@
}
}
+ @GuardedBy("mNotificationLock")
private void clearLightsLocked() {
// light
mLights.clear();
@@ -1051,7 +1054,8 @@
@VisibleForTesting
void init(Looper looper, IPackageManager packageManager, PackageManager packageManagerClient,
LightsManager lightsManager, NotificationListeners notificationListeners,
- ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper) {
+ ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper,
+ NotificationUsageStats usageStats) {
Resources resources = getContext().getResources();
mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
@@ -1074,7 +1078,7 @@
} catch (Resources.NotFoundException e) {
extractorNames = new String[0];
}
- mUsageStats = new NotificationUsageStats(getContext());
+ mUsageStats = usageStats;
mRankingHandler = new RankingHandlerWorker(mRankingThread.getLooper());
mRankingHelper = new RankingHelper(getContext(),
getContext().getPackageManager(),
@@ -1243,7 +1247,7 @@
init(Looper.myLooper(), AppGlobals.getPackageManager(), getContext().getPackageManager(),
getLocalService(LightsManager.class), new NotificationListeners(),
- null, snoozeHelper);
+ null, snoozeHelper, new NotificationUsageStats(getContext()));
publishBinderService(Context.NOTIFICATION_SERVICE, mService);
publishLocalService(NotificationManagerInternal.class, mInternalService);
}
@@ -1274,6 +1278,7 @@
}
}
+ @GuardedBy("mNotificationLock")
private void updateListenerHintsLocked() {
final int hints = calculateHints();
if (hints == mListenerHints) return;
@@ -1282,6 +1287,7 @@
scheduleListenerHintsChanged(hints);
}
+ @GuardedBy("mNotificationLock")
private void updateEffectsSuppressorLocked() {
final long updatedSuppressedEffects = calculateSuppressedEffects();
if (updatedSuppressedEffects == mZenModeHelper.getSuppressedEffects()) return;
@@ -1416,6 +1422,7 @@
return suppressedEffects;
}
+ @GuardedBy("mNotificationLock")
private void updateInterruptionFilterLocked() {
int interruptionFilter = mZenModeHelper.getZenModeListenerInterruptionFilter();
if (interruptionFilter == mInterruptionFilter) return;
@@ -1579,7 +1586,7 @@
mRankingHelper.setEnabled(pkg, uid, enabled);
// Now, cancel any outstanding notifications that are part of a just-disabled app
- if (ENABLE_BLOCKED_NOTIFICATIONS && !enabled) {
+ if (!enabled) {
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, null, 0, 0, true,
UserHandle.getUserId(uid), REASON_PACKAGE_BANNED, null);
}
@@ -2074,6 +2081,7 @@
*
* @param info The binder for the listener, to check that the caller is allowed
*/
+ @GuardedBy("mNotificationLock")
private void cancelNotificationFromListenerLocked(ManagedServiceInfo info,
int callingUid, int callingPid, String pkg, String tag, int id, int userId) {
cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
@@ -2770,25 +2778,28 @@
}
}
+ @GuardedBy("mNotificationLock")
private void addAutogroupKeyLocked(String key) {
NotificationRecord n = mNotificationsByKey.get(key);
if (n == null) {
return;
}
- n.sbn.setOverrideGroupKey(GroupHelper.AUTOGROUP_KEY);
+ n.setOverrideGroupKey(GroupHelper.AUTOGROUP_KEY);
EventLogTags.writeNotificationAutogrouped(key);
}
+ @GuardedBy("mNotificationLock")
private void removeAutogroupKeyLocked(String key) {
NotificationRecord n = mNotificationsByKey.get(key);
if (n == null) {
return;
}
- n.sbn.setOverrideGroupKey(null);
+ n.setOverrideGroupKey(null);
EventLogTags.writeNotificationUnautogrouped(key);
}
// Clears the 'fake' auto-group summary.
+ @GuardedBy("mNotificationLock")
private void clearAutogroupSummaryLocked(int userId, String pkg) {
ArrayMap<String, String> summaries = mAutobundledSummaries.get(userId);
if (summaries != null && summaries.containsKey(pkg)) {
@@ -3109,10 +3120,12 @@
});
}
+ @GuardedBy("mNotificationLock")
private void removeForegroundServiceFlagByListLocked(
- ArrayList<NotificationRecord> notificationList, String pkg, int notificationId, int userId) {
- NotificationRecord r =
- findNotificationByListLocked(notificationList, pkg, null, notificationId, userId);
+ ArrayList<NotificationRecord> notificationList, String pkg, int notificationId,
+ int userId) {
+ NotificationRecord r = findNotificationByListLocked(
+ notificationList, pkg, null, notificationId, userId);
if (r == null) {
return;
}
@@ -3194,7 +3207,7 @@
user, null, System.currentTimeMillis());
final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
- if (!checkDisqualifyingFeatures(userId, notificationUid, id,tag, r)) {
+ if (!checkDisqualifyingFeatures(userId, notificationUid, id, tag, r)) {
return;
}
@@ -3337,7 +3350,8 @@
return isPackageSuspended;
}
- final boolean isBlocked = r.getImportance() == NotificationManager.IMPORTANCE_NONE
+ final boolean isBlocked =
+ mRankingHelper.getImportance(pkg, callingUid) == NotificationManager.IMPORTANCE_NONE
|| r.getChannel().getImportance() == NotificationManager.IMPORTANCE_NONE;
if (isBlocked) {
Slog.e(TAG, "Suppressing notification from package by user request.");
@@ -3367,6 +3381,7 @@
}
}
+ @GuardedBy("mNotificationLock")
void snoozeLocked(NotificationRecord r) {
if (r.sbn.isGroup()) {
final List<NotificationRecord> groupNotifications = findGroupNotificationsLocked(
@@ -3398,6 +3413,7 @@
}
}
+ @GuardedBy("mNotificationLock")
void snoozeNotificationLocked(NotificationRecord r) {
MetricsLogger.action(r.getLogMaker()
.setCategory(MetricsEvent.NOTIFICATION_SNOOZED)
@@ -3586,6 +3602,7 @@
*
* <p>Updates mSummaryByGroupKey.</p>
*/
+ @GuardedBy("mNotificationLock")
private void handleGroupedNotificationLocked(NotificationRecord r, NotificationRecord old,
int callingUid, int callingPid) {
StatusBarNotification sbn = r.sbn;
@@ -3626,6 +3643,7 @@
}
@VisibleForTesting
+ @GuardedBy("mNotificationLock")
void scheduleTimeoutLocked(NotificationRecord record) {
if (record.getNotification().getTimeoutAfter() > 0) {
final PendingIntent pi = PendingIntent.getBroadcast(getContext(),
@@ -3642,6 +3660,7 @@
}
@VisibleForTesting
+ @GuardedBy("mNotificationLock")
void buzzBeepBlinkLocked(NotificationRecord record) {
boolean buzz = false;
boolean beep = false;
@@ -3752,6 +3771,7 @@
}
}
+ @GuardedBy("mNotificationLock")
boolean shouldMuteNotificationLocked(final NotificationRecord record) {
final Notification notification = record.getNotification();
if(record.isUpdate
@@ -3861,6 +3881,7 @@
}.start();
}
+ @GuardedBy("mToastQueue")
void showNextToastLocked() {
ToastRecord record = mToastQueue.get(0);
while (record != null) {
@@ -3887,6 +3908,7 @@
}
}
+ @GuardedBy("mToastQueue")
void cancelToastLocked(int index) {
ToastRecord record = mToastQueue.get(index);
try {
@@ -3910,6 +3932,7 @@
}
}
+ @GuardedBy("mToastQueue")
private void scheduleTimeoutLocked(ToastRecord r)
{
mHandler.removeCallbacksAndMessages(r);
@@ -3929,7 +3952,7 @@
}
}
- // lock on mToastQueue
+ @GuardedBy("mToastQueue")
int indexOfToastLocked(String pkg, ITransientNotification callback)
{
IBinder cbak = callback.asBinder();
@@ -3944,7 +3967,7 @@
return -1;
}
- // lock on mToastQueue
+ @GuardedBy("mToastQueue")
void keepProcessAliveIfNeededLocked(int pid)
{
int toastCount = 0; // toasts from this pid
@@ -4028,6 +4051,7 @@
}
}
+ @GuardedBy("mNotificationLock")
private void recordCallerLocked(NotificationRecord record) {
if (mZenModeHelper.isCall(record)) {
mZenModeHelper.recordCaller(record);
@@ -4035,6 +4059,7 @@
}
// let zen mode evaluate this record
+ @GuardedBy("mNotificationLock")
private void applyZenModeLocked(NotificationRecord record) {
record.setIntercepted(mZenModeHelper.shouldIntercept(record));
if (record.isIntercepted()) {
@@ -4048,7 +4073,7 @@
}
}
- // lock on mNotificationList
+ @GuardedBy("mNotificationLock")
private int findNotificationRecordIndexLocked(NotificationRecord target) {
return mRankingHelper.indexOf(mNotificationList, target);
}
@@ -4181,6 +4206,7 @@
manager.sendAccessibilityEvent(event);
}
+ @GuardedBy("mNotificationLock")
private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete, int reason) {
final String canceledKey = r.getKey();
@@ -4430,6 +4456,7 @@
public boolean apply(int flags);
}
+ @GuardedBy("mNotificationLock")
private void cancelAllNotificationsByListLocked(ArrayList<NotificationRecord> notificationList,
int callingUid, int callingPid, String pkg, boolean nullPkgIndicatesUserSwitch,
String channelId, FlagChecker flagChecker, boolean includeCurrentProfiles, int userId,
@@ -4498,6 +4525,7 @@
savePolicyFile();
}
+ @GuardedBy("mNotificationLock")
void cancelAllLocked(int callingUid, int callingPid, int userId, int reason,
ManagedServiceInfo listener, boolean includeCurrentProfiles) {
mHandler.post(new Runnable() {
@@ -4532,6 +4560,7 @@
}
// Warning: The caller is responsible for invoking updateLightsLocked().
+ @GuardedBy("mNotificationLock")
private void cancelGroupChildrenLocked(NotificationRecord r, int callingUid, int callingPid,
String listenerName, boolean sendDelete) {
Notification n = r.getNotification();
@@ -4553,6 +4582,7 @@
listenerName, sendDelete);
}
+ @GuardedBy("mNotificationLock")
private void cancelGroupChildrenByListLocked(ArrayList<NotificationRecord> notificationList,
NotificationRecord parentNotification, int callingUid, int callingPid,
String listenerName, boolean sendDelete) {
@@ -4572,7 +4602,7 @@
}
}
- // lock on mNotificationList
+ @GuardedBy("mNotificationLock")
void updateLightsLocked()
{
// handle notification lights
@@ -4599,6 +4629,7 @@
}
}
+ @GuardedBy("mNotificationLock")
@NonNull List<NotificationRecord> findGroupNotificationsLocked(String pkg,
String groupKey, int userId) {
List<NotificationRecord> records = new ArrayList<>();
@@ -4609,6 +4640,7 @@
}
+ @GuardedBy("mNotificationLock")
private @NonNull List<NotificationRecord> findGroupNotificationByListLocked(
ArrayList<NotificationRecord> list, String pkg, String groupKey, int userId) {
List<NotificationRecord> records = new ArrayList<>();
@@ -4626,6 +4658,7 @@
// Searches both enqueued and posted notifications by key.
// TODO: need to combine a bunch of these getters with slightly different behavior.
// TODO: Should enqueuing just add to mNotificationsByKey instead?
+ @GuardedBy("mNotificationLock")
private NotificationRecord findNotificationByKeyLocked(String key) {
NotificationRecord r;
if ((r = findNotificationByListLocked(mNotificationList, key)) != null) {
@@ -4637,6 +4670,7 @@
return null;
}
+ @GuardedBy("mNotificationLock")
NotificationRecord findNotificationLocked(String pkg, String tag, int id, int userId) {
NotificationRecord r;
if ((r = findNotificationByListLocked(mNotificationList, pkg, tag, id, userId)) != null) {
@@ -4649,6 +4683,7 @@
return null;
}
+ @GuardedBy("mNotificationLock")
private NotificationRecord findNotificationByListLocked(ArrayList<NotificationRecord> list,
String pkg, String tag, int id, int userId) {
final int len = list.size();
@@ -4662,9 +4697,9 @@
return null;
}
+ @GuardedBy("mNotificationLock")
private NotificationRecord findNotificationByListLocked(ArrayList<NotificationRecord> list,
- String key)
- {
+ String key) {
final int N = list.size();
for (int i = 0; i < N; i++) {
if (key.equals(list.get(i).getKey())) {
@@ -4674,7 +4709,7 @@
return null;
}
- // lock on mNotificationList
+ @GuardedBy("mNotificationLock")
int indexOfNotificationLocked(String key) {
final int N = mNotificationList.size();
for (int i = 0; i < N; i++) {
@@ -4781,9 +4816,8 @@
/**
* Generates a NotificationRankingUpdate from 'sbns', considering only
* notifications visible to the given listener.
- *
- * <p>Caller must hold a lock on mNotificationList.</p>
*/
+ @GuardedBy("mNotificationLock")
private NotificationRankingUpdate makeRankingUpdateLocked(ManagedServiceInfo info) {
final int N = mNotificationList.size();
ArrayList<String> keys = new ArrayList<String>(N);
@@ -4914,7 +4948,7 @@
public class NotificationAssistants extends ManagedServices {
public NotificationAssistants() {
- super(getContext(), mHandler, mNotificationList, mUserProfiles);
+ super(getContext(), mHandler, mNotificationLock, mUserProfiles);
}
@Override
@@ -4945,6 +4979,7 @@
}
@Override
+ @GuardedBy("mNotificationLock")
protected void onServiceRemovedLocked(ManagedServiceInfo removed) {
mListeners.unregisterService(removed.service, removed.userid);
}
@@ -4988,6 +5023,7 @@
* asynchronously notify the assistant that a notification has been snoozed until a
* context
*/
+ @GuardedBy("mNotificationLock")
public void notifyAssistantSnoozedLocked(final StatusBarNotification sbn,
final String snoozeCriterionId) {
TrimCache trimCache = new TrimCache(sbn);
@@ -5021,7 +5057,7 @@
private final ArraySet<ManagedServiceInfo> mLightTrimListeners = new ArraySet<>();
public NotificationListeners() {
- super(getContext(), mHandler, mNotificationList, mUserProfiles);
+ super(getContext(), mHandler, mNotificationLock, mUserProfiles);
}
@Override
@@ -5061,6 +5097,7 @@
}
@Override
+ @GuardedBy("mNotificationLock")
protected void onServiceRemovedLocked(ManagedServiceInfo removed) {
if (removeDisabledHints(removed)) {
updateListenerHintsLocked();
@@ -5069,6 +5106,7 @@
mLightTrimListeners.remove(removed);
}
+ @GuardedBy("mNotificationLock")
public void setOnNotificationPostedTrimLocked(ManagedServiceInfo info, int trim) {
if (trim == TRIM_LIGHT) {
mLightTrimListeners.add(info);
@@ -5088,6 +5126,7 @@
* Also takes care of removing a notification that has been visible to a listener before,
* but isn't anymore.
*/
+ @GuardedBy("mNotificationLock")
public void notifyPostedLocked(StatusBarNotification sbn, StatusBarNotification oldSbn) {
// Lazily initialized snapshots of the notification.
TrimCache trimCache = new TrimCache(sbn);
@@ -5126,6 +5165,7 @@
/**
* asynchronously notify all listeners about a removed notification
*/
+ @GuardedBy("mNotificationLock")
public void notifyRemovedLocked(StatusBarNotification sbn, int reason) {
// make a copy in case changes are made to the underlying Notification object
// NOTE: this copy is lightweight: it doesn't include heavyweight parts of the
@@ -5148,6 +5188,7 @@
/**
* asynchronously notify all listeners about a reordering of notifications
*/
+ @GuardedBy("mNotificationLock")
public void notifyRankingUpdateLocked() {
for (final ManagedServiceInfo serviceInfo : getServices()) {
if (!serviceInfo.isEnabledForCurrentProfiles()) {
@@ -5163,6 +5204,7 @@
}
}
+ @GuardedBy("mNotificationLock")
public void notifyListenerHintsChangedLocked(final int hints) {
for (final ManagedServiceInfo serviceInfo : getServices()) {
if (!serviceInfo.isEnabledForCurrentProfiles()) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 95e1db7..8952870 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -63,7 +63,7 @@
* {@link android.service.notification.NotificationListenerService}s.
*
* <p>These objects should not be mutated unless the code is synchronized
- * on {@link NotificationManagerService#mNotificationList}, and any
+ * on {@link NotificationManagerService#mNotificationLock}, and any
* modification should be followed by a sorting of that list.</p>
*
* <p>Is sortable by {@link NotificationComparator}.</p>
@@ -73,6 +73,7 @@
public final class NotificationRecord {
static final String TAG = "NotificationRecord";
static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final int MAX_LOGTAG_LENGTH = 35;
final StatusBarNotification sbn;
final int mOriginalFlags;
private final Context mContext;
@@ -127,6 +128,8 @@
private boolean mShowBadge;
private LogMaker mLogMaker;
private Light mLight;
+ private String mGroupLogTag;
+ private String mChannelIdLogTag;
@VisibleForTesting
public NotificationRecord(Context context, StatusBarNotification sbn,
@@ -749,6 +752,37 @@
return sbn.getGroupKey();
}
+ public void setOverrideGroupKey(String overrideGroupKey) {
+ sbn.setOverrideGroupKey(overrideGroupKey);
+ mGroupLogTag = null;
+ }
+
+ private String getGroupLogTag() {
+ if (mGroupLogTag == null) {
+ mGroupLogTag = shortenTag(sbn.getGroup());
+ }
+ return mGroupLogTag;
+ }
+
+ private String getChannelIdLogTag() {
+ if (mChannelIdLogTag == null) {
+ mChannelIdLogTag = shortenTag(mChannel.getId());
+ }
+ return mChannelIdLogTag;
+ }
+
+ private String shortenTag(String longTag) {
+ if (longTag == null) {
+ return null;
+ }
+ if (longTag.length() < MAX_LOGTAG_LENGTH) {
+ return longTag;
+ } else {
+ return longTag.substring(0, MAX_LOGTAG_LENGTH - 8) + "-" +
+ Integer.toHexString(longTag.hashCode());
+ }
+ }
+
public boolean isImportanceFromUser() {
return mImportance == mUserImportance;
}
@@ -806,16 +840,23 @@
public LogMaker getLogMaker(long now) {
if (mLogMaker == null) {
+ // initialize fields that only change on update (so a new record)
mLogMaker = new LogMaker(MetricsEvent.VIEW_UNKNOWN)
.setPackageName(sbn.getPackageName())
.addTaggedData(MetricsEvent.NOTIFICATION_ID, sbn.getId())
- .addTaggedData(MetricsEvent.NOTIFICATION_TAG, sbn.getTag());
+ .addTaggedData(MetricsEvent.NOTIFICATION_TAG, sbn.getTag())
+ .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID, getChannelIdLogTag());
}
+ // reset fields that can change between updates, or are used by multiple logs
return mLogMaker
.clearCategory()
.clearType()
.clearSubtype()
.clearTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX)
+ .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE, mImportance)
+ .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID, getGroupLogTag())
+ .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_SUMMARY,
+ sbn.getNotification().isGroupSummary() ? 1 : 0)
.addTaggedData(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS, getLifespanMs(now))
.addTaggedData(MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS, getFreshnessMs(now))
.addTaggedData(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS, getExposureMs(now));
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index ac7b763..d1aecb1 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -936,7 +936,7 @@
// permissions if the version on the system image does not declare them.
if (!isDefaultPhoneOrSms && pkg.isUpdatedSystemApp()) {
PackageSetting sysPs = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName);
- if (sysPs != null) {
+ if (sysPs != null && sysPs.pkg != null) {
if (sysPs.pkg.requestedPermissions.isEmpty()) {
return;
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 29f9f7c..4a5ce12 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -34,6 +34,7 @@
import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
@@ -100,7 +101,6 @@
private static final boolean DEBUG = false;
private static final String TAG = "LauncherAppsService";
private final Context mContext;
- private final PackageManager mPm;
private final UserManager mUm;
private final ActivityManagerInternal mActivityManagerInternal;
private final ShortcutServiceInternal mShortcutServiceInternal;
@@ -113,7 +113,6 @@
public LauncherAppsImpl(Context context) {
mContext = context;
- mPm = mContext.getPackageManager();
mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mActivityManagerInternal = Preconditions.checkNotNull(
LocalServices.getService(ActivityManagerInternal.class));
@@ -263,15 +262,17 @@
void verifyCallingPackage(String callingPackage) {
int packageUid = -1;
try {
- packageUid = mPm.getPackageUidAsUser(callingPackage,
+ packageUid = AppGlobals.getPackageManager().getPackageUid(callingPackage,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_UNINSTALLED_PACKAGES,
UserHandle.getUserId(getCallingUid()));
- } catch (NameNotFoundException e) {
+ } catch (RemoteException ignore) {
+ }
+ if (packageUid < 0) {
Log.e(TAG, "Package not found: " + callingPackage);
}
- if (packageUid != Binder.getCallingUid()) {
+ if (packageUid != injectBinderCallingUid()) {
throw new SecurityException("Calling package name mismatch");
}
}
@@ -315,13 +316,15 @@
return null;
}
+ final int callingUid = injectBinderCallingUid();
long ident = Binder.clearCallingIdentity();
try {
- IPackageManager pm = AppGlobals.getPackageManager();
- return pm.getActivityInfo(component,
+ final PackageManagerInternal pmInt =
+ LocalServices.getService(PackageManagerInternal.class);
+ return pmInt.getActivityInfo(component,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- user.getIdentifier());
+ callingUid, user.getIdentifier());
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -344,12 +347,15 @@
return null;
}
+ final int callingUid = injectBinderCallingUid();
long ident = injectClearCallingIdentity();
try {
- List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(intent,
+ final PackageManagerInternal pmInt =
+ LocalServices.getService(PackageManagerInternal.class);
+ List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- user.getIdentifier());
+ callingUid, user.getIdentifier());
return new ParceledListSlice<>(apps);
} finally {
injectRestoreCallingIdentity(ident);
@@ -390,13 +396,15 @@
return false;
}
+ final int callingUid = injectBinderCallingUid();
long ident = Binder.clearCallingIdentity();
try {
- IPackageManager pm = AppGlobals.getPackageManager();
- PackageInfo info = pm.getPackageInfo(packageName,
+ final PackageManagerInternal pmInt =
+ LocalServices.getService(PackageManagerInternal.class);
+ PackageInfo info = pmInt.getPackageInfo(packageName,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- user.getIdentifier());
+ callingUid, user.getIdentifier());
return info != null && info.applicationInfo.enabled;
} finally {
Binder.restoreCallingIdentity(ident);
@@ -414,11 +422,13 @@
return null;
}
+ final int callingUid = injectBinderCallingUid();
long ident = Binder.clearCallingIdentity();
try {
- IPackageManager pm = AppGlobals.getPackageManager();
- ApplicationInfo info = pm.getApplicationInfo(packageName, flags,
- user.getIdentifier());
+ final PackageManagerInternal pmInt =
+ LocalServices.getService(PackageManagerInternal.class);
+ ApplicationInfo info = pmInt.getApplicationInfo(packageName, flags,
+ callingUid, user.getIdentifier());
return info;
} finally {
Binder.restoreCallingIdentity(ident);
@@ -573,13 +583,15 @@
return false;
}
+ final int callingUid = injectBinderCallingUid();
long ident = Binder.clearCallingIdentity();
try {
- IPackageManager pm = AppGlobals.getPackageManager();
- ActivityInfo info = pm.getActivityInfo(component,
+ final PackageManagerInternal pmInt =
+ LocalServices.getService(PackageManagerInternal.class);
+ ActivityInfo info = pmInt.getActivityInfo(component,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- user.getIdentifier());
+ callingUid, user.getIdentifier());
return info != null;
} finally {
Binder.restoreCallingIdentity(ident);
@@ -604,13 +616,15 @@
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
launchIntent.setPackage(component.getPackageName());
+ final int callingUid = injectBinderCallingUid();
long ident = Binder.clearCallingIdentity();
try {
- IPackageManager pm = AppGlobals.getPackageManager();
- ActivityInfo info = pm.getActivityInfo(component,
+ final PackageManagerInternal pmInt =
+ LocalServices.getService(PackageManagerInternal.class);
+ ActivityInfo info = pmInt.getActivityInfo(component,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- user.getIdentifier());
+ callingUid, user.getIdentifier());
if (!info.exported) {
throw new SecurityException("Cannot launch non-exported components "
+ component);
@@ -619,10 +633,10 @@
// Check that the component actually has Intent.CATEGORY_LAUCNCHER
// as calling startActivityAsUser ignores the category and just
// resolves based on the component if present.
- List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(launchIntent,
+ List<ResolveInfo> apps = pmInt.queryIntentActivities(launchIntent,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- user.getIdentifier());
+ callingUid, user.getIdentifier());
final int size = apps.size();
for (int i = 0; i < size; ++i) {
ActivityInfo activityInfo = apps.get(i).activityInfo;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 99eda86..e62b107 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2186,12 +2186,12 @@
private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId,
String[] grantedPermissions) {
- SettingBase sb = (SettingBase) pkg.mExtras;
- if (sb == null) {
+ PackageSetting ps = (PackageSetting) pkg.mExtras;
+ if (ps == null) {
return;
}
- PermissionsState permissionsState = sb.getPermissionsState();
+ PermissionsState permissionsState = ps.getPermissionsState();
final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
| PackageManager.FLAG_PERMISSION_POLICY_FIXED;
@@ -3516,7 +3516,7 @@
* and {@code 0}</li>
* <li>The calling application has the permission
* {@link android.Manifest.permission#ACCESS_INSTANT_APPS}</li>
- * <li>[TODO] The calling application is the default launcher on the
+ * <li>The calling application is the default launcher on the
* system partition.</li>
* </ol>
*/
@@ -3593,13 +3593,14 @@
@Override
public void checkPackageStartable(String packageName, int userId) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ final int callingUid = Binder.getCallingUid();
+ if (getInstantAppPackageName(callingUid) != null) {
throw new SecurityException("Instant applications don't have access to this method");
}
final boolean userKeyUnlocked = StorageManager.isUserKeyUnlocked(userId);
synchronized (mPackages) {
final PackageSetting ps = mSettings.mPackages.get(packageName);
- if (ps == null) {
+ if (ps == null || filterAppAccessLPr(ps, callingUid, userId)) {
throw new SecurityException("Package " + packageName + " was not found!");
}
@@ -3650,22 +3651,27 @@
@Override
public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
return getPackageInfoInternal(packageName, PackageManager.VERSION_CODE_HIGHEST,
- flags, userId);
+ flags, Binder.getCallingUid(), userId);
}
@Override
public PackageInfo getPackageInfoVersioned(VersionedPackage versionedPackage,
int flags, int userId) {
return getPackageInfoInternal(versionedPackage.getPackageName(),
- versionedPackage.getVersionCode(), flags, userId);
+ versionedPackage.getVersionCode(), flags, Binder.getCallingUid(), userId);
}
+ /**
+ * Important: The provided filterCallingUid is used exclusively to filter out packages
+ * that can be seen based on user state. It's typically the original caller uid prior
+ * to clearing. Because it can only be provided by trusted code, it's value can be
+ * trusted and will be used as-is; unlike userId which will be validated by this method.
+ */
private PackageInfo getPackageInfoInternal(String packageName, int versionCode,
- int flags, int userId) {
+ int flags, int filterCallingUid, int userId) {
if (!sUserManager.exists(userId)) return null;
- final int callingUid = Binder.getCallingUid();
flags = updateFlagsForPackage(flags, userId, packageName);
- enforceCrossUserPermission(callingUid, userId,
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
false /* requireFullPermission */, false /* checkShell */, "get package info");
// reader
@@ -3677,10 +3683,10 @@
if (matchFactoryOnly) {
final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName);
if (ps != null) {
- if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
+ if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
return null;
}
- if (filterAppAccessLPr(ps, callingUid, userId)) {
+ if (filterAppAccessLPr(ps, filterCallingUid, userId)) {
return null;
}
return generatePackageInfo(ps, flags, userId);
@@ -3695,10 +3701,10 @@
Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
if (p != null) {
final PackageSetting ps = (PackageSetting) p.mExtras;
- if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
+ if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
return null;
}
- if (ps != null && filterAppAccessLPr(ps, callingUid, userId)) {
+ if (ps != null && filterAppAccessLPr(ps, filterCallingUid, userId)) {
return null;
}
return generatePackageInfo((PackageSetting)p.mExtras, flags, userId);
@@ -3706,10 +3712,10 @@
if (!matchFactoryOnly && (flags & MATCH_KNOWN_PACKAGES) != 0) {
final PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps == null) return null;
- if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
+ if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
return null;
}
- if (filterAppAccessLPr(ps, callingUid, userId)) {
+ if (filterAppAccessLPr(ps, filterCallingUid, userId)) {
return null;
}
return generatePackageInfo(ps, flags, userId);
@@ -3868,15 +3874,26 @@
@Override
public String[] currentToCanonicalPackageNames(String[] names) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ final int callingUid = Binder.getCallingUid();
+ if (getInstantAppPackageName(callingUid) != null) {
return names;
}
- String[] out = new String[names.length];
+ final String[] out = new String[names.length];
// reader
synchronized (mPackages) {
+ final int callingUserId = UserHandle.getUserId(callingUid);
+ final boolean canViewInstantApps = canViewInstantApps(callingUid, callingUserId);
for (int i=names.length-1; i>=0; i--) {
- PackageSetting ps = mSettings.mPackages.get(names[i]);
- out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
+ final PackageSetting ps = mSettings.mPackages.get(names[i]);
+ boolean translateName = false;
+ if (ps != null && ps.realName != null) {
+ final boolean targetIsInstantApp = ps.getInstantApp(callingUserId);
+ translateName = !targetIsInstantApp
+ || canViewInstantApps
+ || mInstantAppRegistry.isInstantAccessGranted(callingUserId,
+ UserHandle.getAppId(callingUid), ps.appId);
+ }
+ out[i] = translateName ? ps.realName : names[i];
}
}
return out;
@@ -3884,15 +3901,28 @@
@Override
public String[] canonicalToCurrentPackageNames(String[] names) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ final int callingUid = Binder.getCallingUid();
+ if (getInstantAppPackageName(callingUid) != null) {
return names;
}
- String[] out = new String[names.length];
+ final String[] out = new String[names.length];
// reader
synchronized (mPackages) {
+ final int callingUserId = UserHandle.getUserId(callingUid);
+ final boolean canViewInstantApps = canViewInstantApps(callingUid, callingUserId);
for (int i=names.length-1; i>=0; i--) {
- String cur = mSettings.getRenamedPackageLPr(names[i]);
- out[i] = cur != null ? cur : names[i];
+ final String cur = mSettings.getRenamedPackageLPr(names[i]);
+ boolean translateName = false;
+ if (cur != null) {
+ final PackageSetting ps = mSettings.mPackages.get(names[i]);
+ final boolean targetIsInstantApp =
+ ps != null && ps.getInstantApp(callingUserId);
+ translateName = !targetIsInstantApp
+ || canViewInstantApps
+ || mInstantAppRegistry.isInstantAccessGranted(callingUserId,
+ UserHandle.getAppId(callingUid), ps.appId);
+ }
+ out[i] = translateName ? cur : names[i];
}
}
return out;
@@ -4046,14 +4076,14 @@
}
private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
- int uid, int userId) {
+ int filterCallingUid, int userId) {
if (!sUserManager.exists(userId)) return null;
PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps != null) {
- if (filterSharedLibPackageLPr(ps, uid, userId, flags)) {
+ if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
return null;
}
- if (filterAppAccessLPr(ps, uid, userId)) {
+ if (filterAppAccessLPr(ps, filterCallingUid, userId)) {
return null;
}
if (ps.pkg == null) {
@@ -4076,6 +4106,17 @@
@Override
public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
+ return getApplicationInfoInternal(packageName, flags, Binder.getCallingUid(), userId);
+ }
+
+ /**
+ * Important: The provided filterCallingUid is used exclusively to filter out applications
+ * that can be seen based on user state. It's typically the original caller uid prior
+ * to clearing. Because it can only be provided by trusted code, it's value can be
+ * trusted and will be used as-is; unlike userId which will be validated by this method.
+ */
+ private ApplicationInfo getApplicationInfoInternal(String packageName, int flags,
+ int filterCallingUid, int userId) {
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForApplication(flags, userId, packageName);
enforceCrossUserPermission(Binder.getCallingUid(), userId,
@@ -4094,10 +4135,10 @@
if (p != null) {
PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps == null) return null;
- if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
+ if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
return null;
}
- if (filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) {
+ if (filterAppAccessLPr(ps, filterCallingUid, userId)) {
return null;
}
// Note: isEnabledLP() does not apply here - always return info
@@ -4115,7 +4156,7 @@
if ((flags & MATCH_KNOWN_PACKAGES) != 0) {
// Already generates the external package name
return generateApplicationInfoFromSettingsLPw(packageName,
- Binder.getCallingUid(), flags, userId);
+ flags, filterCallingUid, userId);
}
}
return null;
@@ -4545,10 +4586,20 @@
@Override
public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
+ return getActivityInfoInternal(component, flags, Binder.getCallingUid(), userId);
+ }
+
+ /**
+ * Important: The provided filterCallingUid is used exclusively to filter out activities
+ * that can be seen based on user state. It's typically the original caller uid prior
+ * to clearing. Because it can only be provided by trusted code, it's value can be
+ * trusted and will be used as-is; unlike userId which will be validated by this method.
+ */
+ private ActivityInfo getActivityInfoInternal(ComponentName component, int flags,
+ int filterCallingUid, int userId) {
if (!sUserManager.exists(userId)) return null;
- final int callingUid = Binder.getCallingUid();
flags = updateFlagsForComponent(flags, userId, component);
- enforceCrossUserPermission(callingUid, userId,
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
false /* requireFullPermission */, false /* checkShell */, "get activity info");
synchronized (mPackages) {
PackageParser.Activity a = mActivities.mActivities.get(component);
@@ -4557,7 +4608,7 @@
if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
if (ps == null) return null;
- if (filterAppAccessLPr(ps, callingUid, component, TYPE_ACTIVITY, userId)) {
+ if (filterAppAccessLPr(ps, filterCallingUid, component, TYPE_ACTIVITY, userId)) {
return null;
}
return generateActivityInfo(a, flags, ps.readUserState(userId), userId);
@@ -4853,9 +4904,13 @@
}
}
- private void updateSequenceNumberLP(String packageName, int[] userList) {
+ private void updateSequenceNumberLP(PackageSetting pkgSetting, int[] userList) {
for (int i = userList.length - 1; i >= 0; --i) {
final int userId = userList[i];
+ // don't add instant app to the list of updates
+ if (pkgSetting.getInstantApp(userId)) {
+ continue;
+ }
SparseArray<String> changedPackages = mChangedPackages.get(userId);
if (changedPackages == null) {
changedPackages = new SparseArray<>();
@@ -4866,12 +4921,12 @@
sequenceNumbers = new HashMap<>();
mChangedPackagesSequenceNumbers.put(userId, sequenceNumbers);
}
- final Integer sequenceNumber = sequenceNumbers.get(packageName);
+ final Integer sequenceNumber = sequenceNumbers.get(pkgSetting.name);
if (sequenceNumber != null) {
changedPackages.remove(sequenceNumber);
}
- changedPackages.put(mChangedPackagesSequenceNumber, packageName);
- sequenceNumbers.put(packageName, mChangedPackagesSequenceNumber);
+ changedPackages.put(mChangedPackagesSequenceNumber, pkgSetting.name);
+ sequenceNumbers.put(pkgSetting.name, mChangedPackagesSequenceNumber);
}
mChangedPackagesSequenceNumber++;
}
@@ -5302,28 +5357,33 @@
Log.e(TAG, "No such user:" + userId);
return;
}
+ final int callingUid = Binder.getCallingUid();
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
"grantRuntimePermission");
- enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, true /* checkShell */,
"grantRuntimePermission");
final int uid;
- final SettingBase sb;
+ final PackageSetting ps;
synchronized (mPackages) {
final PackageParser.Package pkg = mPackages.get(packageName);
if (pkg == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
-
final BasePermission bp = mSettings.mPermissions.get(name);
if (bp == null) {
throw new IllegalArgumentException("Unknown permission: " + name);
}
+ ps = (PackageSetting) pkg.mExtras;
+ if (ps == null
+ || filterAppAccessLPr(ps, callingUid, userId)) {
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(pkg, bp);
@@ -5338,12 +5398,8 @@
}
uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
- sb = (SettingBase) pkg.mExtras;
- if (sb == null) {
- throw new IllegalArgumentException("Unknown package: " + packageName);
- }
- final PermissionsState permissionsState = sb.getPermissionsState();
+ final PermissionsState permissionsState = ps.getPermissionsState();
final int flags = permissionsState.getPermissionFlags(name, userId);
if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
@@ -5365,7 +5421,6 @@
return;
}
- final PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps.getInstantApp(userId) && !bp.isInstant()) {
throw new SecurityException("Cannot grant non-ephemeral permission"
+ name + " for package " + packageName);
@@ -5449,7 +5504,11 @@
if (pkg == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
-
+ final PackageSetting ps = (PackageSetting) pkg.mExtras;
+ if (ps == null
+ || filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) {
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
final BasePermission bp = mSettings.mPermissions.get(name);
if (bp == null) {
throw new IllegalArgumentException("Unknown permission: " + name);
@@ -5467,12 +5526,7 @@
return;
}
- SettingBase sb = (SettingBase) pkg.mExtras;
- if (sb == null) {
- throw new IllegalArgumentException("Unknown package: " + packageName);
- }
-
- final PermissionsState permissionsState = sb.getPermissionsState();
+ final PermissionsState permissionsState = ps.getPermissionsState();
final int flags = permissionsState.getPermissionFlags(name, userId);
if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
@@ -5611,7 +5665,8 @@
enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags");
- enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ final int callingUid = Binder.getCallingUid();
+ enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, false /* checkShell */,
"getPermissionFlags");
@@ -5620,18 +5675,16 @@
if (pkg == null) {
return 0;
}
-
final BasePermission bp = mSettings.mPermissions.get(name);
if (bp == null) {
return 0;
}
-
- SettingBase sb = (SettingBase) pkg.mExtras;
- if (sb == null) {
+ final PackageSetting ps = (PackageSetting) pkg.mExtras;
+ if (ps == null
+ || filterAppAccessLPr(ps, callingUid, userId)) {
return 0;
}
-
- PermissionsState permissionsState = sb.getPermissionsState();
+ PermissionsState permissionsState = ps.getPermissionsState();
return permissionsState.getPermissionFlags(name, userId);
}
}
@@ -5645,7 +5698,8 @@
enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
- enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ final int callingUid = Binder.getCallingUid();
+ enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, true /* checkShell */,
"updatePermissionFlags");
@@ -5663,18 +5717,18 @@
if (pkg == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
+ final PackageSetting ps = (PackageSetting) pkg.mExtras;
+ if (ps == null
+ || filterAppAccessLPr(ps, callingUid, userId)) {
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
final BasePermission bp = mSettings.mPermissions.get(name);
if (bp == null) {
throw new IllegalArgumentException("Unknown permission: " + name);
}
- SettingBase sb = (SettingBase) pkg.mExtras;
- if (sb == null) {
- throw new IllegalArgumentException("Unknown package: " + packageName);
- }
-
- PermissionsState permissionsState = sb.getPermissionsState();
+ PermissionsState permissionsState = ps.getPermissionsState();
boolean hadState = permissionsState.getRuntimePermissionState(name, userId) != null;
@@ -5718,11 +5772,11 @@
final int packageCount = mPackages.size();
for (int pkgIndex = 0; pkgIndex < packageCount; pkgIndex++) {
final PackageParser.Package pkg = mPackages.valueAt(pkgIndex);
- SettingBase sb = (SettingBase) pkg.mExtras;
- if (sb == null) {
+ final PackageSetting ps = (PackageSetting) pkg.mExtras;
+ if (ps == null) {
continue;
}
- PermissionsState permissionsState = sb.getPermissionsState();
+ PermissionsState permissionsState = ps.getPermissionsState();
changed |= permissionsState.updatePermissionFlagsForAllPermissions(
userId, flagMask, flagValues);
}
@@ -6171,7 +6225,8 @@
@Override
public int getFlagsForUid(int uid) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ final int callingUid = Binder.getCallingUid();
+ if (getInstantAppPackageName(callingUid) != null) {
return 0;
}
synchronized (mPackages) {
@@ -6181,6 +6236,9 @@
return sus.pkgFlags;
} else if (obj instanceof PackageSetting) {
final PackageSetting ps = (PackageSetting) obj;
+ if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+ return 0;
+ }
return ps.pkgFlags;
}
}
@@ -6189,7 +6247,8 @@
@Override
public int getPrivateFlagsForUid(int uid) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ final int callingUid = Binder.getCallingUid();
+ if (getInstantAppPackageName(callingUid) != null) {
return 0;
}
synchronized (mPackages) {
@@ -6199,6 +6258,9 @@
return sus.pkgPrivateFlags;
} else if (obj instanceof PackageSetting) {
final PackageSetting ps = (PackageSetting) obj;
+ if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+ return 0;
+ }
return ps.pkgPrivateFlags;
}
}
@@ -6264,7 +6326,7 @@
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
- flags, userId, resolveForStart);
+ flags, callingUid, userId, resolveForStart);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
final ResolveInfo bestChoice =
@@ -6808,15 +6870,16 @@
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
String resolvedType, int flags, int userId) {
- return queryIntentActivitiesInternal(intent, resolvedType, flags, userId, false);
+ return queryIntentActivitiesInternal(
+ intent, resolvedType, flags, Binder.getCallingUid(), userId, false);
}
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
- String resolvedType, int flags, int userId, boolean resolveForStart) {
+ String resolvedType, int flags, int filterCallingUid, int userId,
+ boolean resolveForStart) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- final int callingUid = Binder.getCallingUid();
- final String instantAppPkgName = getInstantAppPackageName(callingUid);
- enforceCrossUserPermission(callingUid, userId,
+ final String instantAppPkgName = getInstantAppPackageName(filterCallingUid);
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
false /* requireFullPermission */, false /* checkShell */,
"query intent activities");
final String pkgName = intent.getPackage();
@@ -6828,7 +6891,7 @@
}
}
- flags = updateFlagsForResolve(flags, userId, intent, callingUid, resolveForStart,
+ flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart,
comp != null || pkgName != null /*onlyExposedExplicitly*/);
if (comp != null) {
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
@@ -8048,13 +8111,14 @@
@Override
public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ final int callingUid = Binder.getCallingUid();
+ if (getInstantAppPackageName(callingUid) != null) {
return ParceledListSlice.emptyList();
}
if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
flags = updateFlagsForPackage(flags, userId, null);
final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
- enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, false /* checkShell */,
"get installed packages");
@@ -8064,9 +8128,12 @@
if (listUninstalled) {
list = new ArrayList<>(mSettings.mPackages.size());
for (PackageSetting ps : mSettings.mPackages.values()) {
- if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
+ if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
continue;
}
+ if (filterAppAccessLPr(ps, callingUid, userId)) {
+ return null;
+ }
final PackageInfo pi = generatePackageInfo(ps, flags, userId);
if (pi != null) {
list.add(pi);
@@ -8075,10 +8142,13 @@
} else {
list = new ArrayList<>(mPackages.size());
for (PackageParser.Package p : mPackages.values()) {
- if (filterSharedLibPackageLPr((PackageSetting) p.mExtras,
- Binder.getCallingUid(), userId, flags)) {
+ final PackageSetting ps = (PackageSetting) p.mExtras;
+ if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
continue;
}
+ if (filterAppAccessLPr(ps, callingUid, userId)) {
+ return null;
+ }
final PackageInfo pi = generatePackageInfo((PackageSetting)
p.mExtras, flags, userId);
if (pi != null) {
@@ -8165,7 +8235,8 @@
@Override
public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ final int callingUid = Binder.getCallingUid();
+ if (getInstantAppPackageName(callingUid) != null) {
return ParceledListSlice.emptyList();
}
if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
@@ -8184,9 +8255,12 @@
effectiveFlags |= PackageManager.MATCH_ANY_USER;
}
if (ps.pkg != null) {
- if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
+ if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
continue;
}
+ if (filterAppAccessLPr(ps, callingUid, userId)) {
+ return null;
+ }
ai = PackageParser.generateApplicationInfo(ps.pkg, effectiveFlags,
ps.readUserState(userId), userId);
if (ai != null) {
@@ -8197,7 +8271,7 @@
// Shared lib filtering done in generateApplicationInfoFromSettingsLPw
// and already converts to externally visible package name
ai = generateApplicationInfoFromSettingsLPw(ps.name,
- Binder.getCallingUid(), effectiveFlags, userId);
+ callingUid, effectiveFlags, userId);
}
if (ai != null) {
list.add(ai);
@@ -8211,6 +8285,9 @@
if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
continue;
}
+ if (filterAppAccessLPr(ps, callingUid, userId)) {
+ return null;
+ }
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
ps.readUserState(userId), userId);
if (ai != null) {
@@ -9348,6 +9425,11 @@
@Override
public boolean performDexOpt(String packageName,
boolean checkProfiles, int compileReason, boolean force) {
+ if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ return false;
+ } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+ return false;
+ }
return performDexOptWithStatus(packageName, checkProfiles, compileReason, force) !=
PackageDexOptimizer.DEX_OPT_FAILED;
}
@@ -9369,6 +9451,8 @@
boolean checkProfiles, String targetCompilerFilter, boolean force) {
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
return false;
+ } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+ return false;
}
int dexOptStatus = performDexOptTraced(packageName, checkProfiles,
targetCompilerFilter, force);
@@ -9465,6 +9549,8 @@
boolean force) {
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
return false;
+ } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+ return false;
}
mDexManager.reconcileSecondaryDexFiles(packageName);
return mDexManager.dexoptSecondaryDex(packageName, compilerFilter, force);
@@ -9484,6 +9570,8 @@
public void reconcileSecondaryDexFiles(String packageName) {
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
return;
+ } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+ return;
}
mDexManager.reconcileSecondaryDexFiles(packageName);
}
@@ -14261,8 +14349,8 @@
int userId) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
PackageSetting pkgSetting;
- final int uid = Binder.getCallingUid();
- enforceCrossUserPermission(uid, userId,
+ final int callingUid = Binder.getCallingUid();
+ enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, true /* checkShell */,
"setApplicationHiddenSetting for user " + userId);
@@ -14281,6 +14369,9 @@
if (pkgSetting == null) {
return false;
}
+ if (filterAppAccessLPr(pkgSetting, callingUid, userId)) {
+ return false;
+ }
// Do not allow "android" is being disabled
if ("android".equals(packageName)) {
Slog.w(TAG, "Cannot hide package: android");
@@ -14297,7 +14388,7 @@
return false;
}
// Only allow protected packages to hide themselves.
- if (hidden && !UserHandle.isSameApp(uid, pkgSetting.appId)
+ if (hidden && !UserHandle.isSameApp(callingUid, pkgSetting.appId)
&& mProtectedPackages.isPackageStateProtected(userId, packageName)) {
Slog.w(TAG, "Not hiding protected package: " + packageName);
return false;
@@ -14360,19 +14451,23 @@
@Override
public boolean getApplicationHiddenSettingAsUser(String packageName, int userId) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
- enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ final int callingUid = Binder.getCallingUid();
+ enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, false /* checkShell */,
"getApplicationHidden for user " + userId);
- PackageSetting pkgSetting;
+ PackageSetting ps;
long callingId = Binder.clearCallingIdentity();
try {
// writer
synchronized (mPackages) {
- pkgSetting = mSettings.mPackages.get(packageName);
- if (pkgSetting == null) {
+ ps = mSettings.mPackages.get(packageName);
+ if (ps == null) {
return true;
}
- return pkgSetting.getHidden(userId);
+ if (filterAppAccessLPr(ps, callingUid, userId)) {
+ return true;
+ }
+ return ps.getHidden(userId);
}
} finally {
Binder.restoreCallingIdentity(callingId);
@@ -14388,8 +14483,8 @@
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
null);
PackageSetting pkgSetting;
- final int uid = Binder.getCallingUid();
- enforceCrossUserPermission(uid, userId,
+ final int callingUid = Binder.getCallingUid();
+ enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, true /* checkShell */,
"installExistingPackage for user " + userId);
if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
@@ -14410,6 +14505,20 @@
if (pkgSetting == null) {
return PackageManager.INSTALL_FAILED_INVALID_URI;
}
+ if (!canViewInstantApps(callingUid, UserHandle.getUserId(callingUid))) {
+ // only allow the existing package to be used if it's installed as a full
+ // application for at least one user
+ boolean installAllowed = false;
+ for (int checkUserId : sUserManager.getUserIds()) {
+ installAllowed = !pkgSetting.getInstantApp(checkUserId);
+ if (installAllowed) {
+ break;
+ }
+ }
+ if (!installAllowed) {
+ return PackageManager.INSTALL_FAILED_INVALID_URI;
+ }
+ }
if (!pkgSetting.getInstalled(userId)) {
pkgSetting.setInstalled(true, userId);
pkgSetting.setHidden(false, userId);
@@ -14433,7 +14542,7 @@
}
sendPackageAddedForUser(packageName, pkgSetting, userId);
synchronized (mPackages) {
- updateSequenceNumberLP(packageName, new int[]{ userId });
+ updateSequenceNumberLP(pkgSetting, new int[]{ userId });
}
}
} finally {
@@ -14479,7 +14588,8 @@
public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
int userId) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
- enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ final int callingUid = Binder.getCallingUid();
+ enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, true /* checkShell */,
"setPackagesSuspended for user " + userId);
@@ -14500,7 +14610,8 @@
final int appId;
synchronized (mPackages) {
final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
- if (pkgSetting == null) {
+ if (pkgSetting == null
+ || filterAppAccessLPr(pkgSetting, callingUid, userId)) {
Slog.w(TAG, "Could not find package setting for package \"" + packageName
+ "\". Skipping suspending/un-suspending.");
unactionedPackages.add(packageName);
@@ -14824,7 +14935,7 @@
*
* @return true if verification should be performed
*/
- private boolean isVerificationEnabled(int userId, int installFlags) {
+ private boolean isVerificationEnabled(int userId, int installFlags, int installerUid) {
if (!DEFAULT_VERIFY_ENABLE) {
return false;
}
@@ -14845,6 +14956,23 @@
android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) == 0) {
return false;
}
+ } else {
+ // only when not installed from ADB, skip verification for instant apps when
+ // the installer and verifier are the same.
+ if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
+ if (mInstantAppInstallerActivity != null
+ && mInstantAppInstallerActivity.packageName.equals(
+ mRequiredVerifierPackage)) {
+ try {
+ mContext.getSystemService(AppOpsManager.class)
+ .checkPackage(installerUid, mRequiredVerifierPackage);
+ if (DEBUG_VERIFY) {
+ Slog.i(TAG, "disable verification for instant app");
+ }
+ return false;
+ } catch (SecurityException ignore) { }
+ }
+ }
}
if (ensureVerifyAppsEnabled) {
@@ -14872,10 +15000,16 @@
@Override
public int getIntentVerificationStatus(String packageName, int userId) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ final int callingUid = Binder.getCallingUid();
+ if (getInstantAppPackageName(callingUid) != null) {
return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
}
synchronized (mPackages) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (ps == null
+ || filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+ return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+ }
return mSettings.getIntentFilterVerificationStatusLPr(packageName, userId);
}
}
@@ -14887,6 +15021,10 @@
boolean result = false;
synchronized (mPackages) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (filterAppAccessLPr(ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
+ return false;
+ }
result = mSettings.updateIntentFilterVerificationStatusLPw(packageName, status, userId);
}
if (result) {
@@ -14898,10 +15036,15 @@
@Override
public @NonNull ParceledListSlice<IntentFilterVerificationInfo> getIntentFilterVerifications(
String packageName) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ final int callingUid = Binder.getCallingUid();
+ if (getInstantAppPackageName(callingUid) != null) {
return ParceledListSlice.emptyList();
}
synchronized (mPackages) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+ return ParceledListSlice.emptyList();
+ }
return new ParceledListSlice<>(mSettings.getIntentFilterVerificationsLPr(packageName));
}
}
@@ -14982,7 +15125,9 @@
// writer
synchronized (mPackages) {
PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
- if (targetPackageSetting == null) {
+ if (targetPackageSetting == null
+ || filterAppAccessLPr(
+ targetPackageSetting, callingUid, UserHandle.getUserId(callingUid))) {
throw new IllegalArgumentException("Unknown target package: " + targetPackage);
}
@@ -15063,7 +15208,9 @@
if (ps == null) {
throw new IllegalArgumentException("Unknown target package " + packageName);
}
-
+ if (filterAppAccessLPr(ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
+ throw new IllegalArgumentException("Unknown target package " + packageName);
+ }
if (!Objects.equals(callerPackageName, ps.installerPackageName)) {
throw new IllegalArgumentException("Calling package " + callerPackageName
+ " is not installer for " + packageName);
@@ -15668,8 +15815,11 @@
final int requiredUid = mRequiredVerifierPackage == null ? -1
: getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
verifierUser.getIdentifier());
+ final int installerUid =
+ verificationInfo == null ? -1 : verificationInfo.installerUid;
if (!origin.existing && requiredUid != -1
- && isVerificationEnabled(verifierUser.getIdentifier(), installFlags)) {
+ && isVerificationEnabled(
+ verifierUser.getIdentifier(), installFlags, installerUid)) {
final Intent verification = new Intent(
Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -17067,12 +17217,15 @@
@Override
public List<String> getPreviousCodePaths(String packageName) {
+ final int callingUid = Binder.getCallingUid();
final List<String> result = new ArrayList<>();
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ if (getInstantAppPackageName(callingUid) != null) {
return result;
}
final PackageSetting ps = mSettings.mPackages.get(packageName);
- if (ps != null && ps.oldCodePaths != null) {
+ if (ps != null
+ && ps.oldCodePaths != null
+ && !filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
result.addAll(ps.oldCodePaths);
}
return result;
@@ -18078,7 +18231,7 @@
}
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
- updateSequenceNumberLP(pkgName, res.newUsers);
+ updateSequenceNumberLP(ps, res.newUsers);
updateInstantAppInstallerLocked(pkgName);
}
}
@@ -18301,8 +18454,10 @@
@Override
public void deletePackageVersioned(VersionedPackage versionedPackage,
final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
+ final int callingUid = Binder.getCallingUid();
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DELETE_PACKAGES, null);
+ final boolean canViewInstantApps = canViewInstantApps(callingUid, userId);
Preconditions.checkNotNull(versionedPackage);
Preconditions.checkNotNull(observer);
Preconditions.checkArgumentInRange(versionedPackage.getVersionCode(),
@@ -18367,33 +18522,45 @@
public void run() {
mHandler.removeCallbacks(this);
int returnCode;
- if (!deleteAllUsers) {
- returnCode = deletePackageX(internalPackageName, versionCode,
- userId, deleteFlags);
- } else {
- int[] blockUninstallUserIds = getBlockUninstallForUsers(
- internalPackageName, users);
- // If nobody is blocking uninstall, proceed with delete for all users
- if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
+ final PackageSetting ps = mSettings.mPackages.get(internalPackageName);
+ boolean doDeletePackage = true;
+ if (ps != null) {
+ final boolean targetIsInstantApp =
+ ps.getInstantApp(UserHandle.getUserId(callingUid));
+ doDeletePackage = !targetIsInstantApp
+ || canViewInstantApps;
+ }
+ if (doDeletePackage) {
+ if (!deleteAllUsers) {
returnCode = deletePackageX(internalPackageName, versionCode,
userId, deleteFlags);
} else {
- // Otherwise uninstall individually for users with blockUninstalls=false
- final int userFlags = deleteFlags & ~PackageManager.DELETE_ALL_USERS;
- for (int userId : users) {
- if (!ArrayUtils.contains(blockUninstallUserIds, userId)) {
- returnCode = deletePackageX(internalPackageName, versionCode,
- userId, userFlags);
- if (returnCode != PackageManager.DELETE_SUCCEEDED) {
- Slog.w(TAG, "Package delete failed for user " + userId
- + ", returnCode " + returnCode);
+ int[] blockUninstallUserIds = getBlockUninstallForUsers(
+ internalPackageName, users);
+ // If nobody is blocking uninstall, proceed with delete for all users
+ if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
+ returnCode = deletePackageX(internalPackageName, versionCode,
+ userId, deleteFlags);
+ } else {
+ // Otherwise uninstall individually for users with blockUninstalls=false
+ final int userFlags = deleteFlags & ~PackageManager.DELETE_ALL_USERS;
+ for (int userId : users) {
+ if (!ArrayUtils.contains(blockUninstallUserIds, userId)) {
+ returnCode = deletePackageX(internalPackageName, versionCode,
+ userId, userFlags);
+ if (returnCode != PackageManager.DELETE_SUCCEEDED) {
+ Slog.w(TAG, "Package delete failed for user " + userId
+ + ", returnCode " + returnCode);
+ }
}
}
+ // The app has only been marked uninstalled for certain users.
+ // We still need to report that delete was blocked
+ returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
}
- // The app has only been marked uninstalled for certain users.
- // We still need to report that delete was blocked
- returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
}
+ } else {
+ returnCode = PackageManager.DELETE_FAILED_INTERNAL_ERROR;
}
try {
observer.onPackageDeleted(packageName, returnCode, null);
@@ -18664,7 +18831,7 @@
if (pkg != null) {
mInstantAppRegistry.onPackageUninstalledLPw(pkg, info.removedUsers);
}
- updateSequenceNumberLP(packageName, info.removedUsers);
+ updateSequenceNumberLP(uninstalledPs, info.removedUsers);
updateInstantAppInstallerLocked(packageName);
}
}
@@ -19195,6 +19362,10 @@
@Override
public boolean getBlockUninstallForUser(String packageName, int userId) {
synchronized (mPackages) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (ps == null || filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) {
+ return true;
+ }
return mSettings.getBlockUninstallLPr(userId, packageName);
}
}
@@ -19544,9 +19715,14 @@
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CLEAR_APP_USER_DATA, null);
- enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ final int callingUid = Binder.getCallingUid();
+ enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, false /* checkShell */, "clear application data");
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
+ if (ps != null && filterAppAccessLPr(ps, callingUid, userId)) {
+ return;
+ }
if (mProtectedPackages.isPackageDataProtected(userId, packageName)) {
throw new SecurityException("Cannot clear data for a protected package: "
+ packageName);
@@ -19804,11 +19980,14 @@
@Override
public void deleteApplicationCacheFilesAsUser(final String packageName, final int userId,
final IPackageDataObserver observer) {
+ final int callingUid = Binder.getCallingUid();
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DELETE_CACHE_FILES, null);
- enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ enforceCrossUserPermission(callingUid, userId,
/* requireFullPermission= */ true, /* checkShell= */ false,
"delete application cache files");
+ final int hasAccessInstantApps = mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_INSTANT_APPS);
final PackageParser.Package pkg;
synchronized (mPackages) {
@@ -19818,15 +19997,25 @@
// Queue up an async operation since the package deletion may take a little while.
mHandler.post(new Runnable() {
public void run() {
- synchronized (mInstallLock) {
- final int flags = StorageManager.FLAG_STORAGE_DE
- | StorageManager.FLAG_STORAGE_CE;
- // We're only clearing cache files, so we don't care if the
- // app is unfrozen and still able to run
- clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CACHE_ONLY);
- clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ final PackageSetting ps = (PackageSetting) pkg.mExtras;
+ boolean doClearData = true;
+ if (ps != null) {
+ final boolean targetIsInstantApp =
+ ps.getInstantApp(UserHandle.getUserId(callingUid));
+ doClearData = !targetIsInstantApp
+ || hasAccessInstantApps == PackageManager.PERMISSION_GRANTED;
}
- clearExternalStorageDataSync(packageName, userId, false);
+ if (doClearData) {
+ synchronized (mInstallLock) {
+ final int flags = StorageManager.FLAG_STORAGE_DE
+ | StorageManager.FLAG_STORAGE_CE;
+ // We're only clearing cache files, so we don't care if the
+ // app is unfrozen and still able to run
+ clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CACHE_ONLY);
+ clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ }
+ clearExternalStorageDataSync(packageName, userId, false);
+ }
if (observer != null) {
try {
observer.onRemoveCompleted(packageName, true);
@@ -20076,7 +20265,11 @@
android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
}
}
-
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
+ if (ps != null
+ && filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+ return;
+ }
int user = UserHandle.getCallingUserId();
if (clearPackagePreferredActivitiesLPw(packageName, user)) {
scheduleWritePackageRestrictionsLocked(user);
@@ -20726,7 +20919,7 @@
public void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
- int callingUid = Binder.getCallingUid();
+ final int callingUid = Binder.getCallingUid();
enforceOwnerRights(ownerPackage, callingUid);
enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId);
synchronized (mPackages) {
@@ -20749,7 +20942,7 @@
if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
return;
}
- int callingUserId = UserHandle.getUserId(callingUid);
+ final int callingUserId = UserHandle.getUserId(callingUid);
PackageInfo pi = getPackageInfo(pkg, 0, callingUserId);
if (pi == null) {
throw new IllegalArgumentException("Unknown package " + pkg + " on user "
@@ -20994,7 +21187,8 @@
// Limit who can change which apps
if (!UserHandle.isSameApp(callingUid, pkgSetting.appId)) {
// Don't allow apps that don't have permission to modify other apps
- if (!allowedByPermission) {
+ if (!allowedByPermission
+ || filterAppAccessLPr(pkgSetting, callingUid, userId)) {
throw new SecurityException(
"Attempt to change component state; "
+ "pid=" + Binder.getCallingPid()
@@ -21081,7 +21275,7 @@
}
}
scheduleWritePackageRestrictionsLocked(userId);
- updateSequenceNumberLP(packageName, new int[] { userId });
+ updateSequenceNumberLP(pkgSetting, new int[] { userId });
final long callingId = Binder.clearCallingIdentity();
try {
updateInstantAppInstallerLocked(packageName);
@@ -21178,8 +21372,10 @@
true /* requireFullPermission */, true /* checkShell */, "stop package");
// writer
synchronized (mPackages) {
- if (mSettings.setPackageStoppedStateLPw(this, packageName, stopped,
- allowedByPermission, callingUid, userId)) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (!filterAppAccessLPr(ps, callingUid, userId)
+ && mSettings.setPackageStoppedStateLPw(this, packageName, stopped,
+ allowedByPermission, callingUid, userId)) {
scheduleWritePackageRestrictionsLocked(userId);
}
}
@@ -21187,11 +21383,16 @@
@Override
public String getInstallerPackageName(String packageName) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ final int callingUid = Binder.getCallingUid();
+ if (getInstantAppPackageName(callingUid) != null) {
return null;
}
// reader
synchronized (mPackages) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+ return null;
+ }
return mSettings.getInstallerPackageNameLPr(packageName);
}
}
@@ -23385,13 +23586,14 @@
public int movePackage(final String packageName, final String volumeUuid) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
- final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
+ final int callingUid = Binder.getCallingUid();
+ final UserHandle user = new UserHandle(UserHandle.getUserId(callingUid));
final int moveId = mNextMoveId.getAndIncrement();
mHandler.post(new Runnable() {
@Override
public void run() {
try {
- movePackageInternal(packageName, volumeUuid, moveId, user);
+ movePackageInternal(packageName, volumeUuid, moveId, callingUid, user);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to move " + packageName, e);
mMoveCallbacks.notifyStatusChanged(moveId,
@@ -23403,7 +23605,8 @@
}
private void movePackageInternal(final String packageName, final String volumeUuid,
- final int moveId, UserHandle user) throws PackageManagerException {
+ final int moveId, final int callingUid, UserHandle user)
+ throws PackageManagerException {
final StorageManager storage = mContext.getSystemService(StorageManager.class);
final PackageManager pm = mContext.getPackageManager();
@@ -23423,10 +23626,11 @@
synchronized (mPackages) {
final PackageParser.Package pkg = mPackages.get(packageName);
final PackageSetting ps = mSettings.mPackages.get(packageName);
- if (pkg == null || ps == null) {
+ if (pkg == null
+ || ps == null
+ || filterAppAccessLPr(ps, callingUid, user.getIdentifier())) {
throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package");
}
-
if (pkg.applicationInfo.isSystemApp()) {
throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE,
"Cannot move system application");
@@ -23896,6 +24100,11 @@
Slog.w(TAG, "KeySet requested for unknown package: " + packageName);
throw new IllegalArgumentException("Unknown package: " + packageName);
}
+ final PackageSetting ps = (PackageSetting) pkg.mExtras;
+ if (filterAppAccessLPr(ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
+ Slog.w(TAG, "KeySet requested for filtered package: " + packageName);
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
KeySetManagerService ksms = mSettings.mKeySetManagerService;
return new KeySet(ksms.getKeySetByAliasAndPackageNameLPr(packageName, alias));
}
@@ -23932,7 +24141,8 @@
@Override
public boolean isPackageSignedByKeySet(String packageName, KeySet ks) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ final int callingUid = Binder.getCallingUid();
+ if (getInstantAppPackageName(callingUid) != null) {
return false;
}
if (packageName == null || ks == null) {
@@ -23940,7 +24150,9 @@
}
synchronized(mPackages) {
final PackageParser.Package pkg = mPackages.get(packageName);
- if (pkg == null) {
+ if (pkg == null
+ || filterAppAccessLPr((PackageSetting) pkg.mExtras, callingUid,
+ UserHandle.getUserId(callingUid))) {
Slog.w(TAG, "KeySet requested for unknown package: " + packageName);
throw new IllegalArgumentException("Unknown package: " + packageName);
}
@@ -23955,7 +24167,8 @@
@Override
public boolean isPackageSignedByKeySetExactly(String packageName, KeySet ks) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ final int callingUid = Binder.getCallingUid();
+ if (getInstantAppPackageName(callingUid) != null) {
return false;
}
if (packageName == null || ks == null) {
@@ -23963,7 +24176,9 @@
}
synchronized(mPackages) {
final PackageParser.Package pkg = mPackages.get(packageName);
- if (pkg == null) {
+ if (pkg == null
+ || filterAppAccessLPr((PackageSetting) pkg.mExtras, callingUid,
+ UserHandle.getUserId(callingUid))) {
Slog.w(TAG, "KeySet requested for unknown package: " + packageName);
throw new IllegalArgumentException("Unknown package: " + packageName);
}
@@ -24280,8 +24495,34 @@
}
@Override
- public ApplicationInfo getApplicationInfo(String packageName, int userId) {
- return PackageManagerService.this.getApplicationInfo(packageName, 0 /*flags*/, userId);
+ public PackageInfo getPackageInfo(
+ String packageName, int flags, int filterCallingUid, int userId) {
+ return PackageManagerService.this
+ .getPackageInfoInternal(packageName, PackageManager.VERSION_CODE_HIGHEST,
+ flags, filterCallingUid, userId);
+ }
+
+ @Override
+ public ApplicationInfo getApplicationInfo(
+ String packageName, int flags, int filterCallingUid, int userId) {
+ return PackageManagerService.this
+ .getApplicationInfoInternal(packageName, flags, filterCallingUid, userId);
+ }
+
+ @Override
+ public ActivityInfo getActivityInfo(
+ ComponentName component, int flags, int filterCallingUid, int userId) {
+ return PackageManagerService.this
+ .getActivityInfoInternal(component, flags, filterCallingUid, userId);
+ }
+
+ @Override
+ public List<ResolveInfo> queryIntentActivities(
+ Intent intent, int flags, int filterCallingUid, int userId) {
+ final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
+ return PackageManagerService.this
+ .queryIntentActivitiesInternal(intent, resolvedType, flags, filterCallingUid,
+ userId, false /*resolveForStart*/);
}
@Override
@@ -24612,9 +24853,6 @@
@Override
public boolean canRequestPackageInstalls(String packageName, int userId) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
- return false;
- }
return canRequestPackageInstallsInternal(packageName, 0, userId,
true /* throwIfPermNotDeclared*/);
}
diff --git a/services/core/java/com/android/server/policy/AccessibilityShortcutController.java b/services/core/java/com/android/server/policy/AccessibilityShortcutController.java
index 7d53310..3e5e57b 100644
--- a/services/core/java/com/android/server/policy/AccessibilityShortcutController.java
+++ b/services/core/java/com/android/server/policy/AccessibilityShortcutController.java
@@ -233,7 +233,7 @@
private AccessibilityServiceInfo getInfoForTargetService() {
final String currentShortcutServiceString = getTargetServiceComponentNameString(
- mContext, UserHandle.myUserId());
+ mContext, UserHandle.USER_CURRENT);
if (currentShortcutServiceString == null) {
return null;
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index e3bc919..6d46fda 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1418,7 +1418,7 @@
launchHomeFromHotKey();
break;
case SHORT_PRESS_POWER_GO_HOME:
- launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
+ shortPressPowerGoHome();
break;
case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: {
if (mDismissImeOnBackKeyPressed) {
@@ -1430,8 +1430,7 @@
mInputMethodManagerInternal.hideCurrentInputMethod();
}
} else {
- launchHomeFromHotKey(true /* awakenFromDreams */,
- false /*respectKeyguard*/);
+ shortPressPowerGoHome();
}
break;
}
@@ -1439,6 +1438,15 @@
}
}
+ private void shortPressPowerGoHome() {
+ launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
+ if (isKeyguardShowingAndNotOccluded()) {
+ // Notify keyguard so it can do any special handling for the power button since the
+ // device will not power off and only launch home.
+ mKeyguardDelegate.onShortPowerPressedGoHome();
+ }
+ }
+
private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
switch (behavior) {
case MULTI_PRESS_POWER_NOTHING:
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index da90e5a..0121ee1 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -372,6 +372,12 @@
mKeyguardState.bootCompleted = true;
}
+ public void onShortPowerPressedGoHome() {
+ if (mKeyguardService != null) {
+ mKeyguardService.onShortPowerPressedGoHome();
+ }
+ }
+
public void dump(String prefix, PrintWriter pw) {
pw.println(prefix + TAG);
prefix += " ";
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
index 0b839b8..425be54 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
@@ -218,6 +218,15 @@
}
}
+ @Override
+ public void onShortPowerPressedGoHome() {
+ try {
+ mService.onShortPowerPressedGoHome();
+ } catch (RemoteException e) {
+ Slog.w(TAG , "Remote Exception", e);
+ }
+ }
+
@Override // Binder interface
public IBinder asBinder() {
return mService.asBinder();
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 525e0ff..71ecaf6 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1107,7 +1107,7 @@
mAppAnimator.lastFreezeDuration = 0;
mService.mAppsFreezingScreen++;
if (mService.mAppsFreezingScreen == 1) {
- mService.startFreezingDisplayLocked(false, 0, 0);
+ mService.startFreezingDisplayLocked(false, 0, 0, getDisplayContent());
mService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
mService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b5476d7..ccc8f63 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -987,7 +987,7 @@
}
if (!rotateSeamlessly) {
- mService.startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
+ mService.startFreezingDisplayLocked(inTransaction, anim[0], anim[1], this);
// startFreezingDisplayLocked can reset the ScreenRotationAnimation.
screenRotationAnimation = mService.mAnimator.getScreenRotationAnimationLocked(
mDisplayId);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index fb500bc..233e75b 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -858,20 +858,14 @@
final int privateflags = attrs.privateFlags;
boolean displayHasContent = false;
- if (DEBUG_KEEP_SCREEN_ON && (attrFlags & FLAG_KEEP_SCREEN_ON) != 0
- && w != mService.mLastWakeLockHoldingWindow) {
- Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked: " + w
- + " has FLAG_KEEP_SCREEN_ON set, hasSurface=" + w.mHasSurface
- + ", canBeSeen=" + canBeSeen);
- }
-
if (w.mHasSurface && canBeSeen) {
if ((attrFlags & FLAG_KEEP_SCREEN_ON) != 0) {
mHoldScreen = w.mSession;
mHoldScreenWindow = w;
} else if (DEBUG_KEEP_SCREEN_ON && w == mService.mLastWakeLockHoldingWindow) {
Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked: " + w + " was holding "
- + "screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!!");
+ + "screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by"
+ + Debug.getCallers(10));
}
if (!syswin && w.mAttrs.screenBrightness >= 0 && mScreenBrightness < 0) {
mScreenBrightness = w.mAttrs.screenBrightness;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 818df01..bfebca8 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -163,6 +163,8 @@
@VisibleForTesting
boolean shouldDeferRemoval() {
+ // TODO: This should probably return false if mChildren.isEmpty() regardless if the stack
+ // is animating...
return hasWindowsAlive() && mStack.isAnimating();
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 1f7ef50..bf8fabd 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -17,15 +17,13 @@
package com.android.server.wm;
import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS;
-import static android.graphics.Bitmap.Config.ARGB_8888;
-import static android.graphics.Bitmap.Config.HARDWARE;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.StackId;
import android.app.ActivityManager.TaskSnapshot;
+import android.content.pm.PackageManager;
import android.graphics.Bitmap;
-import android.graphics.Canvas;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
import android.os.Environment;
@@ -89,9 +87,16 @@
private final ArraySet<Task> mTmpTasks = new ArraySet<>();
private final Handler mHandler = new Handler();
+ /**
+ * Flag indicating whether we are running on an Android TV device.
+ */
+ private final boolean mIsRunningOnTv;
+
TaskSnapshotController(WindowManagerService service) {
mService = service;
mCache = new TaskSnapshotCache(mService, mLoader);
+ mIsRunningOnTv = mService.mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_LEANBACK);
}
void systemReady() {
@@ -112,7 +117,7 @@
}
private void handleClosingApps(ArraySet<AppWindowToken> closingApps) {
- if (!ENABLE_TASK_SNAPSHOTS || ActivityManager.isLowRamDeviceStatic()) {
+ if (shouldDisableSnapshots()) {
return;
}
@@ -188,6 +193,10 @@
1f /* scale */);
}
+ private boolean shouldDisableSnapshots() {
+ return !ENABLE_TASK_SNAPSHOTS || ActivityManager.isLowRamDeviceStatic() || mIsRunningOnTv;
+ }
+
private Rect minRect(Rect rect1, Rect rect2) {
return new Rect(Math.min(rect1.left, rect2.left),
Math.min(rect1.top, rect2.top),
@@ -301,7 +310,7 @@
* Called when screen is being turned off.
*/
void screenTurningOff(ScreenOffListener listener) {
- if (!ENABLE_TASK_SNAPSHOTS || ActivityManager.isLowRamDeviceStatic()) {
+ if (shouldDisableSnapshots()) {
listener.onScreenOff();
return;
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 3a116bb..551e3bf 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -102,6 +102,8 @@
| FLAG_SCALED
| FLAG_SECURE;
+ private static final int PRIVATE_FLAG_INHERITS = PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+
private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
private static final int MSG_REPORT_DRAW = 0;
private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
@@ -160,7 +162,8 @@
layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
| FLAG_NOT_FOCUSABLE
| FLAG_NOT_TOUCHABLE;
- layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT;
+ layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT
+ | (windowPrivateFlags & PRIVATE_FLAG_INHERITS);
layoutParams.token = token.token;
layoutParams.width = LayoutParams.MATCH_PARENT;
layoutParams.height = LayoutParams.MATCH_PARENT;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index eff8ed9..39878cc 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -109,6 +109,7 @@
/** Application tokens that are exiting, but still on screen for animations. */
final AppTokenList mExitingAppTokens = new AppTokenList();
+ final AppTokenList mTmpAppTokens = new AppTokenList();
/** Detach this stack from its display when animation completes. */
// TODO: maybe tie this to WindowContainer#removeChild some how...
@@ -1626,9 +1627,14 @@
// TODO: Why aren't we just using the loop above for this? mAppAnimator.animating isn't set
// below but is set in the loop above. See if it really matters...
- final int exitingCount = mExitingAppTokens.size();
- for (int i = 0; i < exitingCount; i++) {
- final AppWindowAnimator appAnimator = mExitingAppTokens.get(i).mAppAnimator;
+
+ // Clear before using.
+ mTmpAppTokens.clear();
+ // We copy the list as things can be removed from the exiting token list while we are
+ // processing.
+ mTmpAppTokens.addAll(mExitingAppTokens);
+ for (int i = 0; i < mTmpAppTokens.size(); i++) {
+ final AppWindowAnimator appAnimator = mTmpAppTokens.get(i).mAppAnimator;
appAnimator.wasAnimating = appAnimator.animating;
if (appAnimator.stepAnimationLocked(currentTime)) {
mService.mAnimator.setAnimating(true);
@@ -1641,6 +1647,8 @@
"updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
}
}
+ // Clear to avoid holding reference to tokens.
+ mTmpAppTokens.clear();
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index 4da9c06..6d5673e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
@@ -77,5 +77,5 @@
static final boolean DEBUG_UNKNOWN_APP_VISIBILITY = false;
static final String TAG_KEEP_SCREEN_ON = "DebugKeepScreenOn";
- static final boolean DEBUG_KEEP_SCREEN_ON = true;
+ static final boolean DEBUG_KEEP_SCREEN_ON = false;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 02fdfee..e5af9d2 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -20,7 +20,6 @@
import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.StatusBarManager.DISABLE_MASK;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
@@ -33,6 +32,7 @@
import static android.os.Process.myPid;
import static android.os.UserHandle.USER_NULL;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
@@ -158,6 +158,7 @@
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
+import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -601,7 +602,7 @@
final UnknownAppVisibilityController mUnknownAppVisibilityController =
new UnknownAppVisibilityController(this);
- final TaskSnapshotController mTaskSnapshotController = new TaskSnapshotController(this);
+ final TaskSnapshotController mTaskSnapshotController;
boolean mIsTouchDevice;
@@ -617,6 +618,11 @@
WindowState mCurrentFocus = null;
WindowState mLastFocus = null;
+ /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
+ private final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
+ /** Windows removed since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
+ private final ArrayList<WindowState> mWinRemovedSinceNullFocus = new ArrayList<>();
+
/** This just indicates the window the input method is on top of, not
* necessarily the window its input is going to. */
WindowState mInputMethodTarget = null;
@@ -719,6 +725,9 @@
// For frozen screen animations.
private int mExitAnimId, mEnterAnimId;
+ // The display that the rotation animation is applying to.
+ private int mFrozenDisplayId;
+
/** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
* is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
int mTransactionSequence;
@@ -984,6 +993,7 @@
mWindowPlacerLocked = new WindowSurfacePlacer(this);
mPolicy = policy;
+ mTaskSnapshotController = new TaskSnapshotController(this);
LocalServices.addService(WindowManagerPolicy.class, mPolicy);
@@ -1381,6 +1391,9 @@
// From now on, no exceptions or errors allowed!
res = WindowManagerGlobal.ADD_OKAY;
+ if (mCurrentFocus == null) {
+ mWinAddedSinceNullFocus.add(win);
+ }
if (excludeWindowTypeFromTapOutTask(type)) {
displayContent.mTapExcludedWindows.add(win);
@@ -1667,6 +1680,9 @@
mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
}
+ if (mCurrentFocus == null) {
+ mWinRemovedSinceNullFocus.add(win);
+ }
mPendingRemove.remove(win);
mResizingWindows.remove(win);
mWindowsChanged = true;
@@ -2438,7 +2454,7 @@
} else {
mPolicy.selectRotationAnimationLw(anim);
}
- startFreezingDisplayLocked(false, anim[0], anim[1]);
+ startFreezingDisplayLocked(false, anim[0], anim[1], displayContent);
config = new Configuration(mTempConfiguration);
}
}
@@ -3585,8 +3601,16 @@
// only allow disables from pids which have count on, etc.
@Override
public void showStrictModeViolation(boolean on) {
- int pid = Binder.getCallingPid();
- mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
+ final int pid = Binder.getCallingPid();
+ if (on) {
+ // Show the visualization, and enqueue a second message to tear it
+ // down if we don't hear back from the app.
+ mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 1, pid));
+ mH.sendMessageDelayed(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid),
+ DateUtils.SECOND_IN_MILLIS);
+ } else {
+ mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid));
+ }
}
private void showStrictModeViolation(int arg, int pid) {
@@ -5544,7 +5568,7 @@
if (configChanged) {
mWaitingForConfig = true;
startFreezingDisplayLocked(false /* inTransaction */, 0 /* exitAnim */,
- 0 /* enterAnim */);
+ 0 /* enterAnim */, displayContent);
mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
}
@@ -5804,6 +5828,11 @@
mCurrentFocus = newFocus;
mLosingFocus.remove(newFocus);
+ if (mCurrentFocus != null) {
+ mWinAddedSinceNullFocus.clear();
+ mWinRemovedSinceNullFocus.clear();
+ }
+
int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
if (imWindowChanged && oldFocus != mInputMethodWindow) {
@@ -5846,6 +5875,12 @@
}
void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
+ startFreezingDisplayLocked(inTransaction, exitAnim, enterAnim,
+ getDefaultDisplayContentLocked());
+ }
+
+ void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim,
+ DisplayContent displayContent) {
if (mDisplayFrozen) {
return;
}
@@ -5866,6 +5901,10 @@
mDisplayFreezeTime = SystemClock.elapsedRealtime();
mLastFinishedFreezeSource = null;
+ // {@link mDisplayFrozen} prevents us from freezing on multiple displays at the same time.
+ // As a result, we only track the display that has initially froze the screen.
+ mFrozenDisplayId = displayContent.getDisplayId();
+
mInputMonitor.freezeInputDispatchingLw();
// Clear the last input window -- that is just used for
@@ -5885,10 +5924,8 @@
if (CUSTOM_SCREEN_ROTATION) {
mExitAnimId = exitAnim;
mEnterAnimId = enterAnim;
- final DisplayContent displayContent = getDefaultDisplayContentLocked();
- final int displayId = displayContent.getDisplayId();
ScreenRotationAnimation screenRotationAnimation =
- mAnimator.getScreenRotationAnimationLocked(displayId);
+ mAnimator.getScreenRotationAnimationLocked(mFrozenDisplayId);
if (screenRotationAnimation != null) {
screenRotationAnimation.kill();
}
@@ -5899,8 +5936,10 @@
// TODO(multidisplay): rotation on main screen only.
displayContent.updateDisplayInfo();
screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
- mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure, this);
- mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
+ mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure,
+ this);
+ mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
+ screenRotationAnimation);
}
}
@@ -5924,6 +5963,13 @@
if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
"stopFreezingDisplayLocked: Unfreezing now");
+ final DisplayContent displayContent = mRoot.getDisplayContent(mFrozenDisplayId);
+
+ // We must make a local copy of the displayId as it can be potentially overwritten later on
+ // in this method. For example, {@link startFreezingDisplayLocked} may be called as a result
+ // of update rotation, but we reference the frozen display after that call in this method.
+ final int displayId = mFrozenDisplayId;
+ mFrozenDisplayId = INVALID_DISPLAY;
mDisplayFrozen = false;
mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
StringBuilder sb = new StringBuilder(128);
@@ -5942,8 +5988,6 @@
boolean updateRotation = false;
- final DisplayContent displayContent = getDefaultDisplayContentLocked();
- final int displayId = displayContent.getDisplayId();
ScreenRotationAnimation screenRotationAnimation =
mAnimator.getScreenRotationAnimationLocked(displayId);
if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
@@ -6538,6 +6582,12 @@
if (reason != null) {
pw.println(" Reason: " + reason);
}
+ if (!mWinAddedSinceNullFocus.isEmpty()) {
+ pw.println(" Windows added since null focus: " + mWinAddedSinceNullFocus);
+ }
+ if (!mWinRemovedSinceNullFocus.isEmpty()) {
+ pw.println(" Windows removed since null focus: " + mWinRemovedSinceNullFocus);
+ }
pw.println();
dumpWindowsNoHeaderLocked(pw, true, null);
pw.println();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 44a867c..f74948f 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -18,7 +18,9 @@
import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS;
import static android.app.ActivityManager.StackId;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.isLowRamDeviceStatic;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -761,16 +763,19 @@
final WindowState imeWin = mService.mInputMethodWindow;
// IME is up and obscuring this window. Adjust the window position so it is visible.
if (imeWin != null && imeWin.isVisibleNow() && mService.mInputMethodTarget == this) {
- if (windowsAreFloating && mContainingFrame.bottom > contentFrame.bottom) {
- // In freeform we want to move the top up directly.
- // TODO: Investigate why this is contentFrame not parentFrame.
- mContainingFrame.top -= mContainingFrame.bottom - contentFrame.bottom;
- } else if (mContainingFrame.bottom > parentFrame.bottom) {
- // But in docked we want to behave like fullscreen
- // and behave as if the task were given smaller bounds
- // for the purposes of layout.
- mContainingFrame.bottom = parentFrame.bottom;
- }
+ final int stackId = getStackId();
+ if (stackId == FREEFORM_WORKSPACE_STACK_ID
+ && mContainingFrame.bottom > contentFrame.bottom) {
+ // In freeform we want to move the top up directly.
+ // TODO: Investigate why this is contentFrame not parentFrame.
+ mContainingFrame.top -= mContainingFrame.bottom - contentFrame.bottom;
+ } else if (stackId != PINNED_STACK_ID
+ && mContainingFrame.bottom > parentFrame.bottom) {
+ // But in docked we want to behave like fullscreen and behave as if the task
+ // were given smaller bounds for the purposes of layout. Skip adjustments for
+ // the pinned stack, they are handled separately in the PinnedStackController.
+ mContainingFrame.bottom = parentFrame.bottom;
+ }
}
if (windowsAreFloating) {
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index 9afb2d2..bd6e379 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -17,6 +17,7 @@
package com.android.server.notification;
import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -67,7 +68,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import com.android.server.lights.Light;
@@ -91,6 +91,8 @@
private TestableLooper mTestableLooper;
@Mock
private RankingHelper mRankingHelper;
+ @Mock
+ private NotificationUsageStats mUsageStats;
private NotificationChannel mTestNotificationChannel = new NotificationChannel(
TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
@Mock
@@ -147,7 +149,7 @@
when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
mNotificationManagerService.init(mTestableLooper.getLooper(), mPackageManager,
mPackageManagerClient, mockLightsManager, mNotificationListeners, mCompanionMgr,
- mSnoozeHelper);
+ mSnoozeHelper, mUsageStats);
// Tests call directly into the Binder.
mBinderService = mNotificationManagerService.getBinderService();
@@ -261,40 +263,38 @@
@Test
public void testBlockedNotifications_suspended() throws Exception {
- NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
NotificationChannel channel = new NotificationChannel("id", "name",
NotificationManager.IMPORTANCE_HIGH);
NotificationRecord r = generateNotificationRecord(channel);
- assertTrue(mNotificationManagerService.isBlocked(r, usageStats));
- verify(usageStats, times(1)).registerSuspendedByAdmin(eq(r));
+ assertTrue(mNotificationManagerService.isBlocked(r, mUsageStats));
+ verify(mUsageStats, times(1)).registerSuspendedByAdmin(eq(r));
}
@Test
public void testBlockedNotifications_blockedChannel() throws Exception {
- NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
NotificationChannel channel = new NotificationChannel("id", "name",
NotificationManager.IMPORTANCE_HIGH);
channel.setImportance(NotificationManager.IMPORTANCE_NONE);
NotificationRecord r = generateNotificationRecord(channel);
- assertTrue(mNotificationManagerService.isBlocked(r, usageStats));
- verify(usageStats, times(1)).registerBlocked(eq(r));
+ assertTrue(mNotificationManagerService.isBlocked(r, mUsageStats));
+ verify(mUsageStats, times(1)).registerBlocked(eq(r));
}
@Test
- public void testBlockedNotifications_blockedApp() throws Exception {
- NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
+ public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
- NotificationChannel channel = new NotificationChannel("id", "name",
- NotificationManager.IMPORTANCE_HIGH);
- NotificationRecord r = generateNotificationRecord(channel);
- r.setUserImportance(NotificationManager.IMPORTANCE_NONE);
- assertTrue(mNotificationManagerService.isBlocked(r, usageStats));
- verify(usageStats, times(1)).registerBlocked(eq(r));
+ mBinderService.setNotificationsEnabledForPackage(PKG, uid, false);
+
+ final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
+ mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+ sbn.getId(), sbn.getNotification(), sbn.getUserId());
+ waitForIdle();
+ assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
}
@Test
@@ -645,6 +645,7 @@
associations.add("a");
when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
mListener = mock(ManagedServices.ManagedServiceInfo.class);
+ mListener.component = new ComponentName(PKG, PKG);
when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
index 0812783..5a6225a 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
@@ -35,6 +35,7 @@
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.media.AudioAttributes;
+import android.metrics.LogMaker;
import android.net.Uri;
import android.os.Build;
import android.os.UserHandle;
@@ -44,6 +45,8 @@
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -71,6 +74,14 @@
private final String channelId = "channel";
NotificationChannel channel =
new NotificationChannel(channelId, "test", NotificationManager.IMPORTANCE_DEFAULT);
+ private final String channelIdLong =
+ "give_a_developer_a_string_argument_and_who_knows_what_they_will_pass_in_there";
+ final String groupId = "group";
+ final String groupIdOverride = "other_group";
+ private final String groupIdLong =
+ "0|com.foo.bar|g:content://com.foo.bar.ui/account%3A-0000000/account/";
+ NotificationChannel channelLongId =
+ new NotificationChannel(channelIdLong, "long", NotificationManager.IMPORTANCE_DEFAULT);
NotificationChannel defaultChannel =
new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "test",
NotificationManager.IMPORTANCE_UNSPECIFIED);
@@ -107,7 +118,8 @@
}
private StatusBarNotification getNotification(boolean preO, boolean noisy, boolean defaultSound,
- boolean buzzy, boolean defaultVibration, boolean lights, boolean defaultLights) {
+ boolean buzzy, boolean defaultVibration, boolean lights, boolean defaultLights,
+ String group) {
when(mMockContext.getApplicationInfo()).thenReturn(preO ? legacy : upgrade);
final Builder builder = new Builder(mMockContext)
.setContentTitle("foo")
@@ -151,6 +163,9 @@
builder.setChannelId(channelId);
}
+ if(group != null) {
+ builder.setGroup(group);
+ }
Notification n = builder.build();
if (preO) {
@@ -172,7 +187,7 @@
// pre upgrade, default sound.
StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
- false /* lights */, false /*defaultLights */);
+ false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, record.getSound());
@@ -185,7 +200,7 @@
// pre upgrade, custom sound.
StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
- false /* lights */, false /*defaultLights */);
+ false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
assertEquals(CUSTOM_SOUND, record.getSound());
@@ -199,7 +214,7 @@
// pre upgrade, default sound.
StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
- false /* lights */, false /*defaultLights */);
+ false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
assertEquals(CUSTOM_SOUND, record.getSound());
@@ -211,7 +226,7 @@
// pre upgrade, default sound.
StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
- false /* lights */, false /*defaultLights */);
+ false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
assertEquals(null, record.getSound());
@@ -224,7 +239,7 @@
// post upgrade, default sound.
StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
- false /* lights */, false /*defaultLights */);
+ false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
assertEquals(CUSTOM_SOUND, record.getSound());
@@ -237,7 +252,7 @@
// pre upgrade, default vibration.
StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
false /* defaultSound */, true /* buzzy */, true /* defaultBuzz */,
- false /* lights */, false /*defaultLights */);
+ false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
assertNotNull(record.getVibration());
@@ -249,7 +264,7 @@
// pre upgrade, custom vibration.
StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
- false /* lights */, false /*defaultLights */);
+ false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
assertEquals(CUSTOM_VIBRATION, record.getVibration());
@@ -262,7 +277,7 @@
// pre upgrade, custom vibration.
StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
- false /* lights */, false /*defaultLights */);
+ false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
assertTrue(!Objects.equals(CUSTOM_VIBRATION, record.getVibration()));
@@ -274,7 +289,7 @@
// post upgrade, custom vibration.
StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
- false /* lights */, false /*defaultLights */);
+ false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
assertEquals(CUSTOM_CHANNEL_VIBRATION, record.getVibration());
@@ -284,7 +299,7 @@
public void testImportance_preUpgrade() throws Exception {
StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
- false /* lights */, false /*defaultLights */);
+ false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
assertEquals(NotificationManager.IMPORTANCE_HIGH, record.getImportance());
}
@@ -295,7 +310,7 @@
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
- false /* lights */, false /*defaultLights */);
+ false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
assertEquals(NotificationManager.IMPORTANCE_LOW, record.getImportance());
@@ -307,7 +322,7 @@
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
- false /* lights */, false /*defaultLights */);
+ false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
assertEquals(NotificationManager.IMPORTANCE_HIGH, record.getImportance());
@@ -317,7 +332,7 @@
public void testImportance_upgrade() throws Exception {
StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
- false /* lights */, false /*defaultLights */);
+ false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
assertEquals(NotificationManager.IMPORTANCE_DEFAULT, record.getImportance());
}
@@ -326,7 +341,7 @@
public void testLights_preUpgrade_noLight() throws Exception {
StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
- false /* lights */, false /*defaultLights */);
+ false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
assertNull(record.getLight());
}
@@ -336,7 +351,7 @@
public void testLights_preUpgrade() throws Exception {
StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
- true /* lights */, false /*defaultLights */);
+ true /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
assertEquals(CUSTOM_LIGHT, record.getLight());
}
@@ -347,7 +362,7 @@
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
- true /* lights */, false /*defaultLights */);
+ true /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
assertFalse(CUSTOM_LIGHT.equals(record.getLight()));
@@ -366,7 +381,7 @@
defaultLightColor, defaultLightOn, defaultLightOff);
StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
- true /* lights */, true /*defaultLights */);
+ true /* lights */, true /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
assertEquals(expected, record.getLight());
}
@@ -382,7 +397,7 @@
Color.BLUE, defaultLightOn, defaultLightOff);
StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
- true /* lights */, false /*defaultLights */);
+ true /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
assertEquals(expected, record.getLight());
}
@@ -391,8 +406,80 @@
public void testLights_upgrade_noLight() throws Exception {
StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
- false /* lights */, false /*defaultLights */);
+ false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
assertNull(record.getLight());
}
+
+ @Test
+ public void testLogmakerShortChannel() throws Exception {
+ StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+ false /* lights */, false /* defaultLights */, null /* group */);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ final LogMaker logMaker = record.getLogMaker();
+ assertEquals(channelId,
+ (String) logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID));
+ assertEquals(channel.getImportance(),
+ logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE));
+ }
+
+ @Test
+ public void testLogmakerLongChannel() throws Exception {
+ StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+ false /* lights */, false /*defaultLights */, null /* group */);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channelLongId);
+ final String loggedId = (String)
+ record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID);
+ assertEquals(channelIdLong.substring(0,10), loggedId.substring(0, 10));
+ }
+
+ @Test
+ public void testLogmakerNoGroup() throws Exception {
+ StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+ false /* lights */, false /*defaultLights */, null /* group */);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ assertNull(record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+ }
+
+ @Test
+ public void testLogmakerShortGroup() throws Exception {
+ StatusBarNotification sbn = getNotification(false /*reO */, true /* noisy */,
+ true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+ false /* lights */, false /* defaultLights */, groupId /* group */);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ assertEquals(groupId,
+ record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+ }
+
+ @Test
+ public void testLogmakerLongGroup() throws Exception {
+ StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+ false /* lights */, false /* defaultLights */, groupIdLong /* group */);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ final String loggedId = (String)
+ record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID);
+ assertEquals(groupIdLong.substring(0,10), loggedId.substring(0, 10));
+ }
+
+ @Test
+ public void testLogmakerOverrideGroup() throws Exception {
+ StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+ false /* lights */, false /* defaultLights */, groupId /* group */);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ assertEquals(groupId,
+ record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+ record.setOverrideGroupKey(groupIdOverride);
+ assertEquals(groupIdOverride,
+ record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+ record.setOverrideGroupKey(null);
+ assertEquals(groupId,
+ record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+ }
+
+
}
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 686dad4..e12032d 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -52,6 +52,10 @@
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
+ <!-- Uses API introduced in O (26) -->
+ <uses-sdk android:minSdkVersion="1"
+ android:targetSdkVersion="26"/>
+
<application>
<uses-library android:name="android.test.runner" />
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 36e9b3f8..791d3e9 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -1484,6 +1484,31 @@
}
@SmallTest
+ public void testGetAccountsByTypeForPackageWhenTypeIsNull() throws Exception {
+ unlockSystemUser();
+ HashMap<String, Integer> visibility1 = new HashMap<>();
+ visibility1.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE,
+ AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
+
+ HashMap<String, Integer> visibility2 = new HashMap<>();
+ visibility2.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE,
+ AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE);
+
+ mAms.addAccountExplicitlyWithVisibility(
+ AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "P11", null, visibility1);
+ mAms.addAccountExplicitlyWithVisibility(
+ AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "P12", null, visibility2);
+
+ Account[] accounts = mAms.getAccountsByTypeForPackage(
+ null, "otherPackageName",
+ AccountManagerServiceTestFixtures.CALLER_PACKAGE);
+ // Only get the USER_MANAGED_NOT_VISIBLE account.
+ assertEquals(1, accounts.length);
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, accounts[0].name);
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, accounts[0].type);
+ }
+
+ @SmallTest
public void testGetAuthTokenLabelWithNullAccountType() throws Exception {
unlockSystemUser();
try {
@@ -2341,6 +2366,224 @@
}
@SmallTest
+ public void testGetAccountByTypeAndFeaturesWithNullResponse() throws Exception {
+ unlockSystemUser();
+ try {
+ mAms.getAccountByTypeAndFeatures(
+ null, // response
+ AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+ AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+ "testpackage"); // opPackageName
+ fail("IllegalArgumentException expected. But no exception was thrown.");
+ } catch (IllegalArgumentException e) {
+ // IllegalArgumentException is expected.
+ }
+ }
+
+ @SmallTest
+ public void testGetAccountByTypeAndFeaturesWithNullAccountType() throws Exception {
+ unlockSystemUser();
+ try {
+ mAms.getAccountByTypeAndFeatures(
+ mMockAccountManagerResponse, // response
+ null, // accountType
+ AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+ "testpackage"); // opPackageName
+ fail("IllegalArgumentException expected. But no exception was thrown.");
+ } catch (IllegalArgumentException e) {
+ // IllegalArgumentException is expected.
+ }
+ }
+
+ @SmallTest
+ public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndNoAccount() throws Exception {
+ unlockSystemUser();
+ mAms.getAccountByTypeAndFeatures(
+ mMockAccountManagerResponse,
+ AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+ null,
+ "testpackage");
+ verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+ Bundle result = mBundleCaptor.getValue();
+ String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+ String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
+ assertEquals(null, accountName);
+ assertEquals(null, accountType);
+ }
+
+ @SmallTest
+ public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndOneVisibleAccount()
+ throws Exception {
+ unlockSystemUser();
+ mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null);
+ mAms.getAccountByTypeAndFeatures(
+ mMockAccountManagerResponse,
+ AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+ null,
+ "testpackage");
+ verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+ Bundle result = mBundleCaptor.getValue();
+ String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+ String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, accountName);
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, accountType);
+ }
+
+ @SmallTest
+ public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndOneNotVisibleAccount()
+ throws Exception {
+ unlockSystemUser();
+ HashMap<String, Integer> visibility = new HashMap<>();
+ visibility.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE,
+ AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE);
+ mAms.addAccountExplicitlyWithVisibility(
+ AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null, visibility);
+ mAms.getAccountByTypeAndFeatures(
+ mMockAccountManagerResponse,
+ AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+ null,
+ AccountManagerServiceTestFixtures.CALLER_PACKAGE);
+ verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM));
+ Intent intent = mIntentCaptor.getValue();
+ Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS);
+ assertEquals(1, accounts.length);
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]);
+ }
+
+ @SmallTest
+ public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndTwoAccounts() throws Exception {
+ unlockSystemUser();
+ mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null);
+ mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p12", null);
+
+ mAms.getAccountByTypeAndFeatures(
+ mMockAccountManagerResponse,
+ AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+ null,
+ "testpackage");
+ verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM));
+ Intent intent = mIntentCaptor.getValue();
+ Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS);
+ assertEquals(2, accounts.length);
+ if (accounts[0].equals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS)) {
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]);
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, accounts[1]);
+ } else {
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, accounts[0]);
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[1]);
+ }
+ }
+
+ @SmallTest
+ public void testGetAccountByTypeAndFeaturesWithFeaturesAndNoAccount() throws Exception {
+ unlockSystemUser();
+ final CountDownLatch latch = new CountDownLatch(1);
+ mAms.getAccountByTypeAndFeatures(
+ mMockAccountManagerResponse,
+ AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+ AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+ "testpackage");
+ waitForLatch(latch);
+ verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+ Bundle result = mBundleCaptor.getValue();
+ String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+ String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
+ assertEquals(null, accountName);
+ assertEquals(null, accountType);
+ }
+
+ @SmallTest
+ public void testGetAccountByTypeAndFeaturesWithFeaturesAndNoQualifiedAccount()
+ throws Exception {
+ unlockSystemUser();
+ mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p12", null);
+ final CountDownLatch latch = new CountDownLatch(1);
+ mAms.getAccountByTypeAndFeatures(
+ mMockAccountManagerResponse,
+ AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+ AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+ "testpackage");
+ waitForLatch(latch);
+ verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+ Bundle result = mBundleCaptor.getValue();
+ String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+ String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
+ assertEquals(null, accountName);
+ assertEquals(null, accountType);
+ }
+
+ @SmallTest
+ public void testGetAccountByTypeAndFeaturesWithFeaturesAndOneQualifiedAccount()
+ throws Exception {
+ unlockSystemUser();
+ mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null);
+ mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p12", null);
+ final CountDownLatch latch = new CountDownLatch(1);
+ mAms.getAccountByTypeAndFeatures(
+ mMockAccountManagerResponse,
+ AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+ AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+ "testpackage");
+ waitForLatch(latch);
+ verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+ Bundle result = mBundleCaptor.getValue();
+ String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+ String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, accountName);
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, accountType);
+ }
+
+ @SmallTest
+ public void testGetAccountByTypeAndFeaturesWithFeaturesAndOneQualifiedNotVisibleAccount()
+ throws Exception {
+ unlockSystemUser();
+ HashMap<String, Integer> visibility = new HashMap<>();
+ visibility.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE,
+ AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE);
+ mAms.addAccountExplicitlyWithVisibility(
+ AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null, visibility);
+ final CountDownLatch latch = new CountDownLatch(1);
+ mAms.getAccountByTypeAndFeatures(
+ mMockAccountManagerResponse,
+ AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+ AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+ AccountManagerServiceTestFixtures.CALLER_PACKAGE);
+ waitForLatch(latch);
+ verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM));
+ Intent intent = mIntentCaptor.getValue();
+ Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS);
+ assertEquals(1, accounts.length);
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]);
+ }
+
+ @SmallTest
+ public void testGetAccountByTypeAndFeaturesWithFeaturesAndTwoQualifiedAccount()
+ throws Exception {
+ unlockSystemUser();
+ mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null);
+ mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_2, "p12", null);
+ mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p13", null);
+ final CountDownLatch latch = new CountDownLatch(1);
+ mAms.getAccountByTypeAndFeatures(
+ mMockAccountManagerResponse,
+ AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+ AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+ "testpackage");
+ waitForLatch(latch);
+ verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM));
+ Intent intent = mIntentCaptor.getValue();
+ Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS);
+ assertEquals(2, accounts.length);
+ if (accounts[0].equals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS)) {
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]);
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_2, accounts[1]);
+ } else {
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_2, accounts[0]);
+ assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[1]);
+ }
+ }
+
+ @SmallTest
public void testGetAccountsByFeaturesWithNullResponse() throws Exception {
unlockSystemUser();
try {
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java
index d176a0d..73f30d9 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java
@@ -34,6 +34,7 @@
public static final String KEY_OPTIONS_BUNDLE =
"account_manager_service_test:option_bundle_key";
public static final String ACCOUNT_NAME_SUCCESS = "success_on_return@fixture.com";
+ public static final String ACCOUNT_NAME_SUCCESS_2 = "success_on_return_2@fixture.com";
public static final String ACCOUNT_NAME_INTERVENE = "intervene@fixture.com";
public static final String ACCOUNT_NAME_ERROR = "error@fixture.com";
@@ -69,6 +70,8 @@
public static final Account ACCOUNT_SUCCESS =
new Account(ACCOUNT_NAME_SUCCESS, ACCOUNT_TYPE_1);
+ public static final Account ACCOUNT_SUCCESS_2 =
+ new Account(ACCOUNT_NAME_SUCCESS_2, ACCOUNT_TYPE_1);
public static final Account ACCOUNT_INTERVENE =
new Account(ACCOUNT_NAME_INTERVENE, ACCOUNT_TYPE_1);
public static final Account ACCOUNT_ERROR =
diff --git a/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java
index eb839a2..8106364 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java
@@ -242,6 +242,8 @@
if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) {
// fill bundle with true.
result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
+ } else if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS_2)) {
+ result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
} else if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE)) {
// fill bundle with false.
result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 26a406f..ca74688 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -407,13 +407,15 @@
UsbManager.USB_FUNCTION_ADB);
/**
- * Remove MTP from persistent config, to bring usb to a good state
- * after fixes to b/31814300. This block can be removed after the update
+ * Previous versions can set persist config to mtp/ptp but it does not
+ * get reset on OTA. Reset the property here instead.
*/
String persisted = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY);
- if (UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_MTP)) {
+ if (UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_MTP)
+ || UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_PTP)) {
SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY,
- UsbManager.removeFunction(persisted, UsbManager.USB_FUNCTION_MTP));
+ UsbManager.removeFunction(UsbManager.removeFunction(persisted,
+ UsbManager.USB_FUNCTION_MTP), UsbManager.USB_FUNCTION_PTP));
}
String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 0c5e4bd..3788cf3 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -16,6 +16,8 @@
package com.android.server.voiceinteraction;
+import static android.app.ActivityManager.START_ASSISTANT_HIDDEN_SESSION;
+import static android.app.ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION;
import static android.app.ActivityManager.START_VOICE_HIDDEN_SESSION;
import static android.app.ActivityManager.START_VOICE_NOT_ACTIVE_SESSION;
@@ -212,11 +214,11 @@
try {
if (mActiveSession == null || token != mActiveSession.mToken) {
Slog.w(TAG, "startAssistantActivity does not match active session");
- return START_VOICE_NOT_ACTIVE_SESSION;
+ return START_ASSISTANT_NOT_ACTIVE_SESSION;
}
if (!mActiveSession.mShown) {
Slog.w(TAG, "startAssistantActivity not allowed on hidden session");
- return START_VOICE_HIDDEN_SESSION;
+ return START_ASSISTANT_HIDDEN_SESSION;
}
intent = new Intent(intent);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 4267ec4..d394d63 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -453,6 +453,7 @@
mShowFlags = 0;
mHaveAssistData = false;
mAssistData.clear();
+ mPendingShowCallbacks.clear();
if (mSession != null) {
try {
mSession.hide();
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 0a47a98..d0b36c9 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -17,7 +17,9 @@
import android.Manifest;
import android.annotation.RequiresPermission;
import android.annotation.SuppressAutoDoc;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -48,6 +50,7 @@
* descriptions.
*/
@SuppressAutoDoc
+@SystemService(Context.TELECOM_SERVICE)
public class TelecomManager {
/**
@@ -734,6 +737,10 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PHONE_STATE
+ })
public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme) {
try {
if (isServiceConnected()) {
@@ -815,6 +822,7 @@
* @hide
*/
@SystemApi
+ @SuppressLint("Doclava125")
public List<PhoneAccountHandle> getPhoneAccountsForPackage() {
try {
if (isServiceConnected()) {
@@ -942,6 +950,7 @@
* @hide
*/
@SystemApi
+ @SuppressLint("Doclava125")
public void clearPhoneAccounts() {
clearAccounts();
}
@@ -951,6 +960,7 @@
* @hide
*/
@SystemApi
+ @SuppressLint("Doclava125")
public void clearAccounts() {
try {
if (isServiceConnected()) {
@@ -982,6 +992,7 @@
* @hide
*/
@SystemApi
+ @SuppressLint("Doclava125")
public ComponentName getDefaultPhoneApp() {
try {
if (isServiceConnected()) {
@@ -1198,6 +1209,10 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PHONE_STATE
+ })
public boolean isRinging() {
try {
if (isServiceConnected()) {
@@ -1216,6 +1231,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean endCall() {
try {
if (isServiceConnected()) {
@@ -1295,6 +1311,10 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PHONE_STATE
+ })
public boolean isTtySupported() {
try {
if (isServiceConnected()) {
@@ -1573,6 +1593,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void enablePhoneAccount(PhoneAccountHandle handle, boolean isEnabled) {
ITelecomService service = getTelecomService();
if (service != null) {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 7174a70..c6c1be3 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -18,7 +18,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.Context;
import android.os.PersistableBundle;
import android.os.RemoteException;
@@ -29,14 +32,8 @@
/**
* Provides access to telephony configuration values that are carrier-specific.
- * <p>
- * Users should obtain an instance of this class by calling
- * {@code mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);}
- * </p>
- *
- * @see Context#getSystemService
- * @see Context#CARRIER_CONFIG_SERVICE
*/
+@SystemService(Context.CARRIER_CONFIG_SERVICE)
public class CarrierConfigManager {
private final static String TAG = "CarrierConfigManager";
@@ -1742,6 +1739,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void updateConfigForPhoneId(int phoneId, String simState) {
try {
ICarrierConfigLoader loader = getICarrierConfigLoader();
@@ -1763,6 +1761,7 @@
*/
@NonNull
@SystemApi
+ @SuppressLint("Doclava125")
public static PersistableBundle getDefaultConfig() {
return new PersistableBundle(sDefaults);
}
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 7d4d90b..1eac263 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.app.PendingIntent;
@@ -346,6 +347,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void sendTextMessageWithoutPersisting(
String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
@@ -530,6 +532,7 @@
* @hide
**/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void sendMultipartTextMessageWithoutPersisting(
String destinationAddress, String scAddress, List<String> parts,
List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 7f616ad..709877d 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.SdkConstant;
+import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.content.Intent;
@@ -41,12 +42,10 @@
/**
* SubscriptionManager is the application interface to SubscriptionController
* and provides information about the current Telephony Subscriptions.
- * * <p>
- * You do not instantiate this class directly; instead, you retrieve
- * a reference to an instance through {@link #from}.
* <p>
* All SDK public methods require android.Manifest.permission.READ_PHONE_STATE.
*/
+@SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
public class SubscriptionManager {
private static final String LOG_TAG = "SubscriptionManager";
private static final boolean DBG = false;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b8e24f0..6b921c7 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -22,8 +22,10 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.annotation.WorkerThread;
import android.app.ActivityThread;
import android.app.PendingIntent;
@@ -79,11 +81,6 @@
* types of subscriber information. Applications can also register
* a listener to receive notification of telephony state changes.
* <p>
- * You do not instantiate this class directly; instead, you retrieve
- * a reference to an instance through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.TELEPHONY_SERVICE)}.
- *
* The returned TelephonyManager will use the default subscription for all calls.
* To call an API for a specific subscription, use {@link #createForSubscriptionId(int)}. e.g.
* <code>
@@ -96,6 +93,7 @@
* its manifest file. Where permissions apply, they are noted in the
* the methods through which you access the protected information.
*/
+@SystemService(Context.TELEPHONY_SERVICE)
public class TelephonyManager {
private static final String TAG = "TelephonyManager";
@@ -2671,8 +2669,8 @@
* be implemented instead.
*/
@SystemApi
+ @SuppressLint("Doclava125")
public void setVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle, boolean enabled){
-
}
/**
@@ -2686,6 +2684,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @SuppressLint("Doclava125")
public boolean isVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle){
return false;
}
@@ -2704,6 +2703,7 @@
* @hide
*/
@SystemApi
+ @SuppressLint("Doclava125")
@Nullable
public Bundle getVisualVoicemailSettings(){
try {
@@ -4855,12 +4855,14 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public String getCdmaMdn() {
return getCdmaMdn(getSubId());
}
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public String getCdmaMdn(int subId) {
try {
ITelephony telephony = getITelephony();
@@ -4876,12 +4878,14 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public String getCdmaMin() {
return getCdmaMin(getSubId());
}
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public String getCdmaMin(int subId) {
try {
ITelephony telephony = getITelephony();
@@ -4897,6 +4901,7 @@
/** @hide */
@SystemApi
+ @SuppressLint("Doclava125")
public int checkCarrierPrivilegesForPackage(String pkgName) {
try {
ITelephony telephony = getITelephony();
@@ -4912,6 +4917,7 @@
/** @hide */
@SystemApi
+ @SuppressLint("Doclava125")
public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
try {
ITelephony telephony = getITelephony();
@@ -4963,6 +4969,7 @@
/** @hide */
@SystemApi
+ @SuppressLint("Doclava125")
public void dial(String number) {
try {
ITelephony telephony = getITelephony();
@@ -4975,6 +4982,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.CALL_PHONE)
public void call(String callingPackage, String number) {
try {
ITelephony telephony = getITelephony();
@@ -4987,6 +4995,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.CALL_PHONE)
public boolean endCall() {
try {
ITelephony telephony = getITelephony();
@@ -5000,6 +5009,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void answerRingingCall() {
try {
ITelephony telephony = getITelephony();
@@ -5012,6 +5022,7 @@
/** @hide */
@SystemApi
+ @SuppressLint("Doclava125")
public void silenceRinger() {
try {
getTelecomService().silenceRinger(getOpPackageName());
@@ -5022,6 +5033,10 @@
/** @hide */
@SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PHONE_STATE
+ })
public boolean isOffhook() {
try {
ITelephony telephony = getITelephony();
@@ -5035,6 +5050,10 @@
/** @hide */
@SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PHONE_STATE
+ })
public boolean isRinging() {
try {
ITelephony telephony = getITelephony();
@@ -5048,6 +5067,10 @@
/** @hide */
@SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PHONE_STATE
+ })
public boolean isIdle() {
try {
ITelephony telephony = getITelephony();
@@ -5061,6 +5084,10 @@
/** @hide */
@SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PHONE_STATE
+ })
public boolean isRadioOn() {
try {
ITelephony telephony = getITelephony();
@@ -5074,6 +5101,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean supplyPin(String pin) {
try {
ITelephony telephony = getITelephony();
@@ -5087,6 +5115,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean supplyPuk(String puk, String pin) {
try {
ITelephony telephony = getITelephony();
@@ -5100,6 +5129,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public int[] supplyPinReportResult(String pin) {
try {
ITelephony telephony = getITelephony();
@@ -5113,6 +5143,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public int[] supplyPukReportResult(String puk, String pin) {
try {
ITelephony telephony = getITelephony();
@@ -5232,6 +5263,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean handlePinMmi(String dialString) {
try {
ITelephony telephony = getITelephony();
@@ -5245,6 +5277,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean handlePinMmiForSubscriber(int subId, String dialString) {
try {
ITelephony telephony = getITelephony();
@@ -5258,6 +5291,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void toggleRadioOnOff() {
try {
ITelephony telephony = getITelephony();
@@ -5270,6 +5304,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean setRadio(boolean turnOn) {
try {
ITelephony telephony = getITelephony();
@@ -5283,6 +5318,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean setRadioPower(boolean turnOn) {
try {
ITelephony telephony = getITelephony();
@@ -5296,6 +5332,7 @@
/** @hide */
@SystemApi
+ @SuppressLint("Doclava125")
public void updateServiceLocation() {
try {
ITelephony telephony = getITelephony();
@@ -5308,6 +5345,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean enableDataConnectivity() {
try {
ITelephony telephony = getITelephony();
@@ -5321,6 +5359,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean disableDataConnectivity() {
try {
ITelephony telephony = getITelephony();
@@ -5371,12 +5410,14 @@
*
* @see #hasCarrierPrivileges
*/
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setDataEnabled(boolean enable) {
setDataEnabled(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enable);
}
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setDataEnabled(int subId, boolean enable) {
try {
Log.d(TAG, "setDataEnabled: enabled=" + enable);
@@ -5466,6 +5507,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void enableVideoCalling(boolean enable) {
try {
ITelephony telephony = getITelephony();
@@ -5478,6 +5520,10 @@
/** @hide */
@SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PHONE_STATE
+ })
public boolean isVideoCallingEnabled() {
try {
ITelephony telephony = getITelephony();
@@ -6346,6 +6392,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public List<TelephonyHistogram> getTelephonyHistograms() {
try {
ITelephony service = getITelephony();
@@ -6373,6 +6420,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public int setAllowedCarriers(int slotIndex, List<CarrierIdentifier> carriers) {
try {
ITelephony service = getITelephony();
@@ -6391,9 +6439,6 @@
* Get the allowed carrier list for slotIndex.
* Require system privileges. In the future we may add this to carrier APIs.
*
- * <p>Requires Permission:
- * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}
- *
* <p>This method returns valid data on devices with {@link
* android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled.
*
@@ -6402,6 +6447,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public List<CarrierIdentifier> getAllowedCarriers(int slotIndex) {
try {
ITelephony service = getITelephony();
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java
index db45b9d..99d44e6 100644
--- a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java
@@ -17,7 +17,7 @@
import android.os.Bundle;
import android.support.v4.app.Fragment;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@@ -31,7 +31,7 @@
/**
* Main activity of the app.
*/
-public class MainActivity extends ActionBarActivity {
+public class MainActivity extends AppCompatActivity {
private static final String LOG = "MainActivity";
diff --git a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
index 7632a6e..55440c8 100644
--- a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
+++ b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
@@ -21,7 +21,7 @@
import android.graphics.Color;
import android.graphics.Paint;
import android.os.CountDownTimer;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.Touch;
import android.util.AttributeSet;
@@ -173,7 +173,7 @@
private float mVelocityX, mVelocityY;
}
-public class TouchLatencyActivity extends ActionBarActivity {
+public class TouchLatencyActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index 3172c6e..281223e 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -16,6 +16,12 @@
package com.android.server.connectivity;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyBoolean;
@@ -201,12 +207,19 @@
private void sendWifiApStateChanged(int state) {
final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
- intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, state);
+ intent.putExtra(EXTRA_WIFI_AP_STATE, state);
+ mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
+ private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
+ final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
+ intent.putExtra(EXTRA_WIFI_AP_STATE, state);
+ intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
+ intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
private void verifyInterfaceServingModeStarted() throws Exception {
- verify(mNMService, times(1)).listInterfaces();
verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
verify(mNMService, times(1))
.setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
@@ -223,14 +236,32 @@
}
@Test
- public void workingLocalOnlyHotspot() throws Exception {
+ public void failingLocalOnlyHotspotLegacyApBroadcast() throws Exception {
when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
// Emulate externally-visible WifiManager effects, causing the
// per-interface state machine to start up, and telling us that
// hotspot mode is to be started.
mTethering.interfaceStatusChanged(mTestIfname, true);
- sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
+ sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
+ mLooper.dispatchAll();
+
+ verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
+ verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
+ verifyNoMoreInteractions(mConnectivityManager);
+ verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mWifiManager);
+ }
+
+ @Test
+ public void workingLocalOnlyHotspotEnrichedApBroadcast() throws Exception {
+ when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
+
+ // Emulate externally-visible WifiManager effects, causing the
+ // per-interface state machine to start up, and telling us that
+ // hotspot mode is to be started.
+ mTethering.interfaceStatusChanged(mTestIfname, true);
+ sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, mTestIfname, IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
verifyInterfaceServingModeStarted();
@@ -274,7 +305,7 @@
}
@Test
- public void workingWifiTethering() throws Exception {
+ public void failingWifiTetheringLegacyApBroadcast() throws Exception {
when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
@@ -290,7 +321,34 @@
// per-interface state machine to start up, and telling us that
// tethering mode is to be started.
mTethering.interfaceStatusChanged(mTestIfname, true);
- sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
+ sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
+ mLooper.dispatchAll();
+
+ verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
+ verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
+ verifyNoMoreInteractions(mConnectivityManager);
+ verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mWifiManager);
+ }
+
+ @Test
+ public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
+ when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
+ when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
+
+ // Emulate pressing the WiFi tethering button.
+ mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
+ mLooper.dispatchAll();
+ verify(mWifiManager, times(1)).startSoftAp(null);
+ verifyNoMoreInteractions(mWifiManager);
+ verifyNoMoreInteractions(mConnectivityManager);
+ verifyNoMoreInteractions(mNMService);
+
+ // Emulate externally-visible WifiManager effects, causing the
+ // per-interface state machine to start up, and telling us that
+ // tethering mode is to be started.
+ mTethering.interfaceStatusChanged(mTestIfname, true);
+ sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, mTestIfname, IFACE_IP_MODE_TETHERED);
mLooper.dispatchAll();
verifyInterfaceServingModeStarted();
@@ -372,11 +430,9 @@
// per-interface state machine to start up, and telling us that
// tethering mode is to be started.
mTethering.interfaceStatusChanged(mTestIfname, true);
- sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
+ sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, mTestIfname, IFACE_IP_MODE_TETHERED);
mLooper.dispatchAll();
- // Activity caused by test_wlan0 becoming available.
- verify(mNMService, times(1)).listInterfaces();
// We verify get/set called twice here: once for setup and once during
// teardown because all events happen over the course of the single
// dispatchAll() above.
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index b2f1f62..eff8283 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -159,7 +159,7 @@
// ==========================================================
cc_test_host {
name: "aapt2_tests",
- srcs: ["**/*_test.cpp"],
+ srcs: ["test/Common.cpp", "**/*_test.cpp"],
static_libs: ["libaapt2", "libgmock"],
defaults: ["aapt_defaults"],
}
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 32e0fd5..9503b56 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -623,6 +623,11 @@
return std::move(string);
}
+ // If the text is empty, and the value is not allowed to be a string, encode it as a @null.
+ if (util::TrimWhitespace(raw_value).empty()) {
+ return ResourceUtils::MakeNull();
+ }
+
if (allow_raw_value) {
// We can't parse this so return a RawString if we are allowed.
return util::make_unique<RawString>(
diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h
index 8258019..5631dc2 100644
--- a/tools/aapt2/ResourceParser.h
+++ b/tools/aapt2/ResourceParser.h
@@ -78,42 +78,32 @@
* Item, then a
* RawString is returned. Otherwise this returns false;
*/
- std::unique_ptr<Item> ParseXml(xml::XmlPullParser* parser,
- const uint32_t type_mask,
+ std::unique_ptr<Item> ParseXml(xml::XmlPullParser* parser, const uint32_t type_mask,
const bool allow_raw_value);
bool ParseResources(xml::XmlPullParser* parser);
bool ParseResource(xml::XmlPullParser* parser, ParsedResource* out_resource);
- bool ParseItem(xml::XmlPullParser* parser, ParsedResource* out_resource,
- uint32_t format);
+ bool ParseItem(xml::XmlPullParser* parser, ParsedResource* out_resource, uint32_t format);
bool ParseString(xml::XmlPullParser* parser, ParsedResource* out_resource);
bool ParsePublic(xml::XmlPullParser* parser, ParsedResource* out_resource);
- bool ParsePublicGroup(xml::XmlPullParser* parser,
- ParsedResource* out_resource);
- bool ParseSymbolImpl(xml::XmlPullParser* parser,
- ParsedResource* out_resource);
+ bool ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource* out_resource);
+ bool ParseSymbolImpl(xml::XmlPullParser* parser, ParsedResource* out_resource);
bool ParseSymbol(xml::XmlPullParser* parser, ParsedResource* out_resource);
- bool ParseAddResource(xml::XmlPullParser* parser,
- ParsedResource* out_resource);
+ bool ParseAddResource(xml::XmlPullParser* parser, ParsedResource* out_resource);
bool ParseAttr(xml::XmlPullParser* parser, ParsedResource* out_resource);
- bool ParseAttrImpl(xml::XmlPullParser* parser, ParsedResource* out_resource,
- bool weak);
+ bool ParseAttrImpl(xml::XmlPullParser* parser, ParsedResource* out_resource, bool weak);
Maybe<Attribute::Symbol> ParseEnumOrFlagItem(xml::XmlPullParser* parser,
const android::StringPiece& tag);
bool ParseStyle(const ResourceType type, xml::XmlPullParser* parser,
ParsedResource* out_resource);
bool ParseStyleItem(xml::XmlPullParser* parser, Style* style);
- bool ParseDeclareStyleable(xml::XmlPullParser* parser,
- ParsedResource* out_resource);
+ bool ParseDeclareStyleable(xml::XmlPullParser* parser, ParsedResource* out_resource);
bool ParseArray(xml::XmlPullParser* parser, ParsedResource* out_resource);
- bool ParseIntegerArray(xml::XmlPullParser* parser,
- ParsedResource* out_resource);
- bool ParseStringArray(xml::XmlPullParser* parser,
- ParsedResource* out_resource);
- bool ParseArrayImpl(xml::XmlPullParser* parser, ParsedResource* out_resource,
- uint32_t typeMask);
+ bool ParseIntegerArray(xml::XmlPullParser* parser, ParsedResource* out_resource);
+ bool ParseStringArray(xml::XmlPullParser* parser, ParsedResource* out_resource);
+ bool ParseArrayImpl(xml::XmlPullParser* parser, ParsedResource* out_resource, uint32_t typeMask);
bool ParsePlural(xml::XmlPullParser* parser, ParsedResource* out_resource);
IDiagnostics* diag_;
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index e60ef66..5352ca8 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -25,19 +25,20 @@
#include "test/Test.h"
#include "xml/XmlPullParser.h"
+using ::aapt::test::ValueEq;
using ::android::StringPiece;
using ::testing::Eq;
using ::testing::NotNull;
+using ::testing::Pointee;
namespace aapt {
-constexpr const char* kXmlPreamble =
- "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+constexpr const char* kXmlPreamble = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
TEST(ResourceParserSingleTest, FailToParseWithNoRootResourcesElement) {
std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
std::stringstream input(kXmlPreamble);
- input << "<attr name=\"foo\"/>" << std::endl;
+ input << R"(<attr name="foo"/>)" << std::endl;
ResourceTable table;
ResourceParser parser(context->GetDiagnostics(), &table, Source{"test"}, {});
xml::XmlPullParser xml_parser(input);
@@ -46,19 +47,20 @@
class ResourceParserTest : public ::testing::Test {
public:
- void SetUp() override { context_ = test::ContextBuilder().Build(); }
+ void SetUp() override {
+ context_ = test::ContextBuilder().Build();
+ }
::testing::AssertionResult TestParse(const StringPiece& str) {
return TestParse(str, ConfigDescription{});
}
- ::testing::AssertionResult TestParse(const StringPiece& str,
- const ConfigDescription& config) {
+ ::testing::AssertionResult TestParse(const StringPiece& str, const ConfigDescription& config) {
std::stringstream input(kXmlPreamble);
input << "<resources>\n" << str << "\n</resources>" << std::endl;
ResourceParserOptions parserOptions;
- ResourceParser parser(context_->GetDiagnostics(), &table_, Source{"test"},
- config, parserOptions);
+ ResourceParser parser(context_->GetDiagnostics(), &table_, Source{"test"}, config,
+ parserOptions);
xml::XmlPullParser xmlParser(input);
if (parser.Parse(&xmlParser)) {
return ::testing::AssertionSuccess();
@@ -205,18 +207,18 @@
// a non-existing value, and this causes problems in styles when trying to
// resolve an attribute. Null values must be encoded as android::Res_value::TYPE_REFERENCE
// with a data value of 0.
- BinaryPrimitive* integer = test::GetValue<BinaryPrimitive>(&table_, "integer/foo");
- ASSERT_NE(nullptr, integer);
- EXPECT_EQ(uint16_t(android::Res_value::TYPE_REFERENCE), integer->value.dataType);
- EXPECT_EQ(0u, integer->value.data);
+ Reference* null_ref = test::GetValue<Reference>(&table_, "integer/foo");
+ ASSERT_THAT(null_ref, NotNull());
+ EXPECT_FALSE(null_ref->name);
+ EXPECT_FALSE(null_ref->id);
+ EXPECT_EQ(Reference::Type::kResource, null_ref->reference_type);
}
TEST_F(ResourceParserTest, ParseEmpty) {
std::string input = "<integer name=\"foo\">@empty</integer>";
ASSERT_TRUE(TestParse(input));
- BinaryPrimitive* integer =
- test::GetValue<BinaryPrimitive>(&table_, "integer/foo");
+ BinaryPrimitive* integer = test::GetValue<BinaryPrimitive>(&table_, "integer/foo");
ASSERT_NE(nullptr, integer);
EXPECT_EQ(uint16_t(android::Res_value::TYPE_NULL), integer->value.dataType);
EXPECT_EQ(uint32_t(android::Res_value::DATA_NULL_EMPTY), integer->value.data);
@@ -241,22 +243,18 @@
// ultimately
// stored them with the default configuration. Check that we have the same
// behavior.
-TEST_F(ResourceParserTest,
- ParseAttrAndDeclareStyleableUnderConfigButRecordAsNoConfig) {
+TEST_F(ResourceParserTest, ParseAttrAndDeclareStyleableUnderConfigButRecordAsNoConfig) {
const ConfigDescription watch_config = test::ParseConfigOrDie("watch");
- std::string input = R"EOF(
- <attr name="foo" />
- <declare-styleable name="bar">
- <attr name="baz" />
- </declare-styleable>)EOF";
+ std::string input = R"(
+ <attr name="foo" />
+ <declare-styleable name="bar">
+ <attr name="baz" />
+ </declare-styleable>)";
ASSERT_TRUE(TestParse(input, watch_config));
- EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/foo",
- watch_config));
- EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/baz",
- watch_config));
- EXPECT_EQ(nullptr, test::GetValueForConfig<Styleable>(
- &table_, "styleable/bar", watch_config));
+ EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/foo", watch_config));
+ EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/baz", watch_config));
+ EXPECT_EQ(nullptr, test::GetValueForConfig<Styleable>(&table_, "styleable/bar", watch_config));
EXPECT_NE(nullptr, test::GetValue<Attribute>(&table_, "attr/foo"));
EXPECT_NE(nullptr, test::GetValue<Attribute>(&table_, "attr/baz"));
@@ -833,4 +831,16 @@
EXPECT_NE(nullptr, ValueCast<RawString>(val->entries[0].value.get()));
}
+TEST_F(ResourceParserTest, ParseElementWithNoValue) {
+ std::string input = R"(
+ <item type="drawable" format="reference" name="foo" />
+ <string name="foo" />)";
+ ASSERT_TRUE(TestParse(input));
+ ASSERT_THAT(test::GetValue(&table_, "drawable/foo"), Pointee(ValueEq(Reference())));
+
+ String* str = test::GetValue<String>(&table_, "string/foo");
+ ASSERT_THAT(str, NotNull());
+ EXPECT_THAT(*str->value, Eq(""));
+}
+
} // namespace aapt
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 818c8ce..deeef6e 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -305,21 +305,25 @@
return {};
}
-std::unique_ptr<BinaryPrimitive> TryParseNullOrEmpty(const StringPiece& str) {
- StringPiece trimmed_str(util::TrimWhitespace(str));
- android::Res_value value = {};
+std::unique_ptr<Item> TryParseNullOrEmpty(const StringPiece& str) {
+ const StringPiece trimmed_str(util::TrimWhitespace(str));
if (trimmed_str == "@null") {
- // TYPE_NULL with data set to 0 is interpreted by the runtime as an error.
- // Instead we set the data type to TYPE_REFERENCE with a value of 0.
- value.dataType = android::Res_value::TYPE_REFERENCE;
+ return MakeNull();
} else if (trimmed_str == "@empty") {
- // TYPE_NULL with value of DATA_NULL_EMPTY is handled fine by the runtime.
- value.dataType = android::Res_value::TYPE_NULL;
- value.data = android::Res_value::DATA_NULL_EMPTY;
- } else {
- return {};
+ return MakeEmpty();
}
- return util::make_unique<BinaryPrimitive>(value);
+ return {};
+}
+
+std::unique_ptr<Reference> MakeNull() {
+ // TYPE_NULL with data set to 0 is interpreted by the runtime as an error.
+ // Instead we set the data type to TYPE_REFERENCE with a value of 0.
+ return util::make_unique<Reference>();
+}
+
+std::unique_ptr<BinaryPrimitive> MakeEmpty() {
+ return util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_NULL,
+ android::Res_value::DATA_NULL_EMPTY);
}
std::unique_ptr<BinaryPrimitive> TryParseEnumSymbol(const Attribute* enum_attr,
@@ -569,13 +573,15 @@
std::unique_ptr<Item> TryParseItemForAttribute(
const StringPiece& value, uint32_t type_mask,
const std::function<void(const ResourceName&)>& on_create_reference) {
- std::unique_ptr<BinaryPrimitive> null_or_empty = TryParseNullOrEmpty(value);
+ using android::ResTable_map;
+
+ auto null_or_empty = TryParseNullOrEmpty(value);
if (null_or_empty) {
- return std::move(null_or_empty);
+ return null_or_empty;
}
bool create = false;
- std::unique_ptr<Reference> reference = TryParseReference(value, &create);
+ auto reference = TryParseReference(value, &create);
if (reference) {
if (create && on_create_reference) {
on_create_reference(reference->name.value());
@@ -583,39 +589,37 @@
return std::move(reference);
}
- if (type_mask & android::ResTable_map::TYPE_COLOR) {
+ if (type_mask & ResTable_map::TYPE_COLOR) {
// Try parsing this as a color.
- std::unique_ptr<BinaryPrimitive> color = TryParseColor(value);
+ auto color = TryParseColor(value);
if (color) {
return std::move(color);
}
}
- if (type_mask & android::ResTable_map::TYPE_BOOLEAN) {
+ if (type_mask & ResTable_map::TYPE_BOOLEAN) {
// Try parsing this as a boolean.
- std::unique_ptr<BinaryPrimitive> boolean = TryParseBool(value);
+ auto boolean = TryParseBool(value);
if (boolean) {
return std::move(boolean);
}
}
- if (type_mask & android::ResTable_map::TYPE_INTEGER) {
+ if (type_mask & ResTable_map::TYPE_INTEGER) {
// Try parsing this as an integer.
- std::unique_ptr<BinaryPrimitive> integer = TryParseInt(value);
+ auto integer = TryParseInt(value);
if (integer) {
return std::move(integer);
}
}
- const uint32_t float_mask = android::ResTable_map::TYPE_FLOAT |
- android::ResTable_map::TYPE_DIMENSION |
- android::ResTable_map::TYPE_FRACTION;
+ const uint32_t float_mask =
+ ResTable_map::TYPE_FLOAT | ResTable_map::TYPE_DIMENSION | ResTable_map::TYPE_FRACTION;
if (type_mask & float_mask) {
// Try parsing this as a float.
- std::unique_ptr<BinaryPrimitive> floating_point = TryParseFloat(value);
+ auto floating_point = TryParseFloat(value);
if (floating_point) {
- if (type_mask &
- AndroidTypeToAttributeTypeMask(floating_point->value.dataType)) {
+ if (type_mask & AndroidTypeToAttributeTypeMask(floating_point->value.dataType)) {
return std::move(floating_point);
}
}
@@ -630,24 +634,25 @@
std::unique_ptr<Item> TryParseItemForAttribute(
const StringPiece& str, const Attribute* attr,
const std::function<void(const ResourceName&)>& on_create_reference) {
+ using android::ResTable_map;
+
const uint32_t type_mask = attr->type_mask;
- std::unique_ptr<Item> value =
- TryParseItemForAttribute(str, type_mask, on_create_reference);
+ auto value = TryParseItemForAttribute(str, type_mask, on_create_reference);
if (value) {
return value;
}
- if (type_mask & android::ResTable_map::TYPE_ENUM) {
+ if (type_mask & ResTable_map::TYPE_ENUM) {
// Try parsing this as an enum.
- std::unique_ptr<BinaryPrimitive> enum_value = TryParseEnumSymbol(attr, str);
+ auto enum_value = TryParseEnumSymbol(attr, str);
if (enum_value) {
return std::move(enum_value);
}
}
- if (type_mask & android::ResTable_map::TYPE_FLAGS) {
+ if (type_mask & ResTable_map::TYPE_FLAGS) {
// Try parsing this as a flag.
- std::unique_ptr<BinaryPrimitive> flag_value = TryParseFlagSymbol(attr, str);
+ auto flag_value = TryParseFlagSymbol(attr, str);
if (flag_value) {
return std::move(flag_value);
}
@@ -655,8 +660,7 @@
return {};
}
-std::string BuildResourceFileName(const ResourceFile& res_file,
- const NameMangler* mangler) {
+std::string BuildResourceFileName(const ResourceFile& res_file, const NameMangler* mangler) {
std::stringstream out;
out << "res/" << res_file.name.type;
if (res_file.config != ConfigDescription{}) {
@@ -719,9 +723,9 @@
ref_type = Reference::Type::kAttribute;
}
- if (data == 0) {
+ if (data == 0u) {
// A reference of 0, must be the magic @null reference.
- return util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_REFERENCE, 0u);
+ return util::make_unique<Reference>();
}
// This is a normal reference.
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index da0fc8e..36f6c2b 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -133,7 +133,16 @@
* Returns a BinaryPrimitve object representing @null or @empty if the string
* was parsed as one.
*/
-std::unique_ptr<BinaryPrimitive> TryParseNullOrEmpty(const android::StringPiece& str);
+std::unique_ptr<Item> TryParseNullOrEmpty(const android::StringPiece& str);
+
+// Returns a Reference representing @null.
+// Due to runtime compatibility issues, this is encoded as a reference with ID 0.
+// The runtime will convert this to TYPE_NULL.
+std::unique_ptr<Reference> MakeNull();
+
+// Returns a BinaryPrimitive representing @empty. This is encoded as a Res_value with
+// type Res_value::TYPE_NULL and data Res_value::DATA_NULL_EMPTY.
+std::unique_ptr<BinaryPrimitive> MakeEmpty();
/*
* Returns a BinaryPrimitve object representing a color if the string was parsed
diff --git a/tools/aapt2/ResourceUtils_test.cpp b/tools/aapt2/ResourceUtils_test.cpp
index 048c692..cdc34f1 100644
--- a/tools/aapt2/ResourceUtils_test.cpp
+++ b/tools/aapt2/ResourceUtils_test.cpp
@@ -19,6 +19,9 @@
#include "Resource.h"
#include "test/Test.h"
+using ::aapt::test::ValueEq;
+using ::testing::Pointee;
+
namespace aapt {
TEST(ResourceUtilsTest, ParseBool) {
@@ -200,4 +203,22 @@
EXPECT_EQ(0u, result->value.data);
}
+TEST(ResourceUtilsTest, NullIsEmptyReference) {
+ auto null_value = ResourceUtils::MakeNull();
+ ASSERT_THAT(null_value, Pointee(ValueEq(Reference())));
+
+ auto value = ResourceUtils::TryParseNullOrEmpty("@null");
+ ASSERT_THAT(value, Pointee(ValueEq(Reference())));
+}
+
+TEST(ResourceUtilsTest, EmptyIsBinaryPrimitive) {
+ auto empty_value = ResourceUtils::MakeEmpty();
+ ASSERT_THAT(empty_value, Pointee(ValueEq(BinaryPrimitive(android::Res_value::TYPE_NULL,
+ android::Res_value::DATA_NULL_EMPTY))));
+
+ auto value = ResourceUtils::TryParseNullOrEmpty("@empty");
+ ASSERT_THAT(value, Pointee(ValueEq(BinaryPrimitive(android::Res_value::TYPE_NULL,
+ android::Res_value::DATA_NULL_EMPTY))));
+}
+
} // namespace aapt
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index abfdec4..e808984 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -94,8 +94,8 @@
bool Reference::Flatten(android::Res_value* out_value) const {
const ResourceId resid = id.value_or_default(ResourceId(0));
- const bool dynamic =
- (resid.package_id() != kFrameworkPackageId && resid.package_id() != kAppPackageId);
+ const bool dynamic = resid.is_valid_dynamic() && resid.package_id() != kFrameworkPackageId &&
+ resid.package_id() != kAppPackageId;
if (reference_type == Reference::Type::kResource) {
if (dynamic) {
@@ -119,22 +119,29 @@
}
void Reference::Print(std::ostream* out) const {
- *out << "(reference) ";
- if (reference_type == Reference::Type::kResource) {
- *out << "@";
- if (private_reference) {
- *out << "*";
+ if (reference_type == Type::kResource) {
+ *out << "(reference) @";
+ if (!name && !id) {
+ *out << "null";
+ return;
}
} else {
- *out << "?";
+ *out << "(attr-reference) ?";
+ }
+
+ if (private_reference) {
+ *out << "*";
}
if (name) {
*out << name.value();
}
- if (id && !Res_INTERNALID(id.value().id)) {
- *out << " " << id.value();
+ if (id && id.value().is_valid_dynamic()) {
+ if (name) {
+ *out << " ";
+ }
+ *out << id.value();
}
}
@@ -314,7 +321,11 @@
void BinaryPrimitive::Print(std::ostream* out) const {
switch (value.dataType) {
case android::Res_value::TYPE_NULL:
- *out << "(null)";
+ if (value.data == android::Res_value::DATA_NULL_EMPTY) {
+ *out << "(empty)";
+ } else {
+ *out << "(null)";
+ }
break;
case android::Res_value::TYPE_INT_DEC:
*out << "(integer) " << static_cast<int32_t>(value.data);
diff --git a/tools/aapt2/ResourceValues_test.cpp b/tools/aapt2/ResourceValues_test.cpp
index e154d93..69f8e67 100644
--- a/tools/aapt2/ResourceValues_test.cpp
+++ b/tools/aapt2/ResourceValues_test.cpp
@@ -180,4 +180,14 @@
EXPECT_TRUE(a->Equals(expected.get()));
}
+// TYPE_NULL is encoded as TYPE_REFERENCE with a value of 0. This is represented in AAPT2
+// by a default constructed Reference value.
+TEST(ResourcesValuesTest, EmptyReferenceFlattens) {
+ android::Res_value value = {};
+ ASSERT_TRUE(Reference().Flatten(&value));
+
+ EXPECT_EQ(android::Res_value::TYPE_REFERENCE, value.dataType);
+ EXPECT_EQ(0x0u, value.data);
+}
+
} // namespace aapt
diff --git a/tools/aapt2/integration-tests/AppOne/res/values/test.xml b/tools/aapt2/integration-tests/AppOne/res/values/test.xml
index 5104f82..2c9e8b8 100644
--- a/tools/aapt2/integration-tests/AppOne/res/values/test.xml
+++ b/tools/aapt2/integration-tests/AppOne/res/values/test.xml
@@ -38,4 +38,7 @@
<attr name="android:text" />
<attr name="layout_width" />
</declare-styleable>
+
+ <!-- Declare an empty, resource -->
+ <item type="drawable" name="undefined" />
</resources>
diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp
index 18498e3..a8e510c 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -296,7 +296,10 @@
IAaptContext* context, SymbolTable* symbols,
xml::IPackageDeclStack* decls) {
CHECK(reference != nullptr);
- CHECK(reference->name || reference->id);
+ if (!reference->name && !reference->id) {
+ // This is @null.
+ return true;
+ }
Reference transformed_reference = *reference;
TransformReferenceFromNamespace(decls, context->GetCompilationPackage(), &transformed_reference);
diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp
index 1d0041b..4b56192 100644
--- a/tools/aapt2/proto/TableProtoDeserializer.cpp
+++ b/tools/aapt2/proto/TableProtoDeserializer.cpp
@@ -343,26 +343,19 @@
return value;
}
- bool DeserializeReferenceFromPb(const pb::Reference& pb_ref,
- Reference* out_ref) {
+ bool DeserializeReferenceFromPb(const pb::Reference& pb_ref, Reference* out_ref) {
out_ref->reference_type = DeserializeReferenceTypeFromPb(pb_ref.type());
out_ref->private_reference = pb_ref.private_();
- if (!pb_ref.has_id() && !pb_ref.has_symbol_idx()) {
- return false;
- }
-
if (pb_ref.has_id()) {
out_ref->id = ResourceId(pb_ref.id());
}
if (pb_ref.has_symbol_idx()) {
- const std::string str_symbol =
- util::GetString(*symbol_pool_, pb_ref.symbol_idx());
+ const std::string str_symbol = util::GetString(*symbol_pool_, pb_ref.symbol_idx());
ResourceNameRef name_ref;
if (!ResourceUtils::ParseResourceName(str_symbol, &name_ref, nullptr)) {
- diag_->Error(DiagMessage(source_) << "invalid reference name '"
- << str_symbol << "'");
+ diag_->Error(DiagMessage(source_) << "invalid reference name '" << str_symbol << "'");
return false;
}
diff --git a/tools/aapt2/proto/TableProtoSerializer.cpp b/tools/aapt2/proto/TableProtoSerializer.cpp
index de10bb8..d87d64e 100644
--- a/tools/aapt2/proto/TableProtoSerializer.cpp
+++ b/tools/aapt2/proto/TableProtoSerializer.cpp
@@ -190,8 +190,7 @@
}
if (ref.name) {
- StringPool::Ref symbol_ref =
- symbol_pool_->MakeRef(ref.name.value().ToString());
+ StringPool::Ref symbol_ref = symbol_pool_->MakeRef(ref.name.value().ToString());
pb_ref->set_symbol_idx(static_cast<uint32_t>(symbol_ref.index()));
}
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index 02acedb..f3da780 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -59,8 +59,7 @@
ResourceTableBuilder& AddReference(const android::StringPiece& name, const ResourceId& id,
const android::StringPiece& ref) {
- return AddValue(name, id,
- util::make_unique<Reference>(ParseNameOrDie(ref)));
+ return AddValue(name, id, util::make_unique<Reference>(ParseNameOrDie(ref)));
}
ResourceTableBuilder& AddString(const android::StringPiece& name,
@@ -111,8 +110,8 @@
ResourceTableBuilder& AddValue(const android::StringPiece& name, const ConfigDescription& config,
const ResourceId& id, std::unique_ptr<Value> value) {
ResourceName res_name = ParseNameOrDie(name);
- CHECK(table_->AddResourceAllowMangled(res_name, id, config, {},
- std::move(value), &diagnostics_));
+ CHECK(table_->AddResourceAllowMangled(res_name, id, config, {}, std::move(value),
+ GetDiagnostics()));
return *this;
}
@@ -122,7 +121,7 @@
Symbol symbol;
symbol.state = state;
symbol.allow_new = allow_new;
- CHECK(table_->SetSymbolStateAllowMangled(res_name, id, symbol, &diagnostics_));
+ CHECK(table_->SetSymbolStateAllowMangled(res_name, id, symbol, GetDiagnostics()));
return *this;
}
@@ -131,7 +130,6 @@
private:
DISALLOW_COPY_AND_ASSIGN(ResourceTableBuilder);
- DummyDiagnosticsImpl diagnostics_;
std::unique_ptr<ResourceTable> table_ = util::make_unique<ResourceTable>();
};
diff --git a/tools/aapt2/test/Common.cpp b/tools/aapt2/test/Common.cpp
new file mode 100644
index 0000000..0fabbc4
--- /dev/null
+++ b/tools/aapt2/test/Common.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test/Common.h"
+
+namespace aapt {
+namespace test {
+
+struct DummyDiagnosticsImpl : public IDiagnostics {
+ void Log(Level level, DiagMessageActual& actual_msg) override {
+ switch (level) {
+ case Level::Note:
+ return;
+
+ case Level::Warn:
+ std::cerr << actual_msg.source << ": warn: " << actual_msg.message << "." << std::endl;
+ break;
+
+ case Level::Error:
+ std::cerr << actual_msg.source << ": error: " << actual_msg.message << "." << std::endl;
+ break;
+ }
+ }
+};
+
+IDiagnostics* GetDiagnostics() {
+ static DummyDiagnosticsImpl diag;
+ return &diag;
+}
+
+template <>
+Value* GetValueForConfigAndProduct<Value>(ResourceTable* table,
+ const android::StringPiece& res_name,
+ const ConfigDescription& config,
+ const android::StringPiece& product) {
+ Maybe<ResourceTable::SearchResult> result = table->FindResource(ParseNameOrDie(res_name));
+ if (result) {
+ ResourceConfigValue* config_value = result.value().entry->FindValue(config, product);
+ if (config_value) {
+ return config_value->value.get();
+ }
+ }
+ return nullptr;
+}
+
+} // namespace test
+} // namespace aapt
diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h
index a937de8..0585148 100644
--- a/tools/aapt2/test/Common.h
+++ b/tools/aapt2/test/Common.h
@@ -46,27 +46,7 @@
namespace aapt {
namespace test {
-struct DummyDiagnosticsImpl : public IDiagnostics {
- void Log(Level level, DiagMessageActual& actual_msg) override {
- switch (level) {
- case Level::Note:
- return;
-
- case Level::Warn:
- std::cerr << actual_msg.source << ": warn: " << actual_msg.message << "." << std::endl;
- break;
-
- case Level::Error:
- std::cerr << actual_msg.source << ": error: " << actual_msg.message << "." << std::endl;
- break;
- }
- }
-};
-
-inline IDiagnostics* GetDiagnostics() {
- static DummyDiagnosticsImpl diag;
- return &diag;
-}
+IDiagnostics* GetDiagnostics();
inline ResourceName ParseNameOrDie(const android::StringPiece& str) {
ResourceNameRef ref;
@@ -80,7 +60,7 @@
return config;
}
-template <typename T>
+template <typename T = Value>
T* GetValueForConfigAndProduct(ResourceTable* table, const android::StringPiece& res_name,
const ConfigDescription& config,
const android::StringPiece& product) {
@@ -94,13 +74,19 @@
return nullptr;
}
-template <typename T>
+template <>
+Value* GetValueForConfigAndProduct<Value>(ResourceTable* table,
+ const android::StringPiece& res_name,
+ const ConfigDescription& config,
+ const android::StringPiece& product);
+
+template <typename T = Value>
T* GetValueForConfig(ResourceTable* table, const android::StringPiece& res_name,
const ConfigDescription& config) {
return GetValueForConfigAndProduct<T>(table, res_name, config, {});
}
-template <typename T>
+template <typename T = Value>
T* GetValue(ResourceTable* table, const android::StringPiece& res_name) {
return GetValueForConfig<T>(table, res_name, {});
}
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index b133a44..a4b3bf2a 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -1,7 +1,10 @@
package android.net.wifi;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
@@ -20,6 +23,7 @@
/** @hide */
@SystemApi
+@SystemService(Context.WIFI_RTT_SERVICE)
public class RttManager {
private static final boolean DBG = false;
@@ -167,6 +171,7 @@
/** @deprecated Use the new {@link android.net.wifi.RttManager#getRttCapabilities()} API.*/
@Deprecated
+ @SuppressLint("Doclava125")
public Capabilities getCapabilities() {
return new Capabilities();
}
@@ -990,7 +995,7 @@
* @exception throw IllegalArgumentException when params are illegal
* throw IllegalStateException when RttCapabilities do not exist
*/
-
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void startRanging(RttParams[] params, RttListener listener) {
int index = 0;
for(RttParams rttParam : params) {
@@ -1006,6 +1011,7 @@
0, putListener(listener), parcelableParams);
}
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void stopRanging(RttListener listener) {
validateChannel();
mAsyncChannel.sendMessage(CMD_OP_STOP_RANGING, 0, removeListener(listener));
@@ -1039,6 +1045,7 @@
* @param callback Callback for responder enabling/disabling result.
* @throws IllegalArgumentException If {@code callback} is null.
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void enableResponder(ResponderCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
@@ -1058,6 +1065,7 @@
* @param callback The same callback used for enabling responder.
* @throws IllegalArgumentException If {@code callback} is null.
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void disableResponder(ResponderCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index f7333e2..91fc2f7 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -67,6 +67,8 @@
public static final String updateIdentiferVarName = "update_identifier";
/** {@hide} */
public static final int INVALID_NETWORK_ID = -1;
+ /** {@hide} */
+ public static final int LOCAL_ONLY_NETWORK_ID = -2;
/** {@hide} */
private String mPasspointManagementObjectTree;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 58df4ee..c89a9a4 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -17,9 +17,12 @@
package android.net.wifi;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.net.ConnectivityManager;
@@ -56,27 +59,30 @@
/**
* This class provides the primary API for managing all aspects of Wi-Fi
- * connectivity. Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.WIFI_SERVICE)}.
- * On releases before NYC, it should only be obtained from an application context, and not from
- * any other derived context to avoid memory leaks within the calling process.
-
+ * connectivity.
+ * <p>
+ * On releases before {@link android.os.Build.VERSION_CODES#N}, this object
+ * should only be obtained from an {@linkplain Context#getApplicationContext()
+ * application context}, and not from any other derived context to avoid memory
+ * leaks within the calling process.
+ * <p>
* It deals with several categories of items:
* <ul>
- * <li>The list of configured networks. The list can be viewed and updated,
- * and attributes of individual entries can be modified.</li>
+ * <li>The list of configured networks. The list can be viewed and updated, and
+ * attributes of individual entries can be modified.</li>
* <li>The currently active Wi-Fi network, if any. Connectivity can be
- * established or torn down, and dynamic information about the state of
- * the network can be queried.</li>
- * <li>Results of access point scans, containing enough information to
- * make decisions about what access point to connect to.</li>
- * <li>It defines the names of various Intent actions that are broadcast
- * upon any sort of change in Wi-Fi state.
+ * established or torn down, and dynamic information about the state of the
+ * network can be queried.</li>
+ * <li>Results of access point scans, containing enough information to make
+ * decisions about what access point to connect to.</li>
+ * <li>It defines the names of various Intent actions that are broadcast upon
+ * any sort of change in Wi-Fi state.
* </ul>
- * This is the API to use when performing Wi-Fi specific operations. To
- * perform operations that pertain to network connectivity at an abstract
- * level, use {@link android.net.ConnectivityManager}.
+ * This is the API to use when performing Wi-Fi specific operations. To perform
+ * operations that pertain to network connectivity at an abstract level, use
+ * {@link android.net.ConnectivityManager}.
*/
+@SystemService(Context.WIFI_SERVICE)
public class WifiManager {
private static final String TAG = "WifiManager";
@@ -966,6 +972,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL)
public List<WifiConfiguration> getPrivilegedConfiguredNetworks() {
try {
ParceledListSlice<WifiConfiguration> parceledList =
@@ -981,6 +988,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL)
public WifiConnectionStatistics getConnectionStatistics() {
try {
return mService.getConnectionStatistics();
@@ -1522,6 +1530,7 @@
/** @hide */
@SystemApi
+ @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
public boolean startScan(WorkSource workSource) {
try {
String packageName = mContext.getOpPackageName();
@@ -1542,6 +1551,7 @@
*/
@Deprecated
@SystemApi
+ @SuppressLint("Doclava125")
public boolean startLocationRestrictedScan(WorkSource workSource) {
return false;
}
@@ -1556,6 +1566,7 @@
*/
@Deprecated
@SystemApi
+ @SuppressLint("Doclava125")
public boolean isBatchedScanSupported() {
return false;
}
@@ -1569,6 +1580,7 @@
*/
@Deprecated
@SystemApi
+ @SuppressLint("Doclava125")
public List<BatchedScanResult> getBatchedScanResults() {
return null;
}
@@ -1808,6 +1820,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
String packageName = mContext.getOpPackageName();
@@ -2053,6 +2066,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
public int getWifiApState() {
try {
return mService.getWifiApEnabledState();
@@ -2069,6 +2083,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
public boolean isWifiApEnabled() {
return getWifiApState() == WIFI_AP_STATE_ENABLED;
}
@@ -2080,6 +2095,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
public WifiConfiguration getWifiApConfiguration() {
try {
return mService.getWifiApConfiguration();
@@ -2095,6 +2111,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
try {
mService.setWifiApConfiguration(wifiConfig);
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index c02ceef..f47d5ca 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -16,7 +16,10 @@
package android.net.wifi;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
@@ -40,12 +43,10 @@
/**
* This class provides a way to scan the Wifi universe around the device
- * Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context
- * .WIFI_SCANNING_SERVICE)}.
* @hide
*/
@SystemApi
+@SystemService(Context.WIFI_SCANNING_SERVICE)
public class WifiScanner {
/** no band specified; use channel list instead */
@@ -732,6 +733,7 @@
* key for this scan, and must also be specified to cancel the scan. Multiple
* scans should also not share this object.
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void startBackgroundScan(ScanSettings settings, ScanListener listener) {
startBackgroundScan(settings, listener, null);
}
@@ -744,6 +746,7 @@
* key for this scan, and must also be specified to cancel the scan. Multiple
* scans should also not share this object.
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void startBackgroundScan(ScanSettings settings, ScanListener listener,
WorkSource workSource) {
Preconditions.checkNotNull(listener, "listener cannot be null");
@@ -761,6 +764,7 @@
* @param listener specifies which scan to cancel; must be same object as passed in {@link
* #startBackgroundScan}
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void stopBackgroundScan(ScanListener listener) {
Preconditions.checkNotNull(listener, "listener cannot be null");
int key = removeListener(listener);
@@ -772,6 +776,7 @@
* reports currently available scan results on appropriate listeners
* @return true if all scan results were reported correctly
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public boolean getScanResults() {
validateChannel();
Message reply = mAsyncChannel.sendMessageSynchronously(CMD_GET_SCAN_RESULTS, 0);
@@ -786,6 +791,7 @@
* key for this scan, and must also be specified to cancel the scan. Multiple
* scans should also not share this object.
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void startScan(ScanSettings settings, ScanListener listener) {
startScan(settings, listener, null);
}
@@ -799,6 +805,7 @@
* key for this scan, and must also be specified to cancel the scan. Multiple
* scans should also not share this object.
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void startScan(ScanSettings settings, ScanListener listener, WorkSource workSource) {
Preconditions.checkNotNull(listener, "listener cannot be null");
int key = addListener(listener);
@@ -815,6 +822,7 @@
* hasn't been called on the listener, ignored otherwise
* @param listener
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void stopScan(ScanListener listener) {
Preconditions.checkNotNull(listener, "listener cannot be null");
int key = removeListener(listener);
@@ -962,6 +970,7 @@
* @param bssidInfos access points to watch
*/
@Deprecated
+ @SuppressLint("Doclava125")
public void configureWifiChange(
int rssiSampleSize, /* sample size for RSSI averaging */
int lostApSampleSize, /* samples to confirm AP's loss */
@@ -995,6 +1004,7 @@
* provided on {@link #stopTrackingWifiChange}
*/
@Deprecated
+ @SuppressLint("Doclava125")
public void startTrackingWifiChange(WifiChangeListener listener) {
throw new UnsupportedOperationException();
}
@@ -1005,6 +1015,7 @@
* #stopTrackingWifiChange}
*/
@Deprecated
+ @SuppressLint("Doclava125")
public void stopTrackingWifiChange(WifiChangeListener listener) {
throw new UnsupportedOperationException();
}
@@ -1012,6 +1023,7 @@
/** @hide */
@SystemApi
@Deprecated
+ @SuppressLint("Doclava125")
public void configureWifiChange(WifiChangeSettings settings) {
throw new UnsupportedOperationException();
}
@@ -1067,6 +1079,7 @@
* also be provided on {@link #stopTrackingBssids}
*/
@Deprecated
+ @SuppressLint("Doclava125")
public void startTrackingBssids(BssidInfo[] bssidInfos,
int apLostThreshold, BssidListener listener) {
throw new UnsupportedOperationException();
@@ -1077,6 +1090,7 @@
* @param listener same object provided in {@link #startTrackingBssids}
*/
@Deprecated
+ @SuppressLint("Doclava125")
public void stopTrackingBssids(BssidListener listener) {
throw new UnsupportedOperationException();
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index d3ed792..c22daaf 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
+import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.net.ConnectivityManager;
@@ -48,9 +49,7 @@
/**
* This class provides the primary API for managing Wi-Fi Aware operations:
- * discovery and peer-to-peer data connections. Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String)
- * Context.getSystemService(Context.WIFI_AWARE_SERVICE)}.
+ * discovery and peer-to-peer data connections.
* <p>
* The class provides access to:
* <ul>
@@ -120,6 +119,7 @@
* {@link DiscoverySession#createNetworkSpecifierPassphrase(PeerHandle, String)}.
* </ul>
*/
+@SystemService(Context.WIFI_AWARE_SERVICE)
public class WifiAwareManager {
private static final String TAG = "WifiAwareManager";
private static final boolean DBG = false;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index c93ac7b..95d0a79 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -17,6 +17,7 @@
package android.net.wifi.p2p;
import android.annotation.SdkConstant;
+import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.net.wifi.WpsInfo;
@@ -119,9 +120,6 @@
* {@link android.Manifest.permission#CHANGE_WIFI_STATE} to perform any further peer-to-peer
* operations.
*
- * Get an instance of this class by calling {@link android.content.Context#getSystemService(String)
- * Context.getSystemService(Context.WIFI_P2P_SERVICE)}.
- *
* {@see WifiP2pConfig}
* {@see WifiP2pInfo}
* {@see WifiP2pGroup}
@@ -129,6 +127,7 @@
* {@see WifiP2pDeviceList}
* {@see android.net.wifi.WpsInfo}
*/
+@SystemService(Context.WIFI_P2P_SERVICE)
public class WifiP2pManager {
private static final String TAG = "WifiP2pManager";
/**