diff --git a/core/api/system-current.txt b/core/api/system-current.txt index faf784d05c032..f94c33b7ae3d2 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -46,6 +46,7 @@ package android { field public static final String BIND_PRINT_RECOMMENDATION_SERVICE = "android.permission.BIND_PRINT_RECOMMENDATION_SERVICE"; field public static final String BIND_RESOLVER_RANKER_SERVICE = "android.permission.BIND_RESOLVER_RANKER_SERVICE"; field public static final String BIND_RESUME_ON_REBOOT_SERVICE = "android.permission.BIND_RESUME_ON_REBOOT_SERVICE"; + field public static final String BIND_ROTATION_RESOLVER_SERVICE = "android.permission.BIND_ROTATION_RESOLVER_SERVICE"; field public static final String BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE = "android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE"; field public static final String BIND_SETTINGS_SUGGESTIONS_SERVICE = "android.permission.BIND_SETTINGS_SUGGESTIONS_SERVICE"; field public static final String BIND_SOUND_TRIGGER_DETECTION_SERVICE = "android.permission.BIND_SOUND_TRIGGER_DETECTION_SERVICE"; @@ -133,6 +134,7 @@ package android { field public static final String MANAGE_ONE_TIME_PERMISSION_SESSIONS = "android.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS"; field public static final String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS"; field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS"; + field public static final String MANAGE_ROTATION_RESOLVER = "android.permission.MANAGE_ROTATION_RESOLVER"; field public static final String MANAGE_SEARCH_UI = "android.permission.MANAGE_SEARCH_UI"; field public static final String MANAGE_SENSOR_PRIVACY = "android.permission.MANAGE_SENSOR_PRIVACY"; field public static final String MANAGE_SOUND_TRIGGER = "android.permission.MANAGE_SOUND_TRIGGER"; @@ -9961,6 +9963,37 @@ package android.service.resumeonreboot { } +package android.service.rotationresolver { + + public final class RotationResolutionRequest implements android.os.Parcelable { + method public int describeContents(); + method public int getCurrentRotation(); + method @NonNull public String getPackageName(); + method public int getProposedRotation(); + method public long getTimeoutMillis(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public abstract class RotationResolverService extends android.app.Service { + ctor public RotationResolverService(); + method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent); + method public abstract void onResolveRotation(@NonNull android.service.rotationresolver.RotationResolutionRequest, @Nullable android.os.CancellationSignal, @NonNull android.service.rotationresolver.RotationResolverService.RotationResolverCallback); + field public static final int ROTATION_RESULT_FAILURE_CANCELLED = 0; // 0x0 + field public static final int ROTATION_RESULT_FAILURE_NOT_SUPPORTED = 4; // 0x4 + field public static final int ROTATION_RESULT_FAILURE_PREEMPTED = 2; // 0x2 + field public static final int ROTATION_RESULT_FAILURE_TIMED_OUT = 1; // 0x1 + field public static final int ROTATION_RESULT_FAILURE_UNKNOWN = 3; // 0x3 + field public static final String SERVICE_INTERFACE = "android.service.rotationresolver.RotationResolverService"; + } + + public static interface RotationResolverService.RotationResolverCallback { + method public void onFailure(int); + method public void onSuccess(int); + } + +} + package android.service.search { public abstract class SearchUiService extends android.app.Service { diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 186d1fede5e0d..77542bda22a09 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -3261,6 +3261,15 @@ public class ApplicationPackageManager extends PackageManager { } } + @Override + public String getRotationResolverPackageName() { + try { + return mPM.getRotationResolverPackageName(); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + @Override public String getWellbeingPackageName() { try { diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 6df4304143e7b..5a0ca978b86c7 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4498,6 +4498,16 @@ public abstract class Context { */ public static final String ATTENTION_SERVICE = "attention"; + /** + * Official published name of the (internal) rotation resolver service. + * + * // TODO(b/178151184): change it back to rotation resolver before S release. + * + * @see #getSystemService(String) + * @hide + */ + public static final String ROTATION_RESOLVER_SERVICE = "resolver"; + /** * Use with {@link #getSystemService(String)} to retrieve a * {@link android.view.inputmethod.InputMethodManager} for accessing input diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 7c0b821619880..34d100354051f 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -722,6 +722,8 @@ interface IPackageManager { String getAttentionServicePackageName(); + String getRotationResolverPackageName(); + String getWellbeingPackageName(); String getAppPredictionServicePackageName(); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 8243dc67027ce..4ffdf67a4e1ca 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -8636,6 +8636,16 @@ public abstract class PackageManager { "getAttentionServicePackageName not implemented in subclass"); } + /** + * @return rotation resolver service's package name, or null if there's none. + * + * @hide + */ + public String getRotationResolverPackageName() { + throw new UnsupportedOperationException( + "getRotationResolverPackageName not implemented in subclass"); + } + /** * @return the wellbeing app package name, or null if it's not defined by the OEM. * diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index 7a856e8a02b7f..a29b4b9adbb2a 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -290,6 +290,13 @@ public final class DeviceConfig { @SystemApi public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot"; + /** + * Namespace for Rotation Resolver Manager Service. + * + * @hide + */ + public static final String NAMESPACE_ROTATION_RESOLVER = "rotation_resolver"; + /** * Namespace for all runtime related features that don't require a reboot to become active. * There are no feature flags using NAMESPACE_RUNTIME. diff --git a/core/java/android/rotationresolver/RotationResolverInternal.java b/core/java/android/rotationresolver/RotationResolverInternal.java new file mode 100644 index 0000000000000..db879a7e3f8fb --- /dev/null +++ b/core/java/android/rotationresolver/RotationResolverInternal.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2020 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.rotationresolver; + +import android.annotation.DurationMillisLong; +import android.annotation.NonNull; +import android.os.CancellationSignal; +import android.service.rotationresolver.RotationResolverService; +import android.view.Surface; + +/** + * Internal service for resolving screen rotation. + * + * @hide Only for use within the system server. + */ +public abstract class RotationResolverInternal { + + /** + * Returns {@code true} if rotation resolver service is supported on the current device. + */ + public abstract boolean isRotationResolverSupported(); + + /** + * Queries the appropriate screen orientation. + * + *

The screen rotation that's proposed by the system may not be accurate enough. This method + * is available for the system to request a screen rotation resolution from the {@link + * RotationResolverService}, which can intelligently determine the appropriate screen rotation + * based on various sensors. + * + * @param callback the callback that will be called when the result is computed or an + * error is captured. {@link RotationResolverCallbackInternal} + * @param proposedRotation the screen rotation that is proposed by the system. + * @param currentRotation the current screen rotation. + * @param packageName the package name of the current activity that is running in foreground. + * @param timeoutMillis the timeout in millisecond for the query. If the query doesn't get + * fulfilled within this amount of time. It will be discarded and the + * callback will receive a failure result code {@link + * RotationResolverService#ROTATION_RESULT_FAILURE_TIMED_OUT}. + * @param cancellationSignal a cancellation signal that notifies the rotation resolver manger + */ + public abstract void resolveRotation(@NonNull RotationResolverCallbackInternal callback, + @Surface.Rotation int proposedRotation, @Surface.Rotation int currentRotation, + String packageName, @DurationMillisLong long timeoutMillis, + @NonNull CancellationSignal cancellationSignal); + + /** + * Internal interfaces for the rotation resolver callback. + */ + public interface RotationResolverCallbackInternal { + /** + * Gets called when the screen rotation is calculated successfully. + * + * @param result the resolved screen rotation. + */ + void onSuccess(@Surface.Rotation int result); + + /** + * Gets called when it fails to resolve the screen rotation. + * + * @param error the reason of the failure. + */ + void onFailure(@RotationResolverService.FailureCodes int error); + } +} diff --git a/core/java/android/service/rotationresolver/IRotationResolverCallback.aidl b/core/java/android/service/rotationresolver/IRotationResolverCallback.aidl new file mode 100644 index 0000000000000..e9bbc640acdd0 --- /dev/null +++ b/core/java/android/service/rotationresolver/IRotationResolverCallback.aidl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.rotationresolver; + +import android.os.ICancellationSignal; + +/** + * Callback for onResolveRotation request. + * + * @hide + */ +oneway interface IRotationResolverCallback { + void onCancellable(ICancellationSignal cancellation); + void onSuccess(int recommendedRotation); + void onFailure(int error); +} diff --git a/core/java/android/service/rotationresolver/IRotationResolverService.aidl b/core/java/android/service/rotationresolver/IRotationResolverService.aidl new file mode 100644 index 0000000000000..1b7713e497f76 --- /dev/null +++ b/core/java/android/service/rotationresolver/IRotationResolverService.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.rotationresolver; + +import android.service.rotationresolver.IRotationResolverCallback; +import android.service.rotationresolver.RotationResolutionRequest; + +/** + * Interface from the system to a RotationResolverService. + * + * @hide + */ +oneway interface IRotationResolverService { + void resolveRotation(IRotationResolverCallback callback, in RotationResolutionRequest request); +} \ No newline at end of file diff --git a/core/java/android/service/rotationresolver/RotationResolutionRequest.aidl b/core/java/android/service/rotationresolver/RotationResolutionRequest.aidl new file mode 100644 index 0000000000000..364a8fe934ce6 --- /dev/null +++ b/core/java/android/service/rotationresolver/RotationResolutionRequest.aidl @@ -0,0 +1,19 @@ +/* + * 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.service.rotationresolver; + +parcelable RotationResolutionRequest; \ No newline at end of file diff --git a/core/java/android/service/rotationresolver/RotationResolutionRequest.java b/core/java/android/service/rotationresolver/RotationResolutionRequest.java new file mode 100644 index 0000000000000..94a6052c246dc --- /dev/null +++ b/core/java/android/service/rotationresolver/RotationResolutionRequest.java @@ -0,0 +1,99 @@ +/* + * 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.service.rotationresolver; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * This class represents a request to an {@link RotationResolverService}. The request contains + * information from the system that can help RotationResolverService to determine the appropriate + * screen rotation. + * + * @see RotationResolverService#resolveRotation(IRotationResolverCallback, + * RotationResolutionRequest, ICancellationSignal) + * + * @hide + */ +@SystemApi +public final class RotationResolutionRequest implements Parcelable { + private final @NonNull String mPackageName; + private final int mProposedRotation; + private final int mCurrentRotation; + private final long mTimeoutMillis; + + /** + * @param proposedRotation The system proposed screen rotation. + * @param currentRotation The current screen rotation of the phone. + * @param packageName The current package name of the activity that is running in + * foreground. + * @param timeoutMillis The timeout in millisecond for the rotation request. + * @hide + */ + public RotationResolutionRequest(int proposedRotation, int currentRotation, + @NonNull String packageName, long timeoutMillis) { + mProposedRotation = proposedRotation; + mCurrentRotation = currentRotation; + mPackageName = packageName; + mTimeoutMillis = timeoutMillis; + } + + public int getProposedRotation() { + return mProposedRotation; + } + + public int getCurrentRotation() { + return mCurrentRotation; + } + + public @NonNull String getPackageName() { + return mPackageName; + } + + public long getTimeoutMillis() { + return mTimeoutMillis; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel parcel, int flags) { + parcel.writeInt(mProposedRotation); + parcel.writeInt(mCurrentRotation); + parcel.writeString(mPackageName); + parcel.writeLong(mTimeoutMillis); + } + + public static final @NonNull Creator CREATOR = + new Creator() { + @Override + public RotationResolutionRequest createFromParcel(Parcel source) { + return new RotationResolutionRequest(source.readInt(), source.readInt(), + source.readString(), source.readLong()); + } + + @Override + public RotationResolutionRequest[] newArray(int size) { + return new RotationResolutionRequest[size]; + } + }; +} diff --git a/core/java/android/service/rotationresolver/RotationResolverService.java b/core/java/android/service/rotationresolver/RotationResolverService.java new file mode 100644 index 0000000000000..593a642b4a383 --- /dev/null +++ b/core/java/android/service/rotationresolver/RotationResolverService.java @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.rotationresolver; + +import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; + +import android.annotation.IntDef; +import android.annotation.MainThread; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.app.Service; +import android.content.Intent; +import android.os.CancellationSignal; +import android.os.Handler; +import android.os.IBinder; +import android.os.ICancellationSignal; +import android.os.Looper; +import android.os.RemoteException; +import android.view.Surface; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** + * Abstract base class for rotation resolver service. + * + *

A {@link RotationResolverService} is a service that help determine screen rotation for the + * system. When the system wants to resolve rotations, it will send a request to this service + * via {@link #onResolveRotation} interface. A {@link RotationResolverCallback} is + * attached to the request so that the implementer of the rotation resolver service can send + * back results to the system. The system may then decide to rotate the screen based on the + * results. + * + *

If RotationResolverService provides the result in time, the system will respect that result + * and rotate the screen if possible. + * + *

The system's default RotationResolverService implementation is configured at + * the {@code config_defaultRotationResolverService} field in the config XML file. + * + *

The implementation of RotationResolverService must have the following service interface. + * Also, it must have permission {@link android.Manifest.permission#BIND_ROTATION_RESOLVER_SERVICE}. + * + *

+ * {@literal
+ * 
+ * }
+ * 
+ * + * @hide + */ +@SystemApi +public abstract class RotationResolverService extends Service { + /** + * The {@link Intent} that must be declared as handled by the service. + * To be supported, the service must also require the + * {@link android.Manifest.permission#BIND_ROTATION_RESOLVER_SERVICE} permission so + * that other applications can not abuse it. + */ + public static final String SERVICE_INTERFACE = + "android.service.rotationresolver.RotationResolverService"; + + /** Request has been cancelled. */ + public static final int ROTATION_RESULT_FAILURE_CANCELLED = 0; + + /** Request timed out. */ + public static final int ROTATION_RESULT_FAILURE_TIMED_OUT = 1; + + /** Preempted by other requests. */ + public static final int ROTATION_RESULT_FAILURE_PREEMPTED = 2; + + /** Unknown reasons for failing to fulfill the request. */ + public static final int ROTATION_RESULT_FAILURE_UNKNOWN = 3; + + /** Does not support rotation query at this moment. */ + public static final int ROTATION_RESULT_FAILURE_NOT_SUPPORTED = 4; + + /** + * Result codes explaining why rotation recommendation request was not successful. + * + * @hide + */ + @IntDef(prefix = {"ROTATION_RESULT_FAILURE_"}, value = { + ROTATION_RESULT_FAILURE_CANCELLED, + ROTATION_RESULT_FAILURE_TIMED_OUT, ROTATION_RESULT_FAILURE_PREEMPTED, + ROTATION_RESULT_FAILURE_UNKNOWN, + ROTATION_RESULT_FAILURE_NOT_SUPPORTED}) + @Retention(RetentionPolicy.SOURCE) + public @interface FailureCodes { + } + + private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper(), null, true); + @Nullable + private RotationResolverCallbackWrapper mPendingCallback; + @Nullable + private CancellationSignal mCancellationSignal; + + @Nullable + @Override + public final IBinder onBind(@NonNull Intent intent) { + if (SERVICE_INTERFACE.equals(intent.getAction())) { + return new IRotationResolverService.Stub() { + /** {@inheritDoc} */ + @Override + public void resolveRotation(IRotationResolverCallback callback, + RotationResolutionRequest request) throws RemoteException { + Objects.requireNonNull(callback); + Objects.requireNonNull(request); + final ICancellationSignal transport = CancellationSignal.createTransport(); + callback.onCancellable(transport); + mMainThreadHandler.sendMessage( + obtainMessage(RotationResolverService::resolveRotation, + RotationResolverService.this, callback, request, transport)); + } + }; + } + return null; + } + + @MainThread + private void resolveRotation(IRotationResolverCallback callback, + RotationResolutionRequest request, ICancellationSignal transport) { + // TODO(b/175334753): The current behavior of preempted failures is based on the design we + // had in Smart OS exploration. We should revisit it once we have implemented the whole + // feature and tested on devices. + if (mPendingCallback != null + && (mCancellationSignal == null || !mCancellationSignal.isCanceled())) { + reportFailures(callback, ROTATION_RESULT_FAILURE_PREEMPTED); + return; + } + mPendingCallback = new RotationResolverCallbackWrapper(callback, this); + mCancellationSignal = CancellationSignal.fromTransport(transport); + try { + onResolveRotation(request, mCancellationSignal, mPendingCallback); + } catch (UnsupportedOperationException e) { + reportFailures(callback, ROTATION_RESULT_FAILURE_CANCELLED); + } + } + + @MainThread + private void sendRotationResult(IRotationResolverCallback internalCallback, int result) { + if (mPendingCallback != null && mPendingCallback.mCallback == internalCallback) { + mPendingCallback = null; + try { + internalCallback.onSuccess(result); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + } + + @MainThread + private void sendFailureResult(IRotationResolverCallback internalCallback, int error) { + if (mPendingCallback != null && internalCallback == mPendingCallback.mCallback) { + reportFailures(internalCallback, error); + mPendingCallback = null; + } + } + + @MainThread + private void reportFailures(IRotationResolverCallback callback, int error) { + try { + callback.onFailure(error); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + + /** + * Gets called when the system requests to resolve the screen rotation. The implementer then + * should return the result via the provided callback. + * + * @param request A request instance that contains information from the system that may help + * the implementer provide a better result. + * @param cancellationSignal The signal for observing the cancellation of the request. The + * system will use this to notify the implementer that the rotation + * result is no longer needed. Implementer should then stop handling + * the request in order to save resources. + * @param callback A callback that Receives the rotation results. + */ + public abstract void onResolveRotation(@NonNull RotationResolutionRequest request, + @Nullable CancellationSignal cancellationSignal, + @NonNull RotationResolverCallback callback); + + /** + * Interface definition for a callback to be invoked when rotation resolution request is + * completed. + */ + public interface RotationResolverCallback { + /** + * Signals a success and provides the result code. + */ + void onSuccess(@Surface.Rotation int result); + + /** + * Signals a failure and provides the error code. + */ + void onFailure(@FailureCodes int error); + } + + + /** + * An implementation of the callback that receives rotation resolution results. + * + * @hide + */ + public static final class RotationResolverCallbackWrapper implements RotationResolverCallback { + + @NonNull + private final android.service.rotationresolver.IRotationResolverCallback mCallback; + @NonNull + private final RotationResolverService mService; + @NonNull + private final Handler mHandler; + + private RotationResolverCallbackWrapper( + @NonNull android.service.rotationresolver.IRotationResolverCallback callback, + RotationResolverService service) { + mCallback = callback; + mService = service; + mHandler = service.mMainThreadHandler; + Objects.requireNonNull(mHandler); + } + + + @Override + public void onSuccess(int result) { + mHandler.sendMessage( + obtainMessage(RotationResolverService::sendRotationResult, mService, mCallback, + result)); + } + + @Override + public void onFailure(int error) { + mHandler.sendMessage( + obtainMessage(RotationResolverService::sendFailureResult, mService, + mCallback, + error)); + } + } +} diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 910f1607b2d29..acba415c2025b 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3568,6 +3568,15 @@ android:protectionLevel="signature" /> + + + + + + + + +