Merge "Add Missed call People Tile" into sc-dev
diff --git a/apex/appsearch/Android.bp b/apex/appsearch/Android.bp
index b014fdc..ab44dd9 100644
--- a/apex/appsearch/Android.bp
+++ b/apex/appsearch/Android.bp
@@ -21,6 +21,7 @@
],
key: "com.android.appsearch.key",
certificate: ":com.android.appsearch.certificate",
+ updatable: false,
}
apex_key {
diff --git a/core/api/current.txt b/core/api/current.txt
index db5d143..5b639ff 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -4735,6 +4735,13 @@
field @NonNull public static final android.os.Parcelable.Creator<android.app.AutomaticZenRule> CREATOR;
}
+ public final class BackgroundServiceStartNotAllowedException extends android.app.ServiceStartNotAllowedException implements android.os.Parcelable {
+ ctor public BackgroundServiceStartNotAllowedException(@NonNull String);
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.BackgroundServiceStartNotAllowedException> CREATOR;
+ }
+
public class DatePickerDialog extends android.app.AlertDialog implements android.widget.DatePicker.OnDateChangedListener android.content.DialogInterface.OnClickListener {
ctor public DatePickerDialog(@NonNull android.content.Context);
ctor public DatePickerDialog(@NonNull android.content.Context, @StyleRes int);
@@ -4980,6 +4987,13 @@
method @Deprecated public void setSelectedGroup(int);
}
+ public final class ForegroundServiceStartNotAllowedException extends android.app.ServiceStartNotAllowedException implements android.os.Parcelable {
+ ctor public ForegroundServiceStartNotAllowedException(@NonNull String);
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.ForegroundServiceStartNotAllowedException> CREATOR;
+ }
+
@Deprecated public class Fragment implements android.content.ComponentCallbacks2 android.view.View.OnCreateContextMenuListener {
ctor @Deprecated public Fragment();
method @Deprecated public void dump(String, java.io.FileDescriptor, java.io.PrintWriter, String[]);
@@ -6563,6 +6577,9 @@
field public static final int STOP_FOREGROUND_REMOVE = 1; // 0x1
}
+ public abstract class ServiceStartNotAllowedException extends java.lang.IllegalStateException {
+ }
+
public abstract class SharedElementCallback {
ctor public SharedElementCallback();
method public android.os.Parcelable onCaptureSharedElementSnapshot(android.view.View, android.graphics.Matrix, android.graphics.RectF);
@@ -51684,6 +51701,7 @@
method public int describeContents();
method public void dump(android.util.Printer, String);
method public android.content.ComponentName getComponent();
+ method public int getConfigChanges();
method public String getId();
method public int getIsDefaultResourceId();
method public String getPackageName();
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index fc1edf1..a02320d 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2548,6 +2548,10 @@
method @NonNull public static android.view.inputmethod.InlineSuggestionsResponse newInlineSuggestionsResponse(@NonNull java.util.List<android.view.inputmethod.InlineSuggestion>);
}
+ public final class InputMethodInfo implements android.os.Parcelable {
+ ctor public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, int);
+ }
+
public final class InputMethodManager {
method public int getDisplayId();
method public boolean hasActiveInputConnection(@Nullable android.view.View);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index b8735c7..2f3b50b 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -2551,9 +2551,9 @@
false, // READ_MEDIA_AUDIO
false, // WRITE_MEDIA_AUDIO
false, // READ_MEDIA_VIDEO
- false, // WRITE_MEDIA_VIDEO
+ true, // WRITE_MEDIA_VIDEO
false, // READ_MEDIA_IMAGES
- false, // WRITE_MEDIA_IMAGES
+ true, // WRITE_MEDIA_IMAGES
true, // LEGACY_STORAGE
false, // ACCESS_ACCESSIBILITY
false, // READ_DEVICE_IDENTIFIERS
diff --git a/core/java/android/app/BackgroundServiceStartNotAllowedException.java b/core/java/android/app/BackgroundServiceStartNotAllowedException.java
new file mode 100644
index 0000000..f6361b5
--- /dev/null
+++ b/core/java/android/app/BackgroundServiceStartNotAllowedException.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 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.app;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Exception thrown when an app tries to start a background {@link Service} when it's not allowed to
+ * do so.
+ */
+public final class BackgroundServiceStartNotAllowedException
+ extends ServiceStartNotAllowedException implements Parcelable {
+ /**
+ * Constructor.
+ */
+ public BackgroundServiceStartNotAllowedException(@NonNull String message) {
+ super(message);
+ }
+
+ BackgroundServiceStartNotAllowedException(@NonNull Parcel source) {
+ super(source.readString());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(getMessage());
+ }
+
+ public static final @NonNull Creator<android.app.BackgroundServiceStartNotAllowedException>
+ CREATOR = new Creator<android.app.BackgroundServiceStartNotAllowedException>() {
+ @NonNull
+ public android.app.BackgroundServiceStartNotAllowedException createFromParcel(
+ Parcel source) {
+ return new android.app.BackgroundServiceStartNotAllowedException(source);
+ }
+
+ @NonNull
+ public android.app.BackgroundServiceStartNotAllowedException[] newArray(int size) {
+ return new android.app.BackgroundServiceStartNotAllowedException[size];
+ }
+ };
+}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 85fb543..bc79813 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1796,7 +1796,7 @@
"Unable to start service " + service
+ ": " + cn.getClassName());
} else if (cn.getPackageName().equals("?")) {
- throw new IllegalStateException(
+ throw ServiceStartNotAllowedException.newInstance(requireForeground,
"Not allowed to start service " + service + ": " + cn.getClassName());
}
}
diff --git a/core/java/android/app/ForegroundServiceStartNotAllowedException.java b/core/java/android/app/ForegroundServiceStartNotAllowedException.java
new file mode 100644
index 0000000..41eeada2
--- /dev/null
+++ b/core/java/android/app/ForegroundServiceStartNotAllowedException.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 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.app;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Exception thrown when an app tries to start a foreground {@link Service} when it's not allowed to
+ * do so.
+ */
+public final class ForegroundServiceStartNotAllowedException
+ extends ServiceStartNotAllowedException implements Parcelable {
+ /**
+ * Constructor.
+ */
+ public ForegroundServiceStartNotAllowedException(@NonNull String message) {
+ super(message);
+ }
+
+ ForegroundServiceStartNotAllowedException(@NonNull Parcel source) {
+ super(source.readString());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(getMessage());
+ }
+
+ public static final @NonNull Creator<android.app.ForegroundServiceStartNotAllowedException>
+ CREATOR = new Creator<android.app.ForegroundServiceStartNotAllowedException>() {
+ @NonNull
+ public android.app.ForegroundServiceStartNotAllowedException createFromParcel(
+ Parcel source) {
+ return new android.app.ForegroundServiceStartNotAllowedException(source);
+ }
+
+ @NonNull
+ public android.app.ForegroundServiceStartNotAllowedException[] newArray(int size) {
+ return new android.app.ForegroundServiceStartNotAllowedException[size];
+ }
+ };
+}
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 3798de9..2ceea7f 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -697,7 +697,8 @@
* service element of manifest file. The value of attribute
* {@link android.R.attr#foregroundServiceType} can be multiple flags ORed together.</p>
*
- * @throws IllegalStateException If the app targeting API is
+ * @throws ForegroundServiceStartNotAllowedException
+ * If the app targeting API is
* {@link android.os.Build.VERSION_CODES#S} or later, and the service is restricted from
* becoming foreground service due to background restriction.
*
@@ -738,8 +739,14 @@
* @param notification The Notification to be displayed.
* @param foregroundServiceType must be a subset flags of manifest attribute
* {@link android.R.attr#foregroundServiceType} flags.
+ *
* @throws IllegalArgumentException if param foregroundServiceType is not subset of manifest
* attribute {@link android.R.attr#foregroundServiceType}.
+ * @throws ForegroundServiceStartNotAllowedException
+ * If the app targeting API is
+ * {@link android.os.Build.VERSION_CODES#S} or later, and the service is restricted from
+ * becoming foreground service due to background restriction.
+ *
* @see android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_MANIFEST
*/
public final void startForeground(int id, @NonNull Notification notification,
diff --git a/core/java/android/app/ServiceStartNotAllowedException.java b/core/java/android/app/ServiceStartNotAllowedException.java
new file mode 100644
index 0000000..33285b2
--- /dev/null
+++ b/core/java/android/app/ServiceStartNotAllowedException.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 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.app;
+
+import android.annotation.NonNull;
+
+/**
+ * Exception thrown when an app tries to start a {@link Service} when it's not allowed to do so.
+ */
+public abstract class ServiceStartNotAllowedException extends IllegalStateException {
+ ServiceStartNotAllowedException(@NonNull String message) {
+ super(message);
+ }
+
+ /**
+ * Return either {@link ForegroundServiceStartNotAllowedException} or
+ * {@link BackgroundServiceStartNotAllowedException}
+ * @hide
+ */
+ @NonNull
+ public static ServiceStartNotAllowedException newInstance(boolean foreground,
+ @NonNull String message) {
+ if (foreground) {
+ return new ForegroundServiceStartNotAllowedException(message);
+ } else {
+ return new BackgroundServiceStartNotAllowedException(message);
+ }
+ }
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 4284dc2..e20f706 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3118,8 +3118,18 @@
*
* @throws SecurityException If the caller does not have permission to access the service
* or the service can not be found.
- * @throws IllegalStateException If the application is in a state where the service
- * can not be started (such as not in the foreground in a state when services are allowed).
+ * @throws IllegalStateException
+ * Before Android {@link android.os.Build.VERSION_CODES#S},
+ * if the application is in a state where the service
+ * can not be started (such as not in the foreground in a state when services are allowed),
+ * {@link IllegalStateException} was thrown.
+ * @throws android.app.BackgroundServiceStartNotAllowedException
+ * On Android {@link android.os.Build.VERSION_CODES#S} and later,
+ * if the application is in a state where the service
+ * can not be started (such as not in the foreground in a state when services are allowed),
+ * {@link android.app.BackgroundServiceStartNotAllowedException} is thrown
+ * This excemption extends {@link IllegalStateException}, so apps can
+ * use {@code catch (IllegalStateException)} to catch both.
*
* @see #stopService
* @see #bindService
@@ -3150,7 +3160,8 @@
* @throws SecurityException If the caller does not have permission to access the service
* or the service can not be found.
*
- * @throws IllegalStateException If the caller app's targeting API is
+ * @throws android.app.ForegroundServiceStartNotAllowedException
+ * If the caller app's targeting API is
* {@link android.os.Build.VERSION_CODES#S} or later, and the foreground service is restricted
* from start due to background restriction.
*
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 5cfcd66..9198eb7 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -171,7 +171,7 @@
SomeArgs args = (SomeArgs) msg.obj;
try {
inputMethod.initializeInternal((IBinder) args.arg1, msg.arg1,
- (IInputMethodPrivilegedOperations) args.arg2);
+ (IInputMethodPrivilegedOperations) args.arg2, (int) args.arg3);
} finally {
args.recycle();
}
@@ -280,9 +280,10 @@
@BinderThread
@Override
public void initializeInternal(IBinder token, int displayId,
- IInputMethodPrivilegedOperations privOps) {
+ IInputMethodPrivilegedOperations privOps, int configChanges) {
mCaller.executeOrSendMessage(
- mCaller.obtainMessageIOO(DO_INITIALIZE_INTERNAL, displayId, token, privOps));
+ mCaller.obtainMessageIOOO(DO_INITIALIZE_INTERNAL, displayId, token, privOps,
+ configChanges));
}
@BinderThread
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 7e2be01..03dd306 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -70,6 +70,7 @@
import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -131,6 +132,7 @@
import android.window.WindowMetricsHelper;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.inputmethod.IInputContentUriToken;
import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
import com.android.internal.inputmethod.InputMethodPrivilegedOperations;
@@ -513,6 +515,8 @@
private boolean mIsAutomotive;
private Handler mHandler;
private boolean mImeSurfaceScheduledForRemoval;
+ private Configuration mLastKnownConfig;
+ private int mHandledConfigChanges;
/**
* An opaque {@link Binder} token of window requesting {@link InputMethodImpl#showSoftInput}
@@ -588,12 +592,14 @@
@MainThread
@Override
public final void initializeInternal(@NonNull IBinder token, int displayId,
- IInputMethodPrivilegedOperations privilegedOperations) {
+ IInputMethodPrivilegedOperations privilegedOperations,
+ int configChanges) {
if (InputMethodPrivilegedOperationsRegistry.isRegistered(token)) {
Log.w(TAG, "The token has already registered, ignore this initialization.");
return;
}
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.initializeInternal");
+ mHandledConfigChanges = configChanges;
mPrivOps.set(privilegedOperations);
InputMethodPrivilegedOperationsRegistry.put(token, mPrivOps);
updateInputMethodDisplay(displayId);
@@ -821,6 +827,9 @@
setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition);
}
final boolean isVisible = isInputViewShown();
+ if (isVisible && getResources() != null) {
+ mLastKnownConfig = getResources().getConfiguration();
+ }
final boolean visibilityChanged = isVisible != wasVisible;
if (resultReceiver != null) {
resultReceiver.send(visibilityChanged
@@ -1428,10 +1437,37 @@
* state: {@link #onStartInput} if input is active, and
* {@link #onCreateInputView} and {@link #onStartInputView} and related
* appropriate functions if the UI is displayed.
+ * <p>Starting with {@link Build.VERSION_CODES#S}, IMEs can opt into handling configuration
+ * changes themselves instead of being restarted with
+ * {@link android.R.styleable#InputMethod_configChanges}.
*/
@Override public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- resetStateForNewConfiguration();
+ if (shouldImeRestartForConfig(newConfig)) {
+ resetStateForNewConfiguration();
+ }
+ }
+
+ /**
+ * @return {@code true} if {@link InputMethodService} needs to restart to handle
+ * .{@link #onConfigurationChanged(Configuration)}
+ */
+ @VisibleForTesting
+ boolean shouldImeRestartForConfig(@NonNull Configuration newConfig) {
+ if (mLastKnownConfig == null) {
+ return true;
+ }
+ // If the new config is the same as the config this Service is already running with,
+ // then don't bother calling resetStateForNewConfiguration.
+ int diff = mLastKnownConfig.diffPublicOnly(newConfig);
+ if (diff != 0) {
+ // remove attrs not-relevant to IME service.
+ diff &= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
+ diff &= ActivityInfo.CONFIG_KEYBOARD;
+ diff &= ActivityInfo.CONFIG_NAVIGATION;
+ }
+ int unhandledDiff = (diff & ~mHandledConfigChanges);
+ return unhandledDiff != 0;
}
private void resetStateForNewConfiguration() {
@@ -3181,7 +3217,17 @@
requestHideSelf(InputMethodManager.HIDE_NOT_ALWAYS);
}
}
-
+
+ @VisibleForTesting
+ void setLastKnownConfig(@NonNull Configuration config) {
+ mLastKnownConfig = config;
+ }
+
+ @VisibleForTesting
+ void setHandledConfigChanges(int configChanges) {
+ mHandledConfigChanges = configChanges;
+ }
+
void startExtractingText(boolean inputChanged) {
final ExtractEditText eet = mExtractEditText;
if (eet != null && getCurrentInputStarted()
diff --git a/core/java/android/os/incremental/IncrementalFileStorages.java b/core/java/android/os/incremental/IncrementalFileStorages.java
index a078e04..73520e0 100644
--- a/core/java/android/os/incremental/IncrementalFileStorages.java
+++ b/core/java/android/os/incremental/IncrementalFileStorages.java
@@ -59,7 +59,6 @@
/**
* Set up files and directories used in an installation session. Only used by Incremental.
* All the files will be created in defaultStorage.
- * TODO(b/133435829): code clean up
*
* @throws IllegalStateException the session is not an Incremental installation session.
* @throws IOException if fails to setup files or directories.
@@ -73,12 +72,10 @@
@Nullable IStorageHealthListener healthListener,
@NonNull List<InstallationFileParcel> addedFiles,
@NonNull PerUidReadTimeouts[] perUidReadTimeouts,
- IPackageLoadingProgressCallback progressCallback) throws IOException {
- // TODO(b/136132412): validity check if session should not be incremental
+ @Nullable IPackageLoadingProgressCallback progressCallback) throws IOException {
IncrementalManager incrementalManager = (IncrementalManager) context.getSystemService(
Context.INCREMENTAL_SERVICE);
if (incrementalManager == null) {
- // TODO(b/146080380): add incremental-specific error code
throw new IOException("Failed to obtain incrementalManager.");
}
@@ -89,7 +86,6 @@
try {
result.addApkFile(file);
} catch (IOException e) {
- // TODO(b/146080380): add incremental-specific error code
throw new IOException(
"Failed to add file to IncFS: " + file.name + ", reason: ", e);
}
@@ -203,7 +199,6 @@
/**
* Resets the states and unbinds storage instances for an installation session.
- * TODO(b/136132412): make sure unnecessary binds are removed but useful storages are kept
*/
public void cleanUp() {
if (mDefaultStorage == null) {
@@ -211,8 +206,8 @@
}
try {
+ mIncrementalManager.unregisterLoadingProgressCallbacks(mStageDir.getAbsolutePath());
mDefaultStorage.unBind(mStageDir.getAbsolutePath());
- mDefaultStorage.unregisterLoadingProgressListener();
} catch (IOException ignored) {
}
mDefaultStorage = null;
diff --git a/core/java/android/os/incremental/IncrementalManager.java b/core/java/android/os/incremental/IncrementalManager.java
index 0589994..cec6a1f 100644
--- a/core/java/android/os/incremental/IncrementalManager.java
+++ b/core/java/android/os/incremental/IncrementalManager.java
@@ -342,7 +342,6 @@
storage.unregisterLoadingProgressListener();
}
- // TODO(b/165841827): handle reboot and app update
public boolean registerCallback(@NonNull IncrementalStorage storage,
@NonNull IPackageLoadingProgressCallback callback) {
final int storageId = storage.getId();
@@ -364,30 +363,6 @@
return storage.registerLoadingProgressListener(this);
}
- public boolean unregisterCallback(@NonNull IncrementalStorage storage,
- @NonNull IPackageLoadingProgressCallback callback) {
- final int storageId = storage.getId();
- final RemoteCallbackList<IPackageLoadingProgressCallback> callbacksForStorage;
- synchronized (mCallbacks) {
- callbacksForStorage = mCallbacks.get(storageId);
- if (callbacksForStorage == null) {
- // no callback has ever been registered on this storage
- return false;
- }
- if (!callbacksForStorage.unregister(callback)) {
- // the callback was not registered
- return false;
- }
- if (callbacksForStorage.getRegisteredCallbackCount() > 0) {
- // other callbacks are still listening on this storage
- return true;
- }
- mCallbacks.delete(storageId);
- }
- // stop listening for this storage
- return storage.unregisterLoadingProgressListener();
- }
-
@Override
public void onStorageLoadingProgressChanged(int storageId, float progress) {
final RemoteCallbackList<IPackageLoadingProgressCallback> callbacksForStorage;
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index de4554b..6ade5e6 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -105,7 +105,7 @@
*/
@MainThread
default void initializeInternal(IBinder token, int displayId,
- IInputMethodPrivilegedOperations privilegedOperations) {
+ IInputMethodPrivilegedOperations privilegedOperations, int configChanges) {
updateInputMethodDisplay(displayId);
attachToken(token);
}
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 5d876a6..25712f8 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -18,19 +18,23 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
+import android.inputmethodservice.InputMethodService;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
@@ -60,6 +64,7 @@
* @attr ref android.R.styleable#InputMethod_isDefault
* @attr ref android.R.styleable#InputMethod_supportsSwitchingToNextInputMethod
* @attr ref android.R.styleable#InputMethod_supportsInlineSuggestions
+ * @attr ref android.R.styleable#InputMethod_configChanges
*/
public final class InputMethodInfo implements Parcelable {
static final String TAG = "InputMethodInfo";
@@ -118,6 +123,12 @@
private final boolean mInlineSuggestionsEnabled;
/**
+ * The flag for configurations IME assumes the responsibility for handling in
+ * {@link InputMethodService#onConfigurationChanged(Configuration)}}.
+ */
+ private final int mHandledConfigChanges;
+
+ /**
* @param service the {@link ResolveInfo} corresponds in which the IME is implemented.
* @return a unique ID to be returned by {@link #getId()}. We have used
* {@link ComponentName#flattenToShortString()} for this purpose (and it is already
@@ -203,6 +214,8 @@
false);
inlineSuggestionsEnabled = sa.getBoolean(
com.android.internal.R.styleable.InputMethod_supportsInlineSuggestions, false);
+ mHandledConfigChanges = sa.getInt(
+ com.android.internal.R.styleable.InputMethod_configChanges, 0);
sa.recycle();
final int depth = parser.getDepth();
@@ -287,6 +300,7 @@
mIsVrOnly = source.readBoolean();
mService = ResolveInfo.CREATOR.createFromParcel(source);
mSubtypes = new InputMethodSubtypeArray(source);
+ mHandledConfigChanges = source.readInt();
mForceDefault = false;
}
@@ -298,7 +312,22 @@
this(buildFakeResolveInfo(packageName, className, label), false /* isAuxIme */,
settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
- false /* inlineSuggestionsEnabled */, false /* isVrOnly */);
+ false /* inlineSuggestionsEnabled */, false /* isVrOnly */,
+ 0 /* handledConfigChanges */);
+ }
+
+ /**
+ * Temporary API for creating a built-in input method for test.
+ * @hide
+ */
+ @TestApi
+ public InputMethodInfo(@NonNull String packageName, @NonNull String className,
+ @NonNull CharSequence label, @NonNull String settingsActivity,
+ int handledConfigChanges) {
+ this(buildFakeResolveInfo(packageName, className, label), false /* isAuxIme */,
+ settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
+ false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
+ false /* inlineSuggestionsEnabled */, false /* isVrOnly */, handledConfigChanges);
}
/**
@@ -310,7 +339,7 @@
boolean forceDefault) {
this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
true /* supportsSwitchingToNextInputMethod */, false /* inlineSuggestionsEnabled */,
- false /* isVrOnly */);
+ false /* isVrOnly */, 0 /* handledconfigChanges */);
}
/**
@@ -321,7 +350,8 @@
List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
boolean supportsSwitchingToNextInputMethod, boolean isVrOnly) {
this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
- supportsSwitchingToNextInputMethod, false /* inlineSuggestionsEnabled */, isVrOnly);
+ supportsSwitchingToNextInputMethod, false /* inlineSuggestionsEnabled */, isVrOnly,
+ 0 /* handledConfigChanges */);
}
/**
@@ -331,7 +361,7 @@
public InputMethodInfo(ResolveInfo ri, boolean isAuxIme, String settingsActivity,
List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
boolean supportsSwitchingToNextInputMethod, boolean inlineSuggestionsEnabled,
- boolean isVrOnly) {
+ boolean isVrOnly, int handledConfigChanges) {
final ServiceInfo si = ri.serviceInfo;
mService = ri;
mId = new ComponentName(si.packageName, si.name).flattenToShortString();
@@ -343,6 +373,7 @@
mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
mInlineSuggestionsEnabled = inlineSuggestionsEnabled;
mIsVrOnly = isVrOnly;
+ mHandledConfigChanges = handledConfigChanges;
}
private static ResolveInfo buildFakeResolveInfo(String packageName, String className,
@@ -489,6 +520,17 @@
}
}
+ /**
+ * Returns the bit mask of kinds of configuration changes that this IME
+ * can handle itself (without being restarted by the system).
+ *
+ * @attr ref android.R.styleable#InputMethod_configChanges
+ */
+ @ActivityInfo.Config
+ public int getConfigChanges() {
+ return mHandledConfigChanges;
+ }
+
public void dump(Printer pw, String prefix) {
pw.println(prefix + "mId=" + mId
+ " mSettingsActivityName=" + mSettingsActivityName
@@ -579,6 +621,7 @@
dest.writeBoolean(mIsVrOnly);
mService.writeToParcel(dest, flags);
mSubtypes.writeToParcel(dest);
+ dest.writeInt(mHandledConfigChanges);
}
/**
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index c336373..8d82e33 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -35,7 +35,8 @@
* {@hide}
*/
oneway interface IInputMethod {
- void initializeInternal(IBinder token, int displayId, IInputMethodPrivilegedOperations privOps);
+ void initializeInternal(IBinder token, int displayId, IInputMethodPrivilegedOperations privOps,
+ int configChanges);
void onCreateInlineSuggestionsRequest(in InlineSuggestionsRequestInfo requestInfo,
in IInlineSuggestionsRequestCallback cb);
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 69bb20c..99f58ee 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3564,6 +3564,16 @@
<attr name="__removed2" format="boolean" />
<!-- Specifies whether the IME supports showing inline suggestions. -->
<attr name="supportsInlineSuggestions" format="boolean" />
+ <!-- Specify one or more configuration changes that the IME will handle itself. If not
+ specified, the IME will be restarted if any of these configuration changes happen in
+ the system. Otherwise, the IME will remain running and its
+ {@link android.inputmethodservice.InputMethodService#onConfigurationChanged}
+ method is called with the new configuration.
+ <p>Note that all of these configuration changes can impact the
+ resource values seen by the application, so you will generally need
+ to re-retrieve all resources (including view layouts, drawables, etc)
+ to correctly handle any configuration change.-->
+ <attr name="configChanges" />
</declare-styleable>
<!-- This is the subtype of InputMethod. Subtype can describe locales (for example, en_US and
diff --git a/core/tests/coretests/src/android/inputmethodservice/InputMethodServiceTest.java b/core/tests/coretests/src/android/inputmethodservice/InputMethodServiceTest.java
new file mode 100644
index 0000000..8906149
--- /dev/null
+++ b/core/tests/coretests/src/android/inputmethodservice/InputMethodServiceTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2021 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.inputmethodservice;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+
+import static junit.framework.Assert.assertFalse;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.os.Build;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.ServiceTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.TimeoutException;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class InputMethodServiceTest {
+ private InputMethodService mService;
+ private Context mContext;
+ @Rule
+ public final ServiceTestRule serviceRule = new ServiceTestRule();
+
+ @Before
+ public void setUp() throws TimeoutException {
+ mContext = getInstrumentation().getContext();
+ mService = new InputMethodService();
+ }
+
+ @Test
+ public void testShouldImeRestartForConfig() throws Exception {
+ // Make sure we preserve Pre-S behavior i.e. Service restarts.
+ mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.R;
+ Configuration config = mContext.getResources().getConfiguration();
+ mService.setLastKnownConfig(config);
+ assertTrue("IME should restart for Pre-S",
+ mService.shouldImeRestartForConfig(config));
+
+ // IME shouldn't restart on targetSdk S+ (with no config changes).
+ mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.S;
+ assertFalse("IME shouldn't restart for S+",
+ mService.shouldImeRestartForConfig(config));
+
+ // Screen density changed but IME doesn't handle congfigChanges
+ config.densityDpi = 99;
+ assertTrue("IME should restart for unhandled configChanges",
+ mService.shouldImeRestartForConfig(config));
+
+ // opt-in IME to handle config changes.
+ mService.setHandledConfigChanges(ActivityInfo.CONFIG_DENSITY);
+ assertFalse("IME shouldn't restart for S+ since it handles configChanges",
+ mService.shouldImeRestartForConfig(config));
+ }
+}
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 6e458681..be49e1f 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -170,7 +170,6 @@
<declare-styleable name="AlphaTintDrawableWrapper">
<attr name="android:tint" />
- <attr name="android:drawable" />
<attr name="android:alpha" />
</declare-styleable>
@@ -191,9 +190,5 @@
<attr name="borderThickness" format="dimension" />
<attr name="borderColor" format="color" />
</declare-styleable>
-
- <declare-styleable name="RoundedCornerProgressDrawable">
- <attr name="android:drawable" />
- </declare-styleable>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetEnabler.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetEnabler.java
index b188acb..3df2644 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetEnabler.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetEnabler.java
@@ -23,6 +23,7 @@
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.people.PeopleSpaceActivity;
import com.android.systemui.statusbar.FeatureFlags;
import javax.inject.Inject;
@@ -54,6 +55,12 @@
? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
: PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
+ mContext.getPackageManager().setComponentEnabledSetting(
+ new ComponentName(mContext, PeopleSpaceActivity.class),
+ showPeopleSpace
+ ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
} catch (Exception e) {
Log.w(TAG, "Error enabling People Space widget:", e);
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
index a6aec3b..0b40e22 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
@@ -17,8 +17,6 @@
package com.android.systemui.settings.brightness;
import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -29,10 +27,8 @@
import androidx.annotation.Nullable;
import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
-import com.android.systemui.util.RoundedCornerProgressDrawable;
import com.android.systemui.util.ViewController;
import javax.inject.Inject;
@@ -274,9 +270,6 @@
private BrightnessSlider fromTree(ViewGroup root, boolean useMirror) {
BrightnessSliderView v = root.requireViewById(R.id.brightness_slider);
- // TODO(175026098) Workaround. Remove when b/175026098 is fixed
- applyTheme(v);
-
return new BrightnessSlider(root, v, useMirror);
}
@@ -286,32 +279,5 @@
? R.layout.quick_settings_brightness_dialog_thick
: R.layout.quick_settings_brightness_dialog;
}
-
- private LayerDrawable findProgressClippableDrawable(BrightnessSliderView v) {
- SeekBar b = v.requireViewById(R.id.slider);
- if (b.getProgressDrawable() instanceof LayerDrawable) {
- Drawable progress = ((LayerDrawable) b.getProgressDrawable())
- .findDrawableByLayerId(com.android.internal.R.id.progress);
- if (progress instanceof RoundedCornerProgressDrawable) {
- Drawable inner = ((RoundedCornerProgressDrawable) progress).getDrawable();
- if (inner instanceof LayerDrawable) {
- return (LayerDrawable) inner;
- }
- }
- }
- return null;
- }
-
- private void applyTheme(BrightnessSliderView v) {
- LayerDrawable layer = findProgressClippableDrawable(v);
- if (layer != null) {
- layer.findDrawableByLayerId(R.id.slider_foreground).setTintList(
- Utils.getColorAttr(v.getContext(),
- com.android.internal.R.attr.colorControlActivated));
- layer.findDrawableByLayerId(R.id.slider_icon).setTintList(
- Utils.getColorAttr(v.getContext(),
- com.android.internal.R.attr.colorBackground));
- }
- }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java b/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java
index 79a197d..a22793b 100644
--- a/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java
@@ -16,15 +16,18 @@
package com.android.systemui.util;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
import android.graphics.drawable.DrawableWrapper;
+import android.graphics.drawable.InsetDrawable;
import android.util.AttributeSet;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.systemui.R;
import org.xmlpull.v1.XmlPullParser;
@@ -45,13 +48,18 @@
* @attr ref R.styleable#AlphaTintDrawableWrapper_tint
* @attr ref R.styleable#AlphaTintDrawableWrapper_alpha
*/
-public class AlphaTintDrawableWrapper extends DrawableWrapper {
+public class AlphaTintDrawableWrapper extends InsetDrawable {
private ColorStateList mTint;
private int[] mThemeAttrs;
/** No-arg constructor used by drawable inflation. */
public AlphaTintDrawableWrapper() {
- super(null);
+ super(null, 0);
+ }
+
+ AlphaTintDrawableWrapper(Drawable drawable, int[] themeAttrs) {
+ super(drawable, 0);
+ mThemeAttrs = themeAttrs;
}
@Override
@@ -74,7 +82,7 @@
public void applyTheme(Theme t) {
super.applyTheme(t);
- if (mThemeAttrs != null) {
+ if (mThemeAttrs != null && t != null) {
final TypedArray a = t.resolveAttributes(mThemeAttrs,
R.styleable.AlphaTintDrawableWrapper);
updateStateFromTypedArray(a);
@@ -92,9 +100,6 @@
}
private void updateStateFromTypedArray(@NonNull TypedArray a) {
- if (a.hasValue(R.styleable.AlphaTintDrawableWrapper_android_drawable)) {
- setDrawable(a.getDrawable(R.styleable.AlphaTintDrawableWrapper_android_drawable));
- }
if (a.hasValue(R.styleable.AlphaTintDrawableWrapper_android_tint)) {
mTint = a.getColorStateList(R.styleable.AlphaTintDrawableWrapper_android_tint);
}
@@ -109,4 +114,57 @@
getDrawable().mutate().setTintList(mTint);
}
}
+
+ @Nullable
+ @Override
+ public ConstantState getConstantState() {
+ return new AlphaTintState(super.getConstantState(), mThemeAttrs, getAlpha(), mTint);
+ }
+
+ static class AlphaTintState extends Drawable.ConstantState {
+
+ private ConstantState mWrappedState;
+ private int[] mThemeAttrs;
+ private int mAlpha;
+ private ColorStateList mColorStateList;
+
+ AlphaTintState(
+ ConstantState wrappedState,
+ int[] themeAttrs,
+ int alpha,
+ ColorStateList colorStateList
+ ) {
+ mWrappedState = wrappedState;
+ mThemeAttrs = themeAttrs;
+ mAlpha = alpha;
+ mColorStateList = colorStateList;
+ }
+
+ @NonNull
+ @Override
+ public Drawable newDrawable() {
+ return newDrawable(null, null);
+ }
+
+ @NonNull
+ @Override
+ public Drawable newDrawable(Resources res, Theme theme) {
+ DrawableWrapper wrapper = (DrawableWrapper) mWrappedState.newDrawable(res, theme);
+ AlphaTintDrawableWrapper alphaTintDrawableWrapper =
+ new AlphaTintDrawableWrapper(wrapper.getDrawable(), mThemeAttrs);
+ alphaTintDrawableWrapper.setTintList(mColorStateList);
+ alphaTintDrawableWrapper.setAlpha(mAlpha);
+ return alphaTintDrawableWrapper;
+ }
+
+ @Override
+ public boolean canApplyTheme() {
+ return true;
+ }
+
+ @Override
+ public int getChangingConfigurations() {
+ return mWrappedState.getChangingConfigurations();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt b/packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt
index 1af2c9f..6aadd10 100644
--- a/packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt
@@ -17,15 +17,12 @@
package com.android.systemui.util
import android.content.res.Resources
-import android.content.res.TypedArray
import android.graphics.Canvas
import android.graphics.Path
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.graphics.drawable.DrawableWrapper
-import android.util.AttributeSet
-import com.android.systemui.R
-import org.xmlpull.v1.XmlPullParser
+import android.graphics.drawable.InsetDrawable
/**
* [DrawableWrapper] to use in the progress of a slider.
@@ -38,9 +35,9 @@
* is meant to be smaller than the rounded corner. The background should have rounded corners that
* are half of the height.
*/
-class RoundedCornerProgressDrawable(drawable: Drawable?) : DrawableWrapper(drawable) {
-
- constructor() : this(null)
+class RoundedCornerProgressDrawable @JvmOverloads constructor(
+ drawable: Drawable? = null
+) : InsetDrawable(drawable, 0) {
companion object {
private const val MAX_LEVEL = 10000 // Taken from Drawable
@@ -52,35 +49,11 @@
setClipPath(Rect())
}
- override fun inflate(
- r: Resources,
- parser: XmlPullParser,
- attrs: AttributeSet,
- theme: Resources.Theme?
- ) {
- val a = obtainAttributes(r, theme, attrs, R.styleable.RoundedCornerProgressDrawable)
-
- // Inflation will advance the XmlPullParser and AttributeSet.
- super.inflate(r, parser, attrs, theme)
-
- updateStateFromTypedArray(a)
- if (drawable == null) {
- throw IllegalStateException("${this::class.java.simpleName} needs a drawable")
- }
- a.recycle()
- }
-
override fun onLayoutDirectionChanged(layoutDirection: Int): Boolean {
onLevelChange(level)
return super.onLayoutDirectionChanged(layoutDirection)
}
- private fun updateStateFromTypedArray(a: TypedArray) {
- if (a.hasValue(R.styleable.RoundedCornerProgressDrawable_android_drawable)) {
- setDrawable(a.getDrawable(R.styleable.RoundedCornerProgressDrawable_android_drawable))
- }
- }
-
override fun onBoundsChange(bounds: Rect) {
setClipPath(bounds)
super.onBoundsChange(bounds)
@@ -115,4 +88,24 @@
super.draw(canvas)
canvas.restore()
}
+
+ override fun getConstantState(): ConstantState? {
+ // This should not be null as it was created with a state in the constructor.
+ return RoundedCornerState(super.getConstantState()!!)
+ }
+
+ private class RoundedCornerState(private val wrappedState: ConstantState) : ConstantState() {
+ override fun newDrawable(): Drawable {
+ return newDrawable(null, null)
+ }
+
+ override fun newDrawable(res: Resources?, theme: Resources.Theme?): Drawable {
+ val wrapper = wrappedState.newDrawable(res, theme) as DrawableWrapper
+ return RoundedCornerProgressDrawable(wrapper.drawable)
+ }
+
+ override fun getChangingConfigurations(): Int {
+ return wrappedState.changingConfigurations
+ }
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
index 06806d0..6a648bd 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
@@ -347,6 +347,7 @@
public void check(long timeoutMs, Consumer<Boolean> callback) {
if (!mSensor.isLoaded()) {
callback.accept(null);
+ return;
}
mCallbacks.add(callback);
if (!mRegistered.getAndSet(true)) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java
index c5a197e..242fe9f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.util.sensors;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@@ -86,6 +88,29 @@
}
@Test
+ public void testNotLoaded() {
+ mFakeProximitySensor.setSensorAvailable(false);
+
+ assertThat(mTestableCallback.mLastResult).isNull();
+ assertThat(mTestableCallback.mNumCalls).isEqualTo(0);
+
+ mProximityCheck.check(100, mTestableCallback);
+
+ assertThat(mTestableCallback.mLastResult).isNull();
+ assertThat(mTestableCallback.mNumCalls).isEqualTo(1);
+
+ mFakeProximitySensor.setSensorAvailable(true);
+
+ mProximityCheck.check(100, mTestableCallback);
+
+ mFakeProximitySensor.setLastEvent(new ProximitySensor.ThresholdSensorEvent(true, 0));
+ mFakeProximitySensor.alertListeners();
+
+ assertThat(mTestableCallback.mLastResult).isNotNull();
+ assertThat(mTestableCallback.mNumCalls).isEqualTo(2);
+ }
+
+ @Test
public void testProxDoesntCancelOthers() {
assertFalse(mFakeProximitySensor.isRegistered());
// We don't need our "other" listener to do anything. Just ensure our sensor is registered.
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 5550999..2efc83c 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -52,6 +52,7 @@
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
+import android.app.ForegroundServiceStartNotAllowedException;
import android.app.IApplicationThread;
import android.app.IServiceConnection;
import android.app.Notification;
@@ -693,7 +694,7 @@
+ "could not resolve client package " + callingPackage);
}
if (CompatChanges.isChangeEnabled(FGS_START_EXCEPTION_CHANGE_ID, aInfo.uid)) {
- throw new IllegalStateException(msg);
+ throw new ForegroundServiceStartNotAllowedException(msg);
}
return null;
}
@@ -1778,7 +1779,7 @@
ignoreForeground = true;
if (CompatChanges.isChangeEnabled(FGS_START_EXCEPTION_CHANGE_ID,
r.appInfo.uid)) {
- throw new IllegalStateException(msg);
+ throw new ForegroundServiceStartNotAllowedException(msg);
}
}
}
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index cd17cfe..b3070b7 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -16,6 +16,7 @@
package com.android.server.display;
+import android.content.Context;
import android.graphics.Rect;
import android.hardware.display.DisplayViewport;
import android.os.IBinder;
@@ -38,12 +39,14 @@
private final IBinder mDisplayToken;
private final String mUniqueId;
+ protected DisplayDeviceConfig mDisplayDeviceConfig;
// The display device does not manage these properties itself, they are set by
// the display manager service. The display device shouldn't really be looking at these.
private int mCurrentLayerStack = -1;
private int mCurrentOrientation = -1;
private Rect mCurrentLayerStackRect;
private Rect mCurrentDisplayRect;
+ private final Context mContext;
// The display device owns its surface, but it should only set it
// within a transaction from performTraversalLocked.
@@ -53,10 +56,13 @@
// Do not use for any other purpose.
DisplayDeviceInfo mDebugLastLoggedDeviceInfo;
- public DisplayDevice(DisplayAdapter displayAdapter, IBinder displayToken, String uniqueId) {
+ public DisplayDevice(DisplayAdapter displayAdapter, IBinder displayToken, String uniqueId,
+ Context context) {
mDisplayAdapter = displayAdapter;
mDisplayToken = displayToken;
mUniqueId = uniqueId;
+ mDisplayDeviceConfig = null;
+ mContext = context;
}
/**
@@ -74,7 +80,10 @@
* @return The DisplayDeviceConfig; {@code null} if not overridden.
*/
public DisplayDeviceConfig getDisplayDeviceConfig() {
- return null;
+ if (mDisplayDeviceConfig == null) {
+ mDisplayDeviceConfig = loadDisplayDeviceConfig();
+ }
+ return mDisplayDeviceConfig;
}
/**
@@ -292,4 +301,8 @@
pw.println("mCurrentDisplayRect=" + mCurrentDisplayRect);
pw.println("mCurrentSurface=" + mCurrentSurface);
}
+
+ private DisplayDeviceConfig loadDisplayDeviceConfig() {
+ return DisplayDeviceConfig.create(mContext, false);
+ }
}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 1b25427..49328f1 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -120,7 +120,20 @@
// If no config can be loaded from any ddc xml at all,
// prepare a whole config using the global config.xml.
// Guaranteed not null
- if (isDefaultDisplay) {
+ return create(context, isDefaultDisplay);
+ }
+
+ /**
+ * Creates an instance using global values since no display device config xml exists.
+ * Uses values from config or PowerManager.
+ *
+ * @param context
+ * @param useConfigXml
+ * @return A configuration instance.
+ */
+ public static DisplayDeviceConfig create(Context context, boolean useConfigXml) {
+ DisplayDeviceConfig config;
+ if (useConfigXml) {
config = getConfigFromGlobalXml(context);
} else {
config = getConfigFromPmValues(context);
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index ed01044..a4e2c70 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -40,7 +40,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
-import com.android.internal.os.BackgroundThread;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.lights.LightsManager;
@@ -213,7 +212,6 @@
private SurfaceControl.DisplayMode mActiveSfDisplayMode;
private Spline mSystemBrightnessToNits;
private Spline mNitsToHalBrightness;
- private DisplayDeviceConfig mDisplayDeviceConfig;
private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides =
new DisplayEventReceiver.FrameRateOverride[0];
@@ -222,7 +220,8 @@
SurfaceControl.StaticDisplayInfo staticDisplayInfo,
SurfaceControl.DynamicDisplayInfo dynamicInfo,
SurfaceControl.DesiredDisplayModeSpecs modeSpecs, boolean isDefaultDisplay) {
- super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + physicalDisplayId);
+ super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + physicalDisplayId,
+ getContext());
mPhysicalDisplayId = physicalDisplayId;
mIsDefaultDisplay = isDefaultDisplay;
updateDisplayPropertiesLocked(staticDisplayInfo, dynamicInfo, modeSpecs);
@@ -232,9 +231,6 @@
mAllmSupported = SurfaceControl.getAutoLowLatencyModeSupport(displayToken);
mGameContentTypeSupported = SurfaceControl.getGameContentTypeSupport(displayToken);
mDisplayDeviceConfig = null;
- // Defer configuration file loading
- BackgroundThread.getHandler().sendMessage(PooledLambda.obtainMessage(
- LocalDisplayDevice::loadDisplayConfiguration, this));
}
@Override
@@ -413,6 +409,9 @@
@Override
public DisplayDeviceConfig getDisplayDeviceConfig() {
+ if (mDisplayDeviceConfig == null) {
+ loadDisplayConfiguration();
+ }
return mDisplayDeviceConfig;
}
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 69943e3..330379c 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -281,7 +281,8 @@
List<OverlayMode> modes, int activeMode, int defaultMode,
float refreshRate, long presentationDeadlineNanos,
OverlayFlags flags, int state, SurfaceTexture surfaceTexture, int number) {
- super(OverlayDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + number);
+ super(OverlayDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + number,
+ getContext());
mName = name;
mRefreshRate = refreshRate;
mDisplayPresentationDeadlineNanos = presentationDeadlineNanos;
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index ff4717b..52a810b 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -236,7 +236,7 @@
int ownerUid, String ownerPackageName, Surface surface, int flags,
Callback callback, String uniqueId, int uniqueIndex,
VirtualDisplayConfig virtualDisplayConfig) {
- super(VirtualDisplayAdapter.this, displayToken, uniqueId);
+ super(VirtualDisplayAdapter.this, displayToken, uniqueId, getContext());
mAppToken = appToken;
mOwnerUid = ownerUid;
mOwnerPackageName = ownerPackageName;
diff --git a/services/core/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
index 5732317..d2baaf22 100644
--- a/services/core/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
@@ -598,7 +598,8 @@
public WifiDisplayDevice(IBinder displayToken, String name,
int width, int height, float refreshRate, int flags, String address,
Surface surface) {
- super(WifiDisplayAdapter.this, displayToken, DISPLAY_NAME_PREFIX + address);
+ super(WifiDisplayAdapter.this, displayToken, DISPLAY_NAME_PREFIX + address,
+ getContext());
mName = name;
mWidth = width;
mHeight = height;
diff --git a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
index 86a8e36..983b6b5 100644
--- a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
+++ b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
@@ -100,9 +100,9 @@
@Override
public boolean start() {
- if (mIsCec20) {
- sendSetStreamPath();
- }
+ // Wake-up on <Set Stream Path> was not mandatory before CEC 2.0.
+ // The message is re-sent at the end of the action for devices that don't support 2.0.
+ sendSetStreamPath();
int targetPowerStatus = localDevice().mService.getHdmiCecNetwork()
.getCecDeviceInfo(getTargetAddress()).getDevicePowerStatus();
if (!mIsCec20 || targetPowerStatus == HdmiControlManager.POWER_STATUS_UNKNOWN) {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 0754df0..1e66589 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2620,8 +2620,9 @@
}
if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
// Dispatch display id for InputMethodService to update context display.
- executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
- MSG_INITIALIZE_IME, mCurTokenDisplayId, mCurMethod, mCurToken));
+ executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOOO(
+ MSG_INITIALIZE_IME, mCurTokenDisplayId, mCurMethod, mCurToken,
+ mMethodMap.get(mCurMethodId).getConfigChanges()));
scheduleNotifyImeUidToAudioService(mCurMethodUid);
if (mCurClient != null) {
clearClientSessionLocked(mCurClient);
@@ -4466,7 +4467,8 @@
}
final IBinder token = (IBinder) args.arg2;
((IInputMethod) args.arg1).initializeInternal(token, msg.arg1,
- new InputMethodPrivilegedOperationsImpl(this, token));
+ new InputMethodPrivilegedOperationsImpl(this, token),
+ (int) args.arg3);
} catch (RemoteException e) {
}
args.recycle();
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index f078242..4500bbc 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -39,6 +39,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.util.XmlUtils;
+import com.android.server.pm.PackageManagerService;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -465,6 +466,7 @@
return PendingIntent.getBroadcast(mContext,
REQUEST_CODE_REPOST,
new Intent(REPOST_ACTION)
+ .setPackage(PackageManagerService.PLATFORM_PACKAGE_NAME)
.setData(new Uri.Builder().scheme(REPOST_SCHEME).appendPath(key).build())
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
.putExtra(EXTRA_KEY, key)
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 9e2ca9d..7bf3c5c 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1207,8 +1207,13 @@
@GuardedBy("mLock")
private void computeProgressLocked(boolean forcePublish) {
- mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f)
- + MathUtils.constrain(mInternalProgress * 0.2f, 0f, 0.2f);
+ if (!mCommitted) {
+ mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f)
+ + MathUtils.constrain(mInternalProgress * 0.2f, 0f, 0.2f);
+ } else {
+ // For incremental installs, continue publishing the install progress during committing.
+ mProgress = mIncrementalProgress;
+ }
// Only publish when meaningful change
if (forcePublish || Math.abs(mProgress - mReportedProgress) >= 0.01) {
@@ -1944,9 +1949,11 @@
throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
"Session destroyed");
}
- // Client staging is fully done at this point
- mClientProgress = 1f;
- computeProgressLocked(true);
+ if (!isIncrementalInstallation()) {
+ // For non-incremental installs, client staging is fully done at this point
+ mClientProgress = 1f;
+ computeProgressLocked(true);
+ }
// This ongoing commit should keep session active, even though client
// will probably close their end.
@@ -3804,6 +3811,7 @@
public void onPackageLoadingProgressChanged(float progress) {
synchronized (mLock) {
mIncrementalProgress = progress;
+ computeProgressLocked(true);
}
}
});
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 1c55072..bc86d1d 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -993,7 +993,7 @@
private DisplayDeviceInfo mDisplayDeviceInfo;
FakeDisplayDevice() {
- super(null, null, "");
+ super(null, null, "", mContext);
}
public void setDisplayDeviceInfo(DisplayDeviceInfo displayDeviceInfo) {
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionTest.java
index f49cbca..9bf95c0 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionTest.java
@@ -221,7 +221,8 @@
"testDeviceSelect");
action.start();
mTestLooper.dispatchAll();
- assertThat(mNativeWrapper.getResultMessages()).doesNotContain(SET_STREAM_PATH);
+ assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
+ mNativeWrapper.clearResultMessages();
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
action.processCommand(REPORT_POWER_STATUS_ON);
mTestLooper.dispatchAll();
@@ -238,12 +239,15 @@
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
/*isCec20=*/false);
action.start();
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
action.processCommand(REPORT_POWER_STATUS_STANDBY);
mTestLooper.dispatchAll();
HdmiCecMessage userControlPressed = HdmiCecMessageBuilder.buildUserControlPressed(
ADDR_TV, ADDR_PLAYBACK_1, HdmiCecKeycode.CEC_KEYCODE_POWER);
assertThat(mNativeWrapper.getResultMessages()).contains(userControlPressed);
+ mNativeWrapper.clearResultMessages();
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
action.processCommand(REPORT_POWER_STATUS_ON);
@@ -261,6 +265,9 @@
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
/*isCec20=*/false);
action.start();
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
+ mNativeWrapper.clearResultMessages();
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
action.processCommand(REPORT_POWER_STATUS_STANDBY);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
@@ -285,6 +292,9 @@
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
/*isCec20=*/false);
action.start();
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
+ mNativeWrapper.clearResultMessages();
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
action.processCommand(REPORT_POWER_STATUS_STANDBY);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
@@ -330,8 +340,11 @@
action.start();
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
+ mNativeWrapper.clearResultMessages();
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
action.processCommand(REPORT_POWER_STATUS_ON);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(SET_STREAM_PATH);
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
}
@@ -354,9 +367,12 @@
HdmiCecMessage userControlPressed = HdmiCecMessageBuilder.buildUserControlPressed(
ADDR_TV, ADDR_PLAYBACK_1, HdmiCecKeycode.CEC_KEYCODE_POWER);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(userControlPressed);
+ mNativeWrapper.clearResultMessages();
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
action.processCommand(REPORT_POWER_STATUS_ON);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(SET_STREAM_PATH);
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
index 35b224a..2ae2ef7 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
@@ -51,6 +51,7 @@
import com.android.internal.util.FastXmlSerializer;
import com.android.server.UiServiceTestCase;
+import com.android.server.pm.PackageManagerService;
import org.junit.Before;
import org.junit.Test;
@@ -259,6 +260,17 @@
}
@Test
+ public void testSnoozeSentToAndroid() throws Exception {
+ NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
+ mSnoozeHelper.snooze(r, 1000);
+ ArgumentCaptor<PendingIntent> captor = ArgumentCaptor.forClass(PendingIntent.class);
+ verify(mAm, times(1)).setExactAndAllowWhileIdle(
+ anyInt(), anyLong(), captor.capture());
+ assertEquals(PackageManagerService.PLATFORM_PACKAGE_NAME,
+ captor.getValue().getIntent().getPackage());
+ }
+
+ @Test
public void testSnooze() throws Exception {
NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
mSnoozeHelper.snooze(r, (String) null);