Merge "Check Settings.Global before sysprop in FeatureFlagUtils."
diff --git a/Android.mk b/Android.mk
index b847425..24e717d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -79,6 +79,7 @@
core/java/android/app/IAlarmManager.aidl \
core/java/android/app/IAppTask.aidl \
core/java/android/app/IApplicationThread.aidl \
+ core/java/android/app/IAssistDataReceiver.aidl \
core/java/android/app/ITaskStackListener.aidl \
core/java/android/app/IBackupAgent.aidl \
core/java/android/app/IEphemeralResolver.aidl \
@@ -168,7 +169,6 @@
core/java/android/content/pm/IPackageDataObserver.aidl \
core/java/android/content/pm/IPackageDeleteObserver.aidl \
core/java/android/content/pm/IPackageDeleteObserver2.aidl \
- core/java/android/content/pm/IPackageInstallObserver.aidl \
core/java/android/content/pm/IPackageInstallObserver2.aidl \
core/java/android/content/pm/IPackageInstaller.aidl \
core/java/android/content/pm/IPackageInstallerCallback.aidl \
@@ -383,7 +383,6 @@
core/java/android/speech/tts/ITextToSpeechService.aidl \
core/java/com/android/internal/app/IAppOpsCallback.aidl \
core/java/com/android/internal/app/IAppOpsService.aidl \
- core/java/com/android/internal/app/IAssistDataReceiver.aidl \
core/java/com/android/internal/app/IBatteryStats.aidl \
core/java/com/android/internal/app/ISoundTriggerService.aidl \
core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl \
@@ -638,6 +637,7 @@
framework-protos \
android.hidl.base-V1.0-java \
android.hardware.cas-V1.0-java \
+ android.hardware.contexthub-V1.0-java \
android.hardware.health-V1.0-java-constants \
android.hardware.thermal-V1.0-java-constants \
android.hardware.tv.input-V1.0-java-constants \
@@ -931,7 +931,7 @@
../opt/net/voip/src/java/android/net/sip
framework_base_android_test_mock_src_files := \
- $(call all-java-files-under, test-runner/src/android/test/mock)
+ $(call all-java-files-under, test-mock/src/android/test/mock)
framework_base_android_test_runner_excluding_mock_src_files := \
$(filter-out $(framework_base_android_test_mock_src_files), $(call all-java-files-under, test-runner/src))
diff --git a/apct-tests/perftests/core/src/android/os/ParcelPerfTest.java b/apct-tests/perftests/core/src/android/os/ParcelPerfTest.java
index a92597f..6e4c9c5 100644
--- a/apct-tests/perftests/core/src/android/os/ParcelPerfTest.java
+++ b/apct-tests/perftests/core/src/android/os/ParcelPerfTest.java
@@ -27,6 +27,10 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
@RunWith(AndroidJUnit4.class)
@LargeTest
public class ParcelPerfTest {
@@ -167,4 +171,80 @@
Parcel.obtain().recycle();
}
}
+
+ @Test
+ public void timeWriteException() {
+ timeWriteException(false);
+ }
+
+ @Test
+ public void timeWriteExceptionWithStackTraceParceling() {
+ timeWriteException(true);
+ }
+
+ @Test
+ public void timeReadException() {
+ timeReadException(false);
+ }
+
+ @Test
+ public void timeReadExceptionWithStackTraceParceling() {
+ timeReadException(true);
+ }
+
+ private void timeWriteException(boolean enableParceling) {
+ if (enableParceling) {
+ Parcel.setStackTraceParceling(true);
+ }
+ try {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ Parcel p = Parcel.obtain();
+ SecurityException e = new SecurityException("TestMessage");
+ while (state.keepRunning()) {
+ p.setDataPosition(0);
+ p.writeException(e);
+ }
+ } finally {
+ if (enableParceling) {
+ Parcel.setStackTraceParceling(false);
+ }
+ }
+ }
+
+ private void timeReadException(boolean enableParceling) {
+ if (enableParceling) {
+ Parcel.setStackTraceParceling(true);
+ }
+ try {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ Parcel p = Parcel.obtain();
+ String msg = "TestMessage";
+ p.writeException(new SecurityException(msg));
+ p.setDataPosition(0);
+ // First verify that remote cause is set (if parceling is enabled)
+ try {
+ p.readException();
+ } catch (SecurityException e) {
+ assertEquals(e.getMessage(), msg);
+ if (enableParceling) {
+ assertTrue(e.getCause() instanceof RemoteException);
+ } else {
+ assertNull(e.getCause());
+ }
+ }
+
+ while (state.keepRunning()) {
+ p.setDataPosition(0);
+ try {
+ p.readException();
+ } catch (SecurityException expected) {
+ }
+ }
+ } finally {
+ if (enableParceling) {
+ Parcel.setStackTraceParceling(false);
+ }
+ }
+ }
+
}
diff --git a/api/current.txt b/api/current.txt
index a1b9596..b1ca3e8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -38624,7 +38624,6 @@
method public static void remove(java.lang.String) throws android.system.ErrnoException;
method public static void removexattr(java.lang.String, java.lang.String) throws android.system.ErrnoException;
method public static void rename(java.lang.String, java.lang.String) throws android.system.ErrnoException;
- method public static deprecated long sendfile(java.io.FileDescriptor, java.io.FileDescriptor, android.util.MutableLong, long) throws android.system.ErrnoException;
method public static long sendfile(java.io.FileDescriptor, java.io.FileDescriptor, android.system.Int64Ref, long) throws android.system.ErrnoException;
method public static int sendto(java.io.FileDescriptor, java.nio.ByteBuffer, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
method public static int sendto(java.io.FileDescriptor, byte[], int, int, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
@@ -38650,7 +38649,6 @@
method public static int umask(int);
method public static android.system.StructUtsname uname();
method public static void unsetenv(java.lang.String) throws android.system.ErrnoException;
- method public static deprecated int waitpid(int, android.util.MutableInt, int) throws android.system.ErrnoException;
method public static int waitpid(int, android.system.Int32Ref, int) throws android.system.ErrnoException;
method public static int write(java.io.FileDescriptor, java.nio.ByteBuffer) throws android.system.ErrnoException, java.io.InterruptedIOException;
method public static int write(java.io.FileDescriptor, byte[], int, int) throws android.system.ErrnoException, java.io.InterruptedIOException;
@@ -39227,6 +39225,7 @@
method public android.telecom.Call.RttCall getRttCall();
method public int getState();
method public android.telecom.InCallService.VideoCall getVideoCall();
+ method public void handoverTo(android.telecom.PhoneAccountHandle, int, android.os.Bundle);
method public void hold();
method public boolean isRttActive();
method public void mergeConference();
@@ -39271,6 +39270,8 @@
method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
+ method public void onHandoverComplete(android.telecom.Call);
+ method public void onHandoverFailed(android.telecom.Call, int);
method public void onParentChanged(android.telecom.Call, android.telecom.Call);
method public void onPostDialWait(android.telecom.Call, java.lang.String);
method public void onRttInitiationFailure(android.telecom.Call, int);
@@ -39279,6 +39280,10 @@
method public void onRttStatusChanged(android.telecom.Call, boolean, android.telecom.Call.RttCall);
method public void onStateChanged(android.telecom.Call, int);
method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
+ field public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1; // 0x1
+ field public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3; // 0x3
+ field public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2; // 0x2
+ field public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4; // 0x4
}
public static class Call.Details {
@@ -39613,8 +39618,11 @@
method public void onConference(android.telecom.Connection, android.telecom.Connection);
method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+ method public android.telecom.Connection onCreateIncomingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public void onCreateOutgoingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+ method public android.telecom.Connection onCreateOutgoingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+ method public void onHandoverFailed(android.telecom.ConnectionRequest, int);
method public void onRemoteConferenceAdded(android.telecom.RemoteConference);
method public void onRemoteExistingConnectionAdded(android.telecom.RemoteConnection);
field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService";
@@ -39737,6 +39745,9 @@
field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR;
field public static final java.lang.String EXTRA_CALL_SUBJECT_CHARACTER_ENCODING = "android.telecom.extra.CALL_SUBJECT_CHARACTER_ENCODING";
field public static final java.lang.String EXTRA_CALL_SUBJECT_MAX_LENGTH = "android.telecom.extra.CALL_SUBJECT_MAX_LENGTH";
+ field public static final java.lang.String EXTRA_LOG_SELF_MANAGED_CALLS = "android.telecom.extra.LOG_SELF_MANAGED_CALLS";
+ field public static final java.lang.String EXTRA_SUPPORTS_HANDOVER_FROM = "android.telecom.extra.SUPPORTS_HANDOVER_FROM";
+ field public static final java.lang.String EXTRA_SUPPORTS_HANDOVER_TO = "android.telecom.extra.SUPPORTS_HANDOVER_TO";
field public static final int NO_HIGHLIGHT_COLOR = 0; // 0x0
field public static final int NO_RESOURCE_ID = -1; // 0xffffffff
field public static final java.lang.String SCHEME_SIP = "sip";
@@ -39897,6 +39908,7 @@
}
public class TelecomManager {
+ method public void acceptHandover(android.net.Uri, int, android.telecom.PhoneAccountHandle);
method public void acceptRingingCall();
method public void acceptRingingCall(int);
method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
@@ -46073,6 +46085,7 @@
method public void addExtraDataToAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
method public void addFocusables(java.util.ArrayList<android.view.View>, int);
method public void addFocusables(java.util.ArrayList<android.view.View>, int, int);
+ method public void addKeyFallbackListener(android.view.View.OnKeyFallbackListener);
method public void addKeyboardNavigationClusters(java.util.Collection<android.view.View>, int);
method public void addOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
method public void addOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
@@ -46407,6 +46420,7 @@
method public void onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public void onInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo);
method public boolean onKeyDown(int, android.view.KeyEvent);
+ method public boolean onKeyFallback(android.view.KeyEvent);
method public boolean onKeyLongPress(int, android.view.KeyEvent);
method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
method public boolean onKeyPreIme(int, android.view.KeyEvent);
@@ -46460,6 +46474,7 @@
method public void refreshDrawableState();
method public void releasePointerCapture();
method public boolean removeCallbacks(java.lang.Runnable);
+ method public void removeKeyFallbackListener(android.view.View.OnKeyFallbackListener);
method public void removeOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
method public void removeOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
method public void requestApplyInsets();
@@ -46878,6 +46893,10 @@
method public abstract boolean onHover(android.view.View, android.view.MotionEvent);
}
+ public static abstract interface View.OnKeyFallbackListener {
+ method public abstract boolean onKeyFallback(android.view.View, android.view.KeyEvent);
+ }
+
public static abstract interface View.OnKeyListener {
method public abstract boolean onKey(android.view.View, int, android.view.KeyEvent);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index d4656ac..592bd3d 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -41928,7 +41928,6 @@
method public static void remove(java.lang.String) throws android.system.ErrnoException;
method public static void removexattr(java.lang.String, java.lang.String) throws android.system.ErrnoException;
method public static void rename(java.lang.String, java.lang.String) throws android.system.ErrnoException;
- method public static deprecated long sendfile(java.io.FileDescriptor, java.io.FileDescriptor, android.util.MutableLong, long) throws android.system.ErrnoException;
method public static long sendfile(java.io.FileDescriptor, java.io.FileDescriptor, android.system.Int64Ref, long) throws android.system.ErrnoException;
method public static int sendto(java.io.FileDescriptor, java.nio.ByteBuffer, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
method public static int sendto(java.io.FileDescriptor, byte[], int, int, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
@@ -41954,7 +41953,6 @@
method public static int umask(int);
method public static android.system.StructUtsname uname();
method public static void unsetenv(java.lang.String) throws android.system.ErrnoException;
- method public static deprecated int waitpid(int, android.util.MutableInt, int) throws android.system.ErrnoException;
method public static int waitpid(int, android.system.Int32Ref, int) throws android.system.ErrnoException;
method public static int write(java.io.FileDescriptor, java.nio.ByteBuffer) throws android.system.ErrnoException, java.io.InterruptedIOException;
method public static int write(java.io.FileDescriptor, byte[], int, int) throws android.system.ErrnoException, java.io.InterruptedIOException;
@@ -42550,6 +42548,7 @@
method public android.telecom.Call.RttCall getRttCall();
method public int getState();
method public android.telecom.InCallService.VideoCall getVideoCall();
+ method public void handoverTo(android.telecom.PhoneAccountHandle, int, android.os.Bundle);
method public void hold();
method public boolean isRttActive();
method public void mergeConference();
@@ -42596,6 +42595,8 @@
method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
+ method public void onHandoverComplete(android.telecom.Call);
+ method public void onHandoverFailed(android.telecom.Call, int);
method public void onParentChanged(android.telecom.Call, android.telecom.Call);
method public void onPostDialWait(android.telecom.Call, java.lang.String);
method public void onRttInitiationFailure(android.telecom.Call, int);
@@ -42604,6 +42605,10 @@
method public void onRttStatusChanged(android.telecom.Call, boolean, android.telecom.Call.RttCall);
method public void onStateChanged(android.telecom.Call, int);
method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
+ field public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1; // 0x1
+ field public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3; // 0x3
+ field public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2; // 0x2
+ field public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4; // 0x4
}
public static class Call.Details {
@@ -42949,8 +42954,11 @@
method public void onConference(android.telecom.Connection, android.telecom.Connection);
method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+ method public android.telecom.Connection onCreateIncomingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public void onCreateOutgoingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+ method public android.telecom.Connection onCreateOutgoingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+ method public void onHandoverFailed(android.telecom.ConnectionRequest, int);
method public void onRemoteConferenceAdded(android.telecom.RemoteConference);
method public void onRemoteExistingConnectionAdded(android.telecom.RemoteConnection);
field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService";
@@ -43198,6 +43206,9 @@
field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR;
field public static final java.lang.String EXTRA_CALL_SUBJECT_CHARACTER_ENCODING = "android.telecom.extra.CALL_SUBJECT_CHARACTER_ENCODING";
field public static final java.lang.String EXTRA_CALL_SUBJECT_MAX_LENGTH = "android.telecom.extra.CALL_SUBJECT_MAX_LENGTH";
+ field public static final java.lang.String EXTRA_LOG_SELF_MANAGED_CALLS = "android.telecom.extra.LOG_SELF_MANAGED_CALLS";
+ field public static final java.lang.String EXTRA_SUPPORTS_HANDOVER_FROM = "android.telecom.extra.SUPPORTS_HANDOVER_FROM";
+ field public static final java.lang.String EXTRA_SUPPORTS_HANDOVER_TO = "android.telecom.extra.SUPPORTS_HANDOVER_TO";
field public static final int NO_HIGHLIGHT_COLOR = 0; // 0x0
field public static final int NO_RESOURCE_ID = -1; // 0xffffffff
field public static final java.lang.String SCHEME_SIP = "sip";
@@ -43399,6 +43410,7 @@
}
public class TelecomManager {
+ method public void acceptHandover(android.net.Uri, int, android.telecom.PhoneAccountHandle);
method public void acceptRingingCall();
method public void acceptRingingCall(int);
method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
@@ -49818,6 +49830,7 @@
method public void addExtraDataToAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
method public void addFocusables(java.util.ArrayList<android.view.View>, int);
method public void addFocusables(java.util.ArrayList<android.view.View>, int, int);
+ method public void addKeyFallbackListener(android.view.View.OnKeyFallbackListener);
method public void addKeyboardNavigationClusters(java.util.Collection<android.view.View>, int);
method public void addOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
method public void addOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
@@ -50152,6 +50165,7 @@
method public void onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public void onInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo);
method public boolean onKeyDown(int, android.view.KeyEvent);
+ method public boolean onKeyFallback(android.view.KeyEvent);
method public boolean onKeyLongPress(int, android.view.KeyEvent);
method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
method public boolean onKeyPreIme(int, android.view.KeyEvent);
@@ -50205,6 +50219,7 @@
method public void refreshDrawableState();
method public void releasePointerCapture();
method public boolean removeCallbacks(java.lang.Runnable);
+ method public void removeKeyFallbackListener(android.view.View.OnKeyFallbackListener);
method public void removeOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
method public void removeOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
method public void requestApplyInsets();
@@ -50623,6 +50638,10 @@
method public abstract boolean onHover(android.view.View, android.view.MotionEvent);
}
+ public static abstract interface View.OnKeyFallbackListener {
+ method public abstract boolean onKeyFallback(android.view.View, android.view.KeyEvent);
+ }
+
public static abstract interface View.OnKeyListener {
method public abstract boolean onKey(android.view.View, int, android.view.KeyEvent);
}
diff --git a/api/test-current.txt b/api/test-current.txt
index ffcdeae..98615ee 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -38156,6 +38156,7 @@
public abstract class ConditionProviderService extends android.app.Service {
ctor public ConditionProviderService();
+ method public boolean isBound();
method public final void notifyCondition(android.service.notification.Condition);
method public final void notifyConditions(android.service.notification.Condition...);
method public android.os.IBinder onBind(android.content.Intent);
@@ -39014,7 +39015,6 @@
method public static void remove(java.lang.String) throws android.system.ErrnoException;
method public static void removexattr(java.lang.String, java.lang.String) throws android.system.ErrnoException;
method public static void rename(java.lang.String, java.lang.String) throws android.system.ErrnoException;
- method public static deprecated long sendfile(java.io.FileDescriptor, java.io.FileDescriptor, android.util.MutableLong, long) throws android.system.ErrnoException;
method public static long sendfile(java.io.FileDescriptor, java.io.FileDescriptor, android.system.Int64Ref, long) throws android.system.ErrnoException;
method public static int sendto(java.io.FileDescriptor, java.nio.ByteBuffer, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
method public static int sendto(java.io.FileDescriptor, byte[], int, int, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
@@ -39040,7 +39040,6 @@
method public static int umask(int);
method public static android.system.StructUtsname uname();
method public static void unsetenv(java.lang.String) throws android.system.ErrnoException;
- method public static deprecated int waitpid(int, android.util.MutableInt, int) throws android.system.ErrnoException;
method public static int waitpid(int, android.system.Int32Ref, int) throws android.system.ErrnoException;
method public static int write(java.io.FileDescriptor, java.nio.ByteBuffer) throws android.system.ErrnoException, java.io.InterruptedIOException;
method public static int write(java.io.FileDescriptor, byte[], int, int) throws android.system.ErrnoException, java.io.InterruptedIOException;
@@ -39617,6 +39616,7 @@
method public android.telecom.Call.RttCall getRttCall();
method public int getState();
method public android.telecom.InCallService.VideoCall getVideoCall();
+ method public void handoverTo(android.telecom.PhoneAccountHandle, int, android.os.Bundle);
method public void hold();
method public boolean isRttActive();
method public void mergeConference();
@@ -39661,6 +39661,8 @@
method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
+ method public void onHandoverComplete(android.telecom.Call);
+ method public void onHandoverFailed(android.telecom.Call, int);
method public void onParentChanged(android.telecom.Call, android.telecom.Call);
method public void onPostDialWait(android.telecom.Call, java.lang.String);
method public void onRttInitiationFailure(android.telecom.Call, int);
@@ -39669,6 +39671,10 @@
method public void onRttStatusChanged(android.telecom.Call, boolean, android.telecom.Call.RttCall);
method public void onStateChanged(android.telecom.Call, int);
method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
+ field public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1; // 0x1
+ field public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3; // 0x3
+ field public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2; // 0x2
+ field public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4; // 0x4
}
public static class Call.Details {
@@ -40019,8 +40025,11 @@
method public void onConference(android.telecom.Connection, android.telecom.Connection);
method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+ method public android.telecom.Connection onCreateIncomingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public void onCreateOutgoingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+ method public android.telecom.Connection onCreateOutgoingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+ method public void onHandoverFailed(android.telecom.ConnectionRequest, int);
method public void onRemoteConferenceAdded(android.telecom.RemoteConference);
method public void onRemoteExistingConnectionAdded(android.telecom.RemoteConnection);
field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService";
@@ -40143,6 +40152,9 @@
field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR;
field public static final java.lang.String EXTRA_CALL_SUBJECT_CHARACTER_ENCODING = "android.telecom.extra.CALL_SUBJECT_CHARACTER_ENCODING";
field public static final java.lang.String EXTRA_CALL_SUBJECT_MAX_LENGTH = "android.telecom.extra.CALL_SUBJECT_MAX_LENGTH";
+ field public static final java.lang.String EXTRA_LOG_SELF_MANAGED_CALLS = "android.telecom.extra.LOG_SELF_MANAGED_CALLS";
+ field public static final java.lang.String EXTRA_SUPPORTS_HANDOVER_FROM = "android.telecom.extra.SUPPORTS_HANDOVER_FROM";
+ field public static final java.lang.String EXTRA_SUPPORTS_HANDOVER_TO = "android.telecom.extra.SUPPORTS_HANDOVER_TO";
field public static final int NO_HIGHLIGHT_COLOR = 0; // 0x0
field public static final int NO_RESOURCE_ID = -1; // 0xffffffff
field public static final java.lang.String SCHEME_SIP = "sip";
@@ -40303,6 +40315,7 @@
}
public class TelecomManager {
+ method public void acceptHandover(android.net.Uri, int, android.telecom.PhoneAccountHandle);
method public void acceptRingingCall();
method public void acceptRingingCall(int);
method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
@@ -46729,6 +46742,7 @@
method public void addExtraDataToAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
method public void addFocusables(java.util.ArrayList<android.view.View>, int);
method public void addFocusables(java.util.ArrayList<android.view.View>, int, int);
+ method public void addKeyFallbackListener(android.view.View.OnKeyFallbackListener);
method public void addKeyboardNavigationClusters(java.util.Collection<android.view.View>, int);
method public void addOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
method public void addOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
@@ -47065,6 +47079,7 @@
method public void onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public void onInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo);
method public boolean onKeyDown(int, android.view.KeyEvent);
+ method public boolean onKeyFallback(android.view.KeyEvent);
method public boolean onKeyLongPress(int, android.view.KeyEvent);
method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
method public boolean onKeyPreIme(int, android.view.KeyEvent);
@@ -47118,6 +47133,7 @@
method public void refreshDrawableState();
method public void releasePointerCapture();
method public boolean removeCallbacks(java.lang.Runnable);
+ method public void removeKeyFallbackListener(android.view.View.OnKeyFallbackListener);
method public void removeOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
method public void removeOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
method public void requestApplyInsets();
@@ -47540,6 +47556,10 @@
method public abstract boolean onHover(android.view.View, android.view.MotionEvent);
}
+ public static abstract interface View.OnKeyFallbackListener {
+ method public abstract boolean onKeyFallback(android.view.View, android.view.KeyEvent);
+ }
+
public static abstract interface View.OnKeyListener {
method public abstract boolean onKey(android.view.View, int, android.view.KeyEvent);
}
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 07b1c5c..8bc776f 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
#define DEBUG true
#include "Log.h"
+#include "android-base/stringprintf.h"
#include "StatsService.h"
#include "config/ConfigKey.h"
#include "config/ConfigManager.h"
@@ -25,11 +26,11 @@
#include <android-base/file.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
+#include <dirent.h>
#include <frameworks/base/cmds/statsd/src/statsd_config.pb.h>
#include <private/android_filesystem_config.h>
#include <utils/Looper.h>
#include <utils/String16.h>
-
#include <stdio.h>
#include <stdlib.h>
#include <sys/system_properties.h>
@@ -42,6 +43,7 @@
namespace statsd {
constexpr const char* kPermissionDump = "android.permission.DUMP";
+#define STATS_SERVICE_DIR "/data/system/stats-service"
// ======================================================================
/**
@@ -206,6 +208,10 @@
if (!args[0].compare(String8("send-broadcast"))) {
return cmd_trigger_broadcast(args);
}
+
+ if (!args[0].compare(String8("clear-config"))) {
+ return cmd_remove_config_files(out);
+ }
}
print_cmd_help(out);
@@ -223,6 +229,11 @@
fprintf(out, " Prints the UID, app name, version mapping.\n");
fprintf(out, "\n");
fprintf(out, "\n");
+ fprintf(out, "usage: adb shell cmd stats clear-config \n");
+ fprintf(out, "\n");
+ fprintf(out, " Removes all configs from disk.\n");
+ fprintf(out, "\n");
+ fprintf(out, "\n");
fprintf(out, "usage: adb shell cmds stats pull-source [int] \n");
fprintf(out, "\n");
fprintf(out, " Prints the output of a pulled metrics source (int indicates source)\n");
@@ -405,6 +416,27 @@
return UNKNOWN_ERROR;
}
+status_t StatsService::cmd_remove_config_files(FILE* out) {
+ fprintf(out, "Trying to remove config files...\n");
+ unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR), closedir);
+ if (dir == NULL) {
+ fprintf(out, "No existing config files found exiting...\n");
+ return NO_ERROR;
+ }
+
+ dirent* de;
+ while ((de = readdir(dir.get()))) {
+ char* name = de->d_name;
+ if (name[0] == '.') continue;
+ string file_name = StringPrintf("%s/%s", STATS_SERVICE_DIR, name);
+ fprintf(out, "Deleting file %s\n", file_name.c_str());
+ if (remove(file_name.c_str())) {
+ fprintf(out, "Error deleting file %s\n", file_name.c_str());
+ }
+ }
+ return NO_ERROR;
+}
+
Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int32_t>& version,
const vector<String16>& app) {
if (DEBUG) ALOGD("StatsService::informAllUidData was called");
@@ -543,9 +575,7 @@
Status StatsService::getData(const String16& key, vector<uint8_t>* output) {
IPCThreadState* ipc = IPCThreadState::self();
- if (checkCallingPermission(String16(kPermissionDump),
- reinterpret_cast<int32_t*>(ipc->getCallingPid()),
- reinterpret_cast<int32_t*>(ipc->getCallingUid()))) {
+ if (checkCallingPermission(String16(kPermissionDump))) {
// TODO: Implement this.
return Status::ok();
} else {
@@ -559,8 +589,7 @@
bool* success) {
IPCThreadState* ipc = IPCThreadState::self();
int32_t* uid = reinterpret_cast<int32_t*>(ipc->getCallingUid());
- if (checkCallingPermission(String16(kPermissionDump),
- reinterpret_cast<int32_t*>(ipc->getCallingPid()), uid)) {
+ if (checkCallingPermission(String16(kPermissionDump))) {
string keyString = string(String8(key).string());
ConfigKey configKey(*uid, keyString);
StatsdConfig cfg;
@@ -577,9 +606,7 @@
Status StatsService::removeConfiguration(const String16& key, bool* success) {
IPCThreadState* ipc = IPCThreadState::self();
- if (checkCallingPermission(String16(kPermissionDump),
- reinterpret_cast<int32_t*>(ipc->getCallingPid()),
- reinterpret_cast<int32_t*>(ipc->getCallingUid()))) {
+ if (checkCallingPermission(String16(kPermissionDump))) {
// TODO: Implement this.
return Status::ok();
} else {
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index fba8af7..0163f94 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -152,6 +152,11 @@
status_t cmd_print_pulled_metrics(FILE* out, const Vector<String8>& args);
/**
+ * Removes all configs stored on disk.
+ */
+ status_t cmd_remove_config_files(FILE* out);
+
+ /**
* Update a configuration.
*/
void set_config(int uid, const string& name, const StatsdConfig& config);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 48b85c9..ba93feb 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -102,8 +102,7 @@
/*
* *****************************************************************************
- * Below are all of the individual atoms that are logged by Android via statsd
- * and Westworld.
+ * Below are all of the individual atoms that are logged by Android via statsd.
*
* RULES:
* - The field ids for each atom must start at 1, and count upwards by 1.
diff --git a/cmds/statsd/src/atoms_copy.proto b/cmds/statsd/src/atoms_copy.proto
index 598c2bc..58e225a 100644
--- a/cmds/statsd/src/atoms_copy.proto
+++ b/cmds/statsd/src/atoms_copy.proto
@@ -104,8 +104,7 @@
/*
* *****************************************************************************
- * Below are all of the individual atoms that are logged by Android via statsd
- * and Westworld.
+ * Below are all of the individual atoms that are logged by Android via statsd.
*
* RULES:
* - The field ids for each atom must start at 1, and count upwards by 1.
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
index a694dbf..60060fe 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
@@ -206,7 +206,7 @@
vector<bool>& conditionChangedCache) {
if (conditionCache[mIndex] != ConditionState::kNotEvaluated) {
// it has been evaluated.
- VLOG("Yes, already evaluated, %s %d", mName.c_str(), mNonSlicedConditionState);
+ VLOG("Yes, already evaluated, %s %d", mName.c_str(), conditionCache[mIndex]);
return;
}
@@ -230,8 +230,23 @@
}
if (matchedState < 0) {
+ // The event doesn't match this condition. So we just report existing condition values.
conditionChangedCache[mIndex] = false;
- conditionCache[mIndex] = mNonSlicedConditionState;
+ if (mSliced) {
+ // if the condition result is sliced. metrics won't directly get value from the
+ // cache, so just set any value other than kNotEvaluated.
+ conditionCache[mIndex] = ConditionState::kUnknown;
+ } else if (mSlicedConditionState.find(DEFAULT_DIMENSION_KEY) ==
+ mSlicedConditionState.end()) {
+ // condition not sliced, but we haven't seen the matched start or stop yet. so return
+ // initial value.
+ conditionCache[mIndex] = mInitialValue;
+ } else {
+ // return the cached condition.
+ conditionCache[mIndex] = mSlicedConditionState[DEFAULT_DIMENSION_KEY] > 0
+ ? ConditionState::kTrue
+ : ConditionState::kFalse;
+ }
return;
}
diff --git a/cmds/statsd/src/config/ConfigKey.h b/cmds/statsd/src/config/ConfigKey.h
index bbf20fd..3489c43 100644
--- a/cmds/statsd/src/config/ConfigKey.h
+++ b/cmds/statsd/src/config/ConfigKey.h
@@ -78,7 +78,7 @@
/**
* A hash function for ConfigKey so it can be used for unordered_map/set.
- * Unfortunately this hast to go in std namespace because C++ is fun!
+ * Unfortunately this has to go in std namespace because C++ is fun!
*/
namespace std {
diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp
index 6e8ed77..3319f6d 100644
--- a/cmds/statsd/src/config/ConfigManager.cpp
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -18,16 +18,23 @@
#include "stats_util.h"
-#include <vector>
-
+#include <android-base/file.h>
+#include <dirent.h>
#include <stdio.h>
+#include <vector>
+#include "android-base/stringprintf.h"
namespace android {
namespace os {
namespace statsd {
+#define STATS_SERVICE_DIR "/data/system/stats-service"
+
static StatsdConfig build_fake_config();
+using android::base::StringPrintf;
+using std::unique_ptr;
+
ConfigManager::ConfigManager() {
}
@@ -35,11 +42,10 @@
}
void ConfigManager::Startup() {
- // TODO: Implement me -- read from storage and call onto all of the listeners.
- // Instead, we'll just make a fake one.
+ readConfigFromDisk();
// this should be called from StatsService when it receives a statsd_config
- UpdateConfig(ConfigKey(0, "fake"), build_fake_config());
+ UpdateConfig(ConfigKey(1000, "fake"), build_fake_config());
}
void ConfigManager::AddListener(const sp<ConfigListener>& listener) {
@@ -52,7 +58,7 @@
// Why doesn't this work? mConfigs.insert({key, config});
// Save to disk
- update_saved_configs();
+ update_saved_configs(key, config);
// Tell everyone
for (auto& listener : mListeners) {
@@ -74,8 +80,8 @@
// Remove from map
mConfigs.erase(it);
- // Save to disk
- update_saved_configs();
+ // Remove from disk
+ remove_saved_configs(key);
// Tell everyone
for (auto& listener : mListeners) {
@@ -85,6 +91,26 @@
// If we didn't find it, just quietly ignore it.
}
+void ConfigManager::remove_saved_configs(const ConfigKey& key) {
+ unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR), closedir);
+ if (dir == NULL) {
+ ALOGD("no default config on disk");
+ return;
+ }
+ string prefix = StringPrintf("%d-%s", key.GetUid(), key.GetName().c_str());
+ dirent* de;
+ while ((de = readdir(dir.get()))) {
+ char* name = de->d_name;
+ if (name[0] != '.' && strncmp(name, prefix.c_str(), prefix.size()) == 0) {
+ if (remove(StringPrintf("%s/%d-%s", STATS_SERVICE_DIR, key.GetUid(),
+ key.GetName().c_str())
+ .c_str()) != 0) {
+ ALOGD("no file found");
+ }
+ }
+ }
+}
+
void ConfigManager::RemoveConfigs(int uid) {
vector<ConfigKey> removed;
@@ -118,8 +144,64 @@
}
}
-void ConfigManager::update_saved_configs() {
- // TODO: Implement me -- write to disk.
+void ConfigManager::readConfigFromDisk() {
+ unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR), closedir);
+ if (dir == NULL) {
+ ALOGD("no default config on disk");
+ return;
+ }
+
+ dirent* de;
+ while ((de = readdir(dir.get()))) {
+ char* name = de->d_name;
+ if (name[0] == '.') continue;
+ ALOGD("file %s", name);
+
+ int index = 0;
+ int uid = 0;
+ string configName;
+ char* substr = strtok(name, "-");
+ // Timestamp lives at index 2 but we skip parsing it as it's not needed.
+ while (substr != nullptr && index < 2) {
+ if (index) {
+ uid = atoi(substr);
+ } else {
+ configName = substr;
+ }
+ index++;
+ }
+ if (index < 2) continue;
+ string file_name = StringPrintf("%s/%s", STATS_SERVICE_DIR, name);
+ ALOGD("full file %s", file_name.c_str());
+ int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC);
+ if (fd != -1) {
+ string content;
+ if (android::base::ReadFdToString(fd, &content)) {
+ StatsdConfig config;
+ if (config.ParseFromString(content)) {
+ mConfigs[ConfigKey(uid, configName)] = config;
+ ALOGD("map key uid=%d|name=%s", uid, name);
+ }
+ }
+ close(fd);
+ }
+ }
+}
+
+void ConfigManager::update_saved_configs(const ConfigKey& key, const StatsdConfig& config) {
+ mkdir(STATS_SERVICE_DIR, S_IRWXU);
+ string file_name = StringPrintf("%s/%d-%s-%ld", STATS_SERVICE_DIR, key.GetUid(),
+ key.GetName().c_str(), time(nullptr));
+ int fd = open(file_name.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR);
+ if (fd != -1) {
+ const int numBytes = config.ByteSize();
+ vector<uint8_t> buffer(numBytes);
+ config.SerializeToArray(&buffer[0], numBytes);
+ int result = write(fd, &buffer[0], numBytes);
+ close(fd);
+ bool wroteKey = (result == numBytes);
+ ALOGD("wrote to file %d", wroteKey);
+ }
}
static StatsdConfig build_fake_config() {
@@ -212,7 +294,7 @@
keyMatcher = durationMetric->add_dimension();
keyMatcher->set_key(WAKE_LOCK_UID_KEY_ID);
durationMetric->set_what("WL_HELD_PER_APP_PER_NAME");
- durationMetric->set_predicate("APP_IS_BACKGROUND_AND_SCREEN_ON");
+ durationMetric->set_condition("APP_IS_BACKGROUND_AND_SCREEN_ON");
link = durationMetric->add_links();
link->set_condition("APP_IS_BACKGROUND");
link->add_key_in_main()->set_key(WAKE_LOCK_UID_KEY_ID);
@@ -226,7 +308,7 @@
keyMatcher = durationMetric->add_dimension();
keyMatcher->set_key(WAKE_LOCK_UID_KEY_ID);
durationMetric->set_what("WL_HELD_PER_APP_PER_NAME");
- durationMetric->set_predicate("APP_IS_BACKGROUND_AND_SCREEN_ON");
+ durationMetric->set_condition("APP_IS_BACKGROUND_AND_SCREEN_ON");
link = durationMetric->add_links();
link->set_condition("APP_IS_BACKGROUND");
link->add_key_in_main()->set_key(WAKE_LOCK_UID_KEY_ID);
@@ -238,7 +320,7 @@
durationMetric->mutable_bucket()->set_bucket_size_millis(30 * 1000L);
durationMetric->set_type(DurationMetric_AggregationType_DURATION_MAX_SPARSE);
durationMetric->set_what("WL_HELD_PER_APP_PER_NAME");
- durationMetric->set_predicate("APP_IS_BACKGROUND_AND_SCREEN_ON");
+ durationMetric->set_condition("APP_IS_BACKGROUND_AND_SCREEN_ON");
link = durationMetric->add_links();
link->set_condition("APP_IS_BACKGROUND");
link->add_key_in_main()->set_key(WAKE_LOCK_UID_KEY_ID);
diff --git a/cmds/statsd/src/config/ConfigManager.h b/cmds/statsd/src/config/ConfigManager.h
index c21247f9..5b612cc 100644
--- a/cmds/statsd/src/config/ConfigManager.h
+++ b/cmds/statsd/src/config/ConfigManager.h
@@ -46,9 +46,7 @@
virtual ~ConfigManager();
/**
- * Call to load the saved configs from disk.
- *
- * TODO: Implement me
+ * Initialize ConfigListener by reading from disk and get updates.
*/
void Startup();
@@ -95,7 +93,12 @@
/**
* Save the configs to disk.
*/
- void update_saved_configs();
+ void update_saved_configs(const ConfigKey& key, const StatsdConfig& config);
+
+ /**
+ * Remove saved configs from disk.
+ */
+ void remove_saved_configs(const ConfigKey& key);
/**
* The Configs that have been set. Each config should
@@ -112,6 +115,11 @@
* The ConfigListeners that will be told about changes.
*/
vector<sp<ConfigListener>> mListeners;
+
+ /**
+ * Call to load the saved configs from disk.
+ */
+ void readConfigFromDisk();
};
} // namespace statsd
diff --git a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
index e004d21..e2745d2 100644
--- a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
+++ b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
@@ -71,10 +71,9 @@
do {
timeMs = std::stoull(pch);
auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID_FREQ_PULLED, timestamp);
- auto elemList = ptr->GetAndroidLogEventList();
- *elemList << uid;
- *elemList << idx;
- *elemList << timeMs;
+ ptr->write(uid);
+ ptr->write(idx);
+ ptr->write(timeMs);
ptr->init();
data->push_back(ptr);
VLOG("uid %lld, freq idx %d, sys time %lld", (long long)uid, idx, (long long)timeMs);
diff --git a/cmds/statsd/src/external/CpuTimePerUidPuller.cpp b/cmds/statsd/src/external/CpuTimePerUidPuller.cpp
index b84b877..e0572dc 100644
--- a/cmds/statsd/src/external/CpuTimePerUidPuller.cpp
+++ b/cmds/statsd/src/external/CpuTimePerUidPuller.cpp
@@ -66,10 +66,9 @@
uint64_t sysTimeMs = std::stoull(pch);
auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID_PULLED, timestamp);
- auto elemList = ptr->GetAndroidLogEventList();
- *elemList << uid;
- *elemList << userTimeMs;
- *elemList << sysTimeMs;
+ ptr->write(uid);
+ ptr->write(userTimeMs);
+ ptr->write(sysTimeMs);
ptr->init();
data->push_back(ptr);
VLOG("uid %lld, user time %lld, sys time %lld", (long long)uid, (long long)userTimeMs, (long long)sysTimeMs);
diff --git a/cmds/statsd/src/external/ResourcePowerManagerPuller.cpp b/cmds/statsd/src/external/ResourcePowerManagerPuller.cpp
index 319feef4..3ee636d 100644
--- a/cmds/statsd/src/external/ResourcePowerManagerPuller.cpp
+++ b/cmds/statsd/src/external/ResourcePowerManagerPuller.cpp
@@ -93,11 +93,10 @@
auto statePtr = make_shared<LogEvent>(
android::util::POWER_STATE_PLATFORM_SLEEP_STATE_PULLED, timestamp);
- auto elemList = statePtr->GetAndroidLogEventList();
- *elemList << state.name;
- *elemList << state.residencyInMsecSinceBoot;
- *elemList << state.totalTransitions;
- *elemList << state.supportedOnlyInSuspend;
+ statePtr->write(state.name);
+ statePtr->write(state.residencyInMsecSinceBoot);
+ statePtr->write(state.totalTransitions);
+ statePtr->write(state.supportedOnlyInSuspend);
statePtr->init();
data->push_back(statePtr);
VLOG("powerstate: %s, %lld, %lld, %d", state.name.c_str(),
@@ -106,11 +105,10 @@
for (auto voter : state.voters) {
auto voterPtr =
make_shared<LogEvent>(android::util::POWER_STATE_VOTER_PULLED, timestamp);
- auto elemList = voterPtr->GetAndroidLogEventList();
- *elemList << state.name;
- *elemList << voter.name;
- *elemList << voter.totalTimeInMsecVotedForSinceBoot;
- *elemList << voter.totalNumberOfTimesVotedSinceBoot;
+ voterPtr->write(state.name);
+ voterPtr->write(voter.name);
+ voterPtr->write(voter.totalTimeInMsecVotedForSinceBoot);
+ voterPtr->write(voter.totalNumberOfTimesVotedSinceBoot);
voterPtr->init();
data->push_back(voterPtr);
VLOG("powerstatevoter: %s, %s, %lld, %lld", state.name.c_str(),
@@ -141,13 +139,12 @@
const PowerStateSubsystemSleepState& state = subsystem.states[j];
auto subsystemStatePtr = make_shared<LogEvent>(
android::util::POWER_STATE_SUBSYSTEM_SLEEP_STATE_PULLED, timestamp);
- auto elemList = subsystemStatePtr->GetAndroidLogEventList();
- *elemList << subsystem.name;
- *elemList << state.name;
- *elemList << state.residencyInMsecSinceBoot;
- *elemList << state.totalTransitions;
- *elemList << state.lastEntryTimestampMs;
- *elemList << state.supportedOnlyInSuspend;
+ subsystemStatePtr->write(subsystem.name);
+ subsystemStatePtr->write(state.name);
+ subsystemStatePtr->write(state.residencyInMsecSinceBoot);
+ subsystemStatePtr->write(state.totalTransitions);
+ subsystemStatePtr->write(state.lastEntryTimestampMs);
+ subsystemStatePtr->write(state.supportedOnlyInSuspend);
subsystemStatePtr->init();
data->push_back(subsystemStatePtr);
VLOG("subsystemstate: %s, %s, %lld, %lld, %lld",
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 913b906..8023670 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -29,21 +29,72 @@
using std::string;
using android::util::ProtoOutputStream;
-// We need to keep a copy of the android_log_event_list owned by this instance so that the char*
-// for strings is not cleared before we can read them.
-LogEvent::LogEvent(log_msg& msg) : mList(msg) {
- init(msg.entry_v1.sec * NS_PER_SEC + msg.entry_v1.nsec, &mList);
+LogEvent::LogEvent(log_msg& msg) {
+ android_log_context context =
+ create_android_log_parser(msg.msg() + sizeof(uint32_t), msg.len() - sizeof(uint32_t));
+ mTimestampNs = msg.entry_v1.sec * NS_PER_SEC + msg.entry_v1.nsec;
+ mContext = NULL;
+ init(context);
}
-LogEvent::LogEvent(int tag, uint64_t timestampNs) : mList(tag), mTimestampNs(timestampNs) {
-}
-
-LogEvent::~LogEvent() {
+LogEvent::LogEvent(int32_t tagId, uint64_t timestampNs) {
+ mTimestampNs = timestampNs;
+ mTagId = tagId;
+ mContext = create_android_logger(1937006964); // the event tag shared by all stats logs
+ if (mContext) {
+ android_log_write_int32(mContext, tagId);
+ }
}
void LogEvent::init() {
- mList.convert_to_reader();
- init(mTimestampNs, &mList);
+ if (mContext) {
+ const char* buffer;
+ size_t len = android_log_write_list_buffer(mContext, &buffer);
+ // turns to reader mode
+ mContext = create_android_log_parser(buffer, len);
+ init(mContext);
+ }
+}
+
+bool LogEvent::write(int32_t value) {
+ if (mContext) {
+ return android_log_write_int32(mContext, value) >= 0;
+ }
+ return false;
+}
+
+bool LogEvent::write(uint32_t value) {
+ if (mContext) {
+ return android_log_write_int32(mContext, value) >= 0;
+ }
+ return false;
+}
+
+bool LogEvent::write(uint64_t value) {
+ if (mContext) {
+ return android_log_write_int64(mContext, value) >= 0;
+ }
+ return false;
+}
+
+bool LogEvent::write(const string& value) {
+ if (mContext) {
+ return android_log_write_string8_len(mContext, value.c_str(), value.length()) >= 0;
+ }
+ return false;
+}
+
+bool LogEvent::write(float value) {
+ if (mContext) {
+ return android_log_write_float32(mContext, value) >= 0;
+ }
+ return false;
+}
+
+LogEvent::~LogEvent() {
+ if (mContext) {
+ android_log_destroy(&mContext);
+ }
}
/**
@@ -51,22 +102,25 @@
* The goal is to do as little preprocessing as possible, because we read a tiny fraction
* of the elements that are written to the log.
*/
-void LogEvent::init(int64_t timestampNs, android_log_event_list* reader) {
- mTimestampNs = timestampNs;
- mTagId = reader->tag();
-
+void LogEvent::init(android_log_context context) {
mElements.clear();
android_log_list_element elem;
-
// TODO: The log is actually structured inside one list. This is convenient
// because we'll be able to use it to put the attribution (WorkSource) block first
// without doing our own tagging scheme. Until that change is in, just drop the
// list-related log elements and the order we get there is our index-keyed data
// structure.
+ int i = 0;
do {
- elem = android_log_read_next(reader->context());
+ elem = android_log_read_next(context);
switch ((int)elem.type) {
case EVENT_TYPE_INT:
+ // elem at [0] is EVENT_TYPE_LIST, [1] is the tag id. If we add WorkSource, it would
+ // be the list starting at [2].
+ if (i == 1) {
+ mTagId = elem.data.int32;
+ break;
+ }
case EVENT_TYPE_FLOAT:
case EVENT_TYPE_STRING:
case EVENT_TYPE_LONG:
@@ -81,13 +135,10 @@
default:
break;
}
+ i++;
} while ((elem.type != EVENT_TYPE_UNKNOWN) && !elem.complete);
}
-android_log_event_list* LogEvent::GetAndroidLogEventList() {
- return &mList;
-}
-
int64_t LogEvent::GetLong(size_t key, status_t* err) const {
if (key < 1 || (key - 1) >= mElements.size()) {
*err = BAD_INDEX;
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 2984940..7e8a96b 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -21,6 +21,7 @@
#include <android/util/ProtoOutputStream.h>
#include <log/log_event_list.h>
#include <log/log_read.h>
+#include <private/android_logger.h>
#include <utils/Errors.h>
#include <memory>
@@ -45,12 +46,9 @@
explicit LogEvent(log_msg& msg);
/**
- * Constructs a LogEvent with the specified tag and creates an android_log_event_list in write
- * mode. Obtain this list with the getter. Make sure to call init() before attempting to read
- * any of the values. This constructor is useful for unit-testing since we can't pass in an
- * android_log_event_list since there is no copy constructor or assignment operator available.
+ * Constructs a LogEvent with synthetic data for testing. Must call init() before reading.
*/
- explicit LogEvent(int tag, uint64_t timestampNs);
+ explicit LogEvent(int32_t tagId, uint64_t timestampNs);
~LogEvent();
@@ -76,6 +74,17 @@
float GetFloat(size_t key, status_t* err) const;
/**
+ * Write test data to the LogEvent. This can only be used when the LogEvent is constructed
+ * using LogEvent(tagId, timestampNs). You need to call init() before you can read from it.
+ */
+ bool write(uint32_t value);
+ bool write(int32_t value);
+ bool write(uint64_t value);
+ bool write(int64_t value);
+ bool write(const string& value);
+ bool write(float value);
+
+ /**
* Return a string representation of this event.
*/
string ToString() const;
@@ -91,13 +100,6 @@
KeyValuePair GetKeyValueProto(size_t key) const;
/**
- * A pointer to the contained log_event_list.
- *
- * @return The android_log_event_list contained within.
- */
- android_log_event_list* GetAndroidLogEventList();
-
- /**
* Used with the constructor where tag is passed in. Converts the log_event_list to read mode
* and prepares the list for reading.
*/
@@ -113,16 +115,11 @@
/**
* Parses a log_msg into a LogEvent object.
*/
- void init(const log_msg& msg);
-
- /**
- * Parses a log_msg into a LogEvent object.
- */
- void init(int64_t timestampNs, android_log_event_list* reader);
+ void init(android_log_context context);
vector<android_log_list_element> mElements;
- // Need a copy of the android_log_event_list so the strings are not cleared.
- android_log_event_list mList;
+
+ android_log_context mContext;
uint64_t mTimestampNs;
diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp
index a740280..41b24bc 100644
--- a/cmds/statsd/src/main.cpp
+++ b/cmds/statsd/src/main.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp
index cccc9b3..255165c 100644
--- a/cmds/statsd/src/matchers/matcher_util.cpp
+++ b/cmds/statsd/src/matchers/matcher_util.cpp
@@ -112,6 +112,7 @@
if (err == NO_ERROR && val != NULL) {
if (!(cur.eq_string() == val)) {
allMatched = false;
+ break;
}
}
} else if (matcherCase == KeyValueMatcher::ValueMatcherCase::kEqInt ||
@@ -126,26 +127,30 @@
if (matcherCase == KeyValueMatcher::ValueMatcherCase::kEqInt) {
if (!(val == cur.eq_int())) {
allMatched = false;
+ break;
}
} else if (matcherCase == KeyValueMatcher::ValueMatcherCase::kLtInt) {
if (!(val < cur.lt_int())) {
allMatched = false;
+ break;
}
} else if (matcherCase == KeyValueMatcher::ValueMatcherCase::kGtInt) {
if (!(val > cur.gt_int())) {
allMatched = false;
+ break;
}
} else if (matcherCase == KeyValueMatcher::ValueMatcherCase::kLteInt) {
if (!(val <= cur.lte_int())) {
allMatched = false;
+ break;
}
} else if (matcherCase == KeyValueMatcher::ValueMatcherCase::kGteInt) {
if (!(val >= cur.gte_int())) {
allMatched = false;
+ break;
}
}
}
- break;
} else if (matcherCase == KeyValueMatcher::ValueMatcherCase::kEqBool) {
// Boolean fields
status_t err = NO_ERROR;
@@ -153,21 +158,24 @@
if (err == NO_ERROR) {
if (!(cur.eq_bool() == val)) {
allMatched = false;
+ break;
}
}
} else if (matcherCase == KeyValueMatcher::ValueMatcherCase::kLtFloat ||
matcherCase == KeyValueMatcher::ValueMatcherCase::kGtFloat) {
// Float fields
status_t err = NO_ERROR;
- bool val = event.GetFloat(key, &err);
+ float val = event.GetFloat(key, &err);
if (err == NO_ERROR) {
if (matcherCase == KeyValueMatcher::ValueMatcherCase::kLtFloat) {
- if (!(cur.lt_float() <= val)) {
+ if (!(val < cur.lt_float())) {
allMatched = false;
+ break;
}
} else if (matcherCase == KeyValueMatcher::ValueMatcherCase::kGtFloat) {
- if (!(cur.gt_float() >= val)) {
+ if (!(val > cur.gt_float())) {
allMatched = false;
+ break;
}
}
}
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index aaf3ec2..de6f365 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -233,10 +233,12 @@
}
VLOG("flushing...........");
- for (auto it = mCurrentSlicedDuration.begin(); it != mCurrentSlicedDuration.end(); ++it) {
+ for (auto it = mCurrentSlicedDuration.begin(); it != mCurrentSlicedDuration.end();) {
if (it->second->flushIfNeeded(eventTime)) {
VLOG("erase bucket for key %s", it->first.c_str());
- mCurrentSlicedDuration.erase(it);
+ it = mCurrentSlicedDuration.erase(it);
+ } else {
+ ++it;
}
}
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index c2044d8..4c63b20 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -220,6 +220,11 @@
handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
metric.links(), allConditionTrackers, conditionIndex,
conditionToMetricMap);
+ } else {
+ if (metric.links_size() > 0) {
+ ALOGW("metrics has a EventConditionLink but doesn't have a condition");
+ return false;
+ }
}
sp<MetricProducer> countProducer =
@@ -276,10 +281,15 @@
int conditionIndex = -1;
- if (metric.has_predicate()) {
- handleMetricWithConditions(metric.predicate(), metricIndex, conditionTrackerMap,
+ if (metric.has_condition()) {
+ handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
metric.links(), allConditionTrackers, conditionIndex,
conditionToMetricMap);
+ } else {
+ if (metric.links_size() > 0) {
+ ALOGW("metrics has a EventConditionLink but doesn't have a condition");
+ return false;
+ }
}
sp<MetricProducer> durationMetric = new DurationMetricProducer(
@@ -308,6 +318,11 @@
handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
metric.links(), allConditionTrackers, conditionIndex,
conditionToMetricMap);
+ } else {
+ if (metric.links_size() > 0) {
+ ALOGW("metrics has a EventConditionLink but doesn't have a condition");
+ return false;
+ }
}
sp<MetricProducer> eventMetric =
@@ -349,6 +364,11 @@
handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
metric.links(), allConditionTrackers, conditionIndex,
conditionToMetricMap);
+ } else {
+ if (metric.links_size() > 0) {
+ ALOGW("metrics has a EventConditionLink but doesn't have a condition");
+ return false;
+ }
}
sp<MetricProducer> valueProducer =
@@ -389,6 +409,11 @@
handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
metric.links(), allConditionTrackers, conditionIndex,
conditionToMetricMap);
+ } else {
+ if (metric.links_size() > 0) {
+ ALOGW("metrics has a EventConditionLink but doesn't have a condition");
+ return false;
+ }
}
sp<MetricProducer> gaugeProducer =
diff --git a/cmds/statsd/src/packages/PackageInfoListener.h b/cmds/statsd/src/packages/PackageInfoListener.h
index 13e776f..5aa3db5 100644
--- a/cmds/statsd/src/packages/PackageInfoListener.h
+++ b/cmds/statsd/src/packages/PackageInfoListener.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index 2398814..6c32d3e 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, versionCode 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index de68fbc..24eb966 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 7648a91..9a760b1 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -161,20 +161,20 @@
optional string what = 2;
+ optional string condition = 3;
+
+ repeated EventConditionLink links = 4;
+
enum AggregationType {
DURATION_SUM = 1;
DURATION_MAX_SPARSE = 2;
- }
- optional AggregationType type = 3;
+ }
+ optional AggregationType type = 5;
- optional string predicate = 4;
+ repeated KeyMatcher dimension = 6;
- repeated KeyMatcher dimension = 5;
-
- optional Bucket bucket = 6;
-
- repeated EventConditionLink links = 7;
+ optional Bucket bucket = 7;
}
message GaugeMetric {
diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp
index d0898b0..40c0e9d 100644
--- a/cmds/statsd/tests/LogEntryMatcher_test.cpp
+++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp
@@ -27,7 +27,7 @@
using std::unordered_map;
using std::vector;
-const int TAG_ID = 123;
+const int32_t TAG_ID = 123;
const int FIELD_ID_1 = 1;
const int FIELD_ID_2 = 2;
const int FIELD_ID_3 = 2;
@@ -43,8 +43,6 @@
simpleMatcher->set_tag(TAG_ID);
LogEvent event(TAG_ID, 0);
-
- // Convert to a LogEvent
event.init();
// Test
@@ -63,10 +61,8 @@
// Set up the event
LogEvent event(TAG_ID, 0);
- auto list = event.GetAndroidLogEventList();
- *list << true;
- *list << false;
-
+ event.write(true);
+ event.write(false);
// Convert to a LogEvent
event.init();
@@ -99,9 +95,7 @@
// Set up the event
LogEvent event(TAG_ID, 0);
- auto list = event.GetAndroidLogEventList();
- *list << "some value";
-
+ event.write("some value");
// Convert to a LogEvent
event.init();
@@ -109,6 +103,38 @@
EXPECT_TRUE(matchesSimple(*simpleMatcher, event));
}
+TEST(LogEntryMatcherTest, TestMultiFieldsMatcher) {
+ // Set up the matcher
+ LogEntryMatcher matcher;
+ auto simpleMatcher = matcher.mutable_simple_log_entry_matcher();
+ simpleMatcher->set_tag(TAG_ID);
+ auto keyValue1 = simpleMatcher->add_key_value_matcher();
+ keyValue1->mutable_key_matcher()->set_key(FIELD_ID_1);
+ auto keyValue2 = simpleMatcher->add_key_value_matcher();
+ keyValue2->mutable_key_matcher()->set_key(FIELD_ID_2);
+
+ // Set up the event
+ LogEvent event(TAG_ID, 0);
+ event.write(2);
+ event.write(3);
+
+ // Convert to a LogEvent
+ event.init();
+
+ // Test
+ keyValue1->set_eq_int(2);
+ keyValue2->set_eq_int(3);
+ EXPECT_TRUE(matchesSimple(*simpleMatcher, event));
+
+ keyValue1->set_eq_int(2);
+ keyValue2->set_eq_int(4);
+ EXPECT_FALSE(matchesSimple(*simpleMatcher, event));
+
+ keyValue1->set_eq_int(4);
+ keyValue2->set_eq_int(3);
+ EXPECT_FALSE(matchesSimple(*simpleMatcher, event));
+}
+
TEST(LogEntryMatcherTest, TestIntComparisonMatcher) {
// Set up the matcher
LogEntryMatcher matcher;
@@ -120,9 +146,7 @@
// Set up the event
LogEvent event(TAG_ID, 0);
- auto list = event.GetAndroidLogEventList();
- *list << 11;
-
+ event.write(11);
event.init();
// Test
@@ -168,8 +192,6 @@
EXPECT_FALSE(matchesSimple(*simpleMatcher, event));
}
-#if 0
-
TEST(LogEntryMatcherTest, TestFloatComparisonMatcher) {
// Set up the matcher
LogEntryMatcher matcher;
@@ -179,22 +201,28 @@
auto keyValue = simpleMatcher->add_key_value_matcher();
keyValue->mutable_key_matcher()->set_key(FIELD_ID_1);
- LogEvent event;
- event.tagId = TAG_ID;
-
+ LogEvent event1(TAG_ID, 0);
keyValue->set_lt_float(10.0);
- event.floatMap[FIELD_ID_1] = 10.1;
- EXPECT_FALSE(matchesSimple(*simpleMatcher, event));
- event.floatMap[FIELD_ID_1] = 9.9;
- EXPECT_TRUE(matchesSimple(*simpleMatcher, event));
+ event1.write(10.1f);
+ event1.init();
+ EXPECT_FALSE(matchesSimple(*simpleMatcher, event1));
+ LogEvent event2(TAG_ID, 0);
+ event2.write(9.9f);
+ event2.init();
+ EXPECT_TRUE(matchesSimple(*simpleMatcher, event2));
+
+ LogEvent event3(TAG_ID, 0);
+ event3.write(10.1f);
+ event3.init();
keyValue->set_gt_float(10.0);
- event.floatMap[FIELD_ID_1] = 10.1;
- EXPECT_TRUE(matchesSimple(*simpleMatcher, event));
- event.floatMap[FIELD_ID_1] = 9.9;
- EXPECT_FALSE(matchesSimple(*simpleMatcher, event));
+ EXPECT_TRUE(matchesSimple(*simpleMatcher, event3));
+
+ LogEvent event4(TAG_ID, 0);
+ event4.write(9.9f);
+ event4.init();
+ EXPECT_FALSE(matchesSimple(*simpleMatcher, event4));
}
-#endif
// Helper for the composite matchers.
void addSimpleMatcher(SimpleLogEntryMatcher* simpleMatcher, int tag, int key, int val) {
diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp
index c64719e..4c12b03 100644
--- a/cmds/statsd/tests/UidMap_test.cpp
+++ b/cmds/statsd/tests/UidMap_test.cpp
@@ -36,10 +36,9 @@
sp<UidMap> m = new UidMap();
StatsLogProcessor p(m, nullptr);
LogEvent addEvent(android::util::ISOLATED_UID_CHANGED, 1);
- android_log_event_list* list = addEvent.GetAndroidLogEventList();
- *list << 100; // parent UID
- *list << 101; // isolated UID
- *list << 1; // Indicates creation.
+ addEvent.write(100); // parent UID
+ addEvent.write(101); // isolated UID
+ addEvent.write(1); // Indicates creation.
addEvent.init();
EXPECT_EQ(101, m->getParentUidOrSelf(101));
@@ -48,10 +47,9 @@
EXPECT_EQ(100, m->getParentUidOrSelf(101));
LogEvent removeEvent(android::util::ISOLATED_UID_CHANGED, 1);
- list = removeEvent.GetAndroidLogEventList();
- *list << 100; // parent UID
- *list << 101; // isolated UID
- *list << 0; // Indicates removal.
+ removeEvent.write(100); // parent UID
+ removeEvent.write(101); // isolated UID
+ removeEvent.write(0); // Indicates removal.
removeEvent.init();
p.OnLogEvent(removeEvent);
EXPECT_EQ(101, m->getParentUidOrSelf(101));
diff --git a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
index 05aad29..80a0068 100644
--- a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
+++ b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
@@ -46,10 +46,9 @@
}
void makeWakeLockEvent(LogEvent* event, int uid, const string& wl, int acquire) {
- auto list = event->GetAndroidLogEventList();
- *list << uid; // uid
- *list << wl;
- *list << acquire;
+ event->write(uid); // uid
+ event->write(wl);
+ event->write(acquire);
event->init();
}
@@ -108,6 +107,18 @@
EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
EXPECT_TRUE(changedCache[0]);
+ // match nothing.
+ matcherState.clear();
+ matcherState.push_back(MatchingState::kNotMatched);
+ matcherState.push_back(MatchingState::kNotMatched);
+ conditionCache[0] = ConditionState::kNotEvaluated;
+ changedCache[0] = false;
+
+ conditionTracker.evaluateCondition(event, matcherState, allConditions, conditionCache,
+ changedCache);
+ EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
+ EXPECT_FALSE(changedCache[0]);
+
// the case for match stop.
matcherState.clear();
matcherState.push_back(MatchingState::kNotMatched);
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index d07a84d..b7c9b40 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -138,15 +138,13 @@
link->add_key_in_condition()->set_key(2);
LogEvent event1(1, bucketStartTimeNs + 1);
- auto list = event1.GetAndroidLogEventList();
- *list << "111"; // uid
+ event1.write("111"); // uid
event1.init();
ConditionKey key1;
key1["APP_IN_BACKGROUND_PER_UID"] = "2:111|";
LogEvent event2(1, bucketStartTimeNs + 10);
- auto list2 = event2.GetAndroidLogEventList();
- *list2 << "222"; // uid
+ event2.write("222"); // uid
event2.init();
ConditionKey key2;
key2["APP_IN_BACKGROUND_PER_UID"] = "2:222|";
diff --git a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
index 0971d26..18d177c 100644
--- a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
@@ -95,15 +95,13 @@
link->add_key_in_condition()->set_key(2);
LogEvent event1(1, bucketStartTimeNs + 1);
- auto list = event1.GetAndroidLogEventList();
- *list << "111"; // uid
+ event1.write("111"); // uid
event1.init();
ConditionKey key1;
key1["APP_IN_BACKGROUND_PER_UID"] = "2:111|";
LogEvent event2(1, bucketStartTimeNs + 10);
- auto list2 = event2.GetAndroidLogEventList();
- *list2 << "222"; // uid
+ event2.write("222"); // uid
event2.init();
ConditionKey key2;
key2["APP_IN_BACKGROUND_PER_UID"] = "2:222|";
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 72b4194..cd647cb 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -64,9 +64,8 @@
vector<shared_ptr<LogEvent>> allData;
allData.clear();
shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
- auto list = event->GetAndroidLogEventList();
- *list << 1;
- *list << 11;
+ event->write(1);
+ event->write(11);
event->init();
allData.push_back(event);
@@ -89,9 +88,8 @@
allData.clear();
event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- list = event->GetAndroidLogEventList();
- *list << 1;
- *list << 22;
+ event->write(1);
+ event->write(22);
event->init();
allData.push_back(event);
valueProducer.onDataPulled(allData);
@@ -110,9 +108,8 @@
allData.clear();
event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
- list = event->GetAndroidLogEventList();
- *list << 1;
- *list << 33;
+ event->write(1);
+ event->write(33);
event->init();
allData.push_back(event);
valueProducer.onDataPulled(allData);
@@ -159,9 +156,8 @@
int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
data->clear();
shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- auto list = event->GetAndroidLogEventList();
- *list << 1;
- *list << 100;
+ event->write(1);
+ event->write(100);
event->init();
data->push_back(event);
return true;
@@ -174,9 +170,8 @@
int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
data->clear();
shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
- auto list = event->GetAndroidLogEventList();
- *list << 1;
- *list << 120;
+ event->write(1);
+ event->write(120);
event->init();
data->push_back(event);
return true;
@@ -201,9 +196,8 @@
vector<shared_ptr<LogEvent>> allData;
allData.clear();
shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- auto list = event->GetAndroidLogEventList();
- *list << 1;
- *list << 110;
+ event->write(1);
+ event->write(110);
event->init();
allData.push_back(event);
valueProducer.onDataPulled(allData);
@@ -253,14 +247,12 @@
bucketStartTimeNs, pullerManager);
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- auto list = event1->GetAndroidLogEventList();
- *list << 1;
- *list << 10;
+ event1->write(1);
+ event1->write(10);
event1->init();
shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- auto list2 = event2->GetAndroidLogEventList();
- *list2 << 1;
- *list2 << 20;
+ event2->write(1);
+ event2->write(20);
event2->init();
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1, false);
// has one slice
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index ee89ca8..cc95eb6 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -254,6 +254,11 @@
HashMap<String, PropertyValuesHolder> mValuesMap;
/**
+ * If set to non-negative value, this will override {@link #sDurationScale}.
+ */
+ private float mDurationScale = -1f;
+
+ /**
* Public constants
*/
@@ -579,8 +584,23 @@
return this;
}
+ /**
+ * Overrides the global duration scale by a custom value.
+ *
+ * @param durationScale The duration scale to set; or {@code -1f} to use the global duration
+ * scale.
+ * @hide
+ */
+ public void overrideDurationScale(float durationScale) {
+ mDurationScale = durationScale;
+ }
+
+ private float resolveDurationScale() {
+ return mDurationScale >= 0f ? mDurationScale : sDurationScale;
+ }
+
private long getScaledDuration() {
- return (long)(mDuration * sDurationScale);
+ return (long)(mDuration * resolveDurationScale());
}
/**
@@ -735,7 +755,10 @@
if (mSeekFraction >= 0) {
return (long) (mDuration * mSeekFraction);
}
- float durationScale = sDurationScale == 0 ? 1 : sDurationScale;
+ float durationScale = resolveDurationScale();
+ if (durationScale == 0f) {
+ durationScale = 1f;
+ }
return (long) ((AnimationUtils.currentAnimationTimeMillis() - mStartTime) / durationScale);
}
@@ -1397,7 +1420,9 @@
if (mStartTime < 0) {
// First frame. If there is start delay, start delay count down will happen *after* this
// frame.
- mStartTime = mReversing ? frameTime : frameTime + (long) (mStartDelay * sDurationScale);
+ mStartTime = mReversing
+ ? frameTime
+ : frameTime + (long) (mStartDelay * resolveDurationScale());
}
// Handle pause/resume
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 99f3dee..03a3631 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4379,7 +4379,7 @@
throw new IllegalArgumentException("requestCode should be >= 0");
}
if (mHasCurrentPermissionsRequest) {
- Log.w(TAG, "Can reqeust only one set of permissions at a time");
+ Log.w(TAG, "Can request only one set of permissions at a time");
// Dispatch the callback with empty arrays which means a cancellation.
onRequestPermissionsResult(requestCode, new String[0], new int[0]);
return;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 21e454f..95c5fb5 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5380,7 +5380,7 @@
}
}
- GraphicsEnvironment.chooseDriver(context);
+ GraphicsEnvironment.getInstance().setup(context);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index b7c1f4e..7257044 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -17,9 +17,12 @@
package android.app;
import android.os.Build;
+import android.os.GraphicsEnvironment;
import android.os.Trace;
import android.util.ArrayMap;
+
import com.android.internal.os.ClassLoaderFactory;
+
import dalvik.system.PathClassLoader;
/** @hide */
@@ -72,8 +75,9 @@
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setupVulkanLayerPath");
- setupVulkanLayerPath(classloader, librarySearchPath);
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setLayerPaths");
+ GraphicsEnvironment.getInstance().setLayerPaths(
+ classloader, librarySearchPath, libraryPermittedPath);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
mLoaders.put(cacheKey, classloader);
@@ -105,8 +109,6 @@
cacheKey, null /* classLoaderName */);
}
- private static native void setupVulkanLayerPath(ClassLoader classLoader, String librarySearchPath);
-
/**
* Adds a new path the classpath of the given loader.
* @throws IllegalStateException if the provided class loader is not a {@link PathClassLoader}.
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 0eafdec..7a4c00f 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -35,7 +35,6 @@
import android.content.pm.IOnPermissionsChangeListener;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
-import android.content.pm.IPackageInstallObserver;
import android.content.pm.IPackageManager;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
@@ -1681,21 +1680,8 @@
}
@Override
- public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
- String installerPackageName) {
- installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
- installerPackageName, mContext.getUserId());
- }
-
- @Override
- public void installPackage(Uri packageURI, PackageInstallObserver observer,
- int flags, String installerPackageName) {
- installCommon(packageURI, observer, flags, installerPackageName, mContext.getUserId());
- }
-
- private void installCommon(Uri packageURI,
- PackageInstallObserver observer, int flags, String installerPackageName,
- int userId) {
+ public void installPackage(Uri packageURI,
+ PackageInstallObserver observer, int flags, String installerPackageName) {
if (!"file".equals(packageURI.getScheme())) {
throw new UnsupportedOperationException("Only file:// URIs are supported");
}
@@ -1703,7 +1689,7 @@
final String originPath = packageURI.getPath();
try {
mPM.installPackageAsUser(originPath, observer.getBinder(), flags, installerPackageName,
- userId);
+ mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index bbc90c8..4fc649e 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -22,6 +22,7 @@
import android.app.IApplicationThread;
import android.app.IActivityController;
import android.app.IAppTask;
+import android.app.IAssistDataReceiver;
import android.app.IInstrumentationWatcher;
import android.app.IProcessObserver;
import android.app.IServiceConnection;
@@ -63,7 +64,6 @@
import android.os.PersistableBundle;
import android.os.StrictMode;
import android.service.voice.IVoiceInteractionSession;
-import com.android.internal.app.IAssistDataReceiver;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.os.IResultReceiver;
import com.android.internal.policy.IKeyguardDismissCallback;
@@ -423,7 +423,7 @@
int startAssistantActivity(in String callingPackage, int callingPid, int callingUid,
in Intent intent, in String resolvedType, in Bundle options, int userId);
int startRecentsActivity(in IAssistDataReceiver assistDataReceiver, in Bundle options,
- int userId);
+ in Bundle activityOptions, int userId);
int startActivityFromRecents(int taskId, in Bundle options);
Bundle getActivityOptions(in IBinder token);
List<IBinder> getAppTasks(in String callingPackage);
diff --git a/core/java/com/android/internal/app/IAssistDataReceiver.aidl b/core/java/android/app/IAssistDataReceiver.aidl
similarity index 95%
rename from core/java/com/android/internal/app/IAssistDataReceiver.aidl
rename to core/java/android/app/IAssistDataReceiver.aidl
index 9c9ffef..2d5daf9 100644
--- a/core/java/com/android/internal/app/IAssistDataReceiver.aidl
+++ b/core/java/android/app/IAssistDataReceiver.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.internal.app;
+package android.app;
import android.graphics.Bitmap;
import android.os.Bundle;
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 0d7a941..8200414 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -100,6 +100,12 @@
*/
public static final int CHOOSER_ACTION = 9;
+ /**
+ * An event type denoting that a notification was viewed by the user.
+ * @hide
+ */
+ public static final int NOTIFICATION_SEEN = 10;
+
/** @hide */
public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java
index e3d763a..6692e13 100644
--- a/core/java/android/bluetooth/BluetoothHidDevice.java
+++ b/core/java/android/bluetooth/BluetoothHidDevice.java
@@ -350,13 +350,22 @@
* application can be registered at time. When no longer used, application
* should be unregistered using
* {@link #unregisterApp(BluetoothHidDeviceAppConfiguration)}.
+ * The registration status should be tracked by the application by handling callback from
+ * BluetoothHidDeviceCallback#onAppStatusChanged. The app registration status is not related
+ * to the return value of this method.
*
* @param sdp {@link BluetoothHidDeviceAppSdpSettings} object of HID Device SDP record.
+ * The HID Device SDP record is required.
* @param inQos {@link BluetoothHidDeviceAppQosSettings} object of Incoming QoS Settings.
+ * The Incoming QoS Settings is not required. Use null or default
+ * BluetoothHidDeviceAppQosSettings.Builder for default values.
* @param outQos {@link BluetoothHidDeviceAppQosSettings} object of Outgoing QoS Settings.
+ * The Outgoing QoS Settings is not required. Use null or default
+ * BluetoothHidDeviceAppQosSettings.Builder for default values.
* @param callback {@link BluetoothHidDeviceCallback} object to which callback messages will be
* sent.
- * @return
+ * The BluetoothHidDeviceCallback object is required.
+ * @return true if the command is successfully sent; otherwise false.
*/
public boolean registerApp(BluetoothHidDeviceAppSdpSettings sdp,
BluetoothHidDeviceAppQosSettings inQos, BluetoothHidDeviceAppQosSettings outQos,
@@ -394,12 +403,15 @@
* {@link #registerApp
* (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
* BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceCallback)}
+ * The registration status should be tracked by the application by handling callback from
+ * BluetoothHidDeviceCallback#onAppStatusChanged. The app registration status is not related
+ * to the return value of this method.
*
* @param config {@link BluetoothHidDeviceAppConfiguration} object as obtained from {@link
* BluetoothHidDeviceCallback#onAppStatusChanged(BluetoothDevice,
* BluetoothHidDeviceAppConfiguration,
* boolean)}
- * @return
+ * @return true if the command is successfully sent; otherwise false.
*/
public boolean unregisterApp(BluetoothHidDeviceAppConfiguration config) {
Log.v(TAG, "unregisterApp()");
@@ -426,7 +438,7 @@
* @param id Report Id, as defined in descriptor. Can be 0 in case Report Id are not defined in
* descriptor.
* @param data Report data, not including Report Id.
- * @return
+ * @return true if the command is successfully sent; otherwise false.
*/
public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
boolean result = false;
@@ -452,7 +464,7 @@
* @param type Report Type, as in request.
* @param id Report Id, as in request.
* @param data Report data, not including Report Id.
- * @return
+ * @return true if the command is successfully sent; otherwise false.
*/
public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) {
Log.v(TAG, "replyReport(): device=" + device + " type=" + type + " id=" + id);
@@ -478,7 +490,7 @@
* from {@link BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])}.
*
* @param error Error to be sent for SET_REPORT via HANDSHAKE.
- * @return
+ * @return true if the command is successfully sent; otherwise false.
*/
public boolean reportError(BluetoothDevice device, byte error) {
Log.v(TAG, "reportError(): device=" + device + " error=" + error);
@@ -524,10 +536,13 @@
}
/**
- * Initiates connection to host which currently has Virtual Cable
- * established with device.
+ * Initiates connection to host which is currently paired with this device.
+ * If the application is not registered, #connect(BluetoothDevice) will fail.
+ * The connection state should be tracked by the application by handling callback from
+ * BluetoothHidDeviceCallback#onConnectionStateChanged. The connection state is not related
+ * to the return value of this method.
*
- * @return
+ * @return true if the command is successfully sent; otherwise false.
*/
public boolean connect(BluetoothDevice device) {
Log.v(TAG, "connect(): device=" + device);
@@ -550,8 +565,11 @@
/**
* Disconnects from currently connected host.
+ * The connection state should be tracked by the application by handling callback from
+ * BluetoothHidDeviceCallback#onConnectionStateChanged. The connection state is not related
+ * to the return value of this method.
*
- * @return
+ * @return true if the command is successfully sent; otherwise false.
*/
public boolean disconnect(BluetoothDevice device) {
Log.v(TAG, "disconnect(): device=" + device);
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java
index ccc3ef4..881ae98 100644
--- a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java
+++ b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java
@@ -45,6 +45,21 @@
public static final int MAX = (int) 0xffffffff;
+ /**
+ * Create a BluetoothHidDeviceAppQosSettings object for the Bluetooth L2CAP channel.
+ * The QoS Settings is optional.
+ * Recommended to use BluetoothHidDeviceAppQosSettings.Builder.
+ * {@see <a href="https://www.bluetooth.com/specifications/profiles-overview">
+ * https://www.bluetooth.com/specifications/profiles-overview
+ * </a>
+ * Bluetooth HID Specfication v1.1.1 Section 5.2 and Appendix D }
+ * @param serviceType L2CAP service type
+ * @param tokenRate L2CAP token rate
+ * @param tokenBucketSize L2CAP token bucket size
+ * @param peakBandwidth L2CAP peak bandwidth
+ * @param latency L2CAP latency
+ * @param delayVariation L2CAP delay variation
+ */
public BluetoothHidDeviceAppQosSettings(int serviceType, int tokenRate, int tokenBucketSize,
int peakBandwidth, int latency, int delayVariation) {
this.serviceType = serviceType;
@@ -59,7 +74,12 @@
public boolean equals(Object o) {
if (o instanceof BluetoothHidDeviceAppQosSettings) {
BluetoothHidDeviceAppQosSettings qos = (BluetoothHidDeviceAppQosSettings) o;
- return false;
+ return this.serviceType == qos.serviceType
+ && this.tokenRate == qos.tokenRate
+ && this.tokenBucketSize == qos.tokenBucketSize
+ && this.peakBandwidth == qos.peakBandwidth
+ && this.latency == qos.latency
+ && this.delayVariation == qos.delayVariation;
}
return false;
}
@@ -106,4 +126,85 @@
serviceType, tokenRate, tokenBucketSize, peakBandwidth, latency, delayVariation
};
}
+
+ /**
+ * A helper to build the BluetoothHidDeviceAppQosSettings object.
+ */
+ public static class Builder {
+ // Optional parameters - initialized to default values
+ private int mServiceType = SERVICE_BEST_EFFORT;
+ private int mTokenRate = 0;
+ private int mTokenBucketSize = 0;
+ private int mPeakBandwidth = 0;
+ private int mLatency = MAX;
+ private int mDelayVariation = MAX;
+
+ /**
+ * Set the service type.
+ * @param val service type. Should be one of {SERVICE_NO_TRAFFIC, SERVICE_BEST_EFFORT,
+ * SERVICE_GUARANTEED}, with SERVICE_BEST_EFFORT being the default one.
+ * @return BluetoothHidDeviceAppQosSettings Builder with specified service type.
+ */
+ public Builder serviceType(int val) {
+ mServiceType = val;
+ return this;
+ }
+ /**
+ * Set the token rate.
+ * @param val token rate
+ * @return BluetoothHidDeviceAppQosSettings Builder with specified token rate.
+ */
+ public Builder tokenRate(int val) {
+ mTokenRate = val;
+ return this;
+ }
+
+ /**
+ * Set the bucket size.
+ * @param val bucket size
+ * @return BluetoothHidDeviceAppQosSettings Builder with specified bucket size.
+ */
+ public Builder tokenBucketSize(int val) {
+ mTokenBucketSize = val;
+ return this;
+ }
+
+ /**
+ * Set the peak bandwidth.
+ * @param val peak bandwidth
+ * @return BluetoothHidDeviceAppQosSettings Builder with specified peak bandwidth.
+ */
+ public Builder peakBandwidth(int val) {
+ mPeakBandwidth = val;
+ return this;
+ }
+ /**
+ * Set the latency.
+ * @param val latency
+ * @return BluetoothHidDeviceAppQosSettings Builder with specified latency.
+ */
+ public Builder latency(int val) {
+ mLatency = val;
+ return this;
+ }
+
+ /**
+ * Set the delay variation.
+ * @param val delay variation
+ * @return BluetoothHidDeviceAppQosSettings Builder with specified delay variation.
+ */
+ public Builder delayVariation(int val) {
+ mDelayVariation = val;
+ return this;
+ }
+
+ /**
+ * Build the BluetoothHidDeviceAppQosSettings object.
+ * @return BluetoothHidDeviceAppQosSettings object with current settings.
+ */
+ public BluetoothHidDeviceAppQosSettings build() {
+ return new BluetoothHidDeviceAppQosSettings(mServiceType, mTokenRate, mTokenBucketSize,
+ mPeakBandwidth, mLatency, mDelayVariation);
+ }
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
index f01c493..4669637 100644
--- a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
+++ b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
@@ -19,6 +19,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.Arrays;
+
/**
* Represents the Service Discovery Protocol (SDP) settings for a Bluetooth
* HID Device application.
@@ -39,6 +41,18 @@
public final byte subclass;
public final byte[] descriptors;
+ /**
+ * Create a BluetoothHidDeviceAppSdpSettings object for the Bluetooth SDP record.
+ * @param name Name of this Bluetooth HID device. Maximum length is 50 bytes.
+ * @param description Description for this Bluetooth HID device. Maximum length is 50 bytes.
+ * @param provider Provider of this Bluetooth HID device. Maximum length is 50 bytes.
+ * @param subclass Subclass of this Bluetooth HID device.
+ * See <a href="www.usb.org/developers/hidpage/HID1_11.pdf">
+ * www.usb.org/developers/hidpage/HID1_11.pdf Section 4.2</a>
+ * @param descriptors Descriptors of this Bluetooth HID device.
+ * See <a href="www.usb.org/developers/hidpage/HID1_11.pdf">
+ * www.usb.org/developers/hidpage/HID1_11.pdf Chapter 6</a> Maximum length is 2048 bytes.
+ */
public BluetoothHidDeviceAppSdpSettings(String name, String description, String provider,
byte subclass, byte[] descriptors) {
this.name = name;
@@ -52,7 +66,11 @@
public boolean equals(Object o) {
if (o instanceof BluetoothHidDeviceAppSdpSettings) {
BluetoothHidDeviceAppSdpSettings sdp = (BluetoothHidDeviceAppSdpSettings) o;
- return false;
+ return this.name.equals(sdp.name)
+ && this.description.equals(sdp.description)
+ && this.provider.equals(sdp.provider)
+ && this.subclass == sdp.subclass
+ && Arrays.equals(this.descriptors, sdp.descriptors);
}
return false;
}
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index 4b09fed..d3652e8 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -30,6 +30,11 @@
* when they are committed to storage. Objects that are returned from the
* various <code>get</code> methods must be treated as immutable by the application.
*
+ * <p>Note: This class provides strong consistency guarantees. It is using expensive operations
+ * which might slow down an app. Frequently changing properties or properties where loss can be
+ * tolerated should use other mechanisms. For more details read the comments on
+ * {@link Editor#commit()} and {@link Editor#apply()}.
+ *
* <p><em>Note: This class does not support use across multiple processes.</em>
*
* <div class="special reference">
diff --git a/core/java/android/content/pm/IPackageInstallObserver.aidl b/core/java/android/content/pm/IPackageInstallObserver.aidl
deleted file mode 100644
index 6133365..0000000
--- a/core/java/android/content/pm/IPackageInstallObserver.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-/**
- * API for installation callbacks from the Package Manager.
- * @hide
- */
-oneway interface IPackageInstallObserver {
- void packageInstalled(in String packageName, int returnCode);
-}
-
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 86288396..77c5743 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -81,6 +81,9 @@
* <li>All APKs must have unique split names.
* <li>All installations must contain a single base APK.
* </ul>
+ * <p>
+ * The ApiDemos project contains examples of using this API:
+ * <code>ApiDemos/src/com/example/android/apis/content/InstallApk*.java</code>.
*/
public class PackageInstaller {
private static final String TAG = "PackageInstaller";
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 31ca198..15ea4b5 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -871,8 +871,8 @@
public static final int INSTALL_REASON_USER = 4;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} on success.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * on success.
*
* @hide
*/
@@ -880,8 +880,8 @@
public static final int INSTALL_SUCCEEDED = 1;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the package is already installed.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the package is already installed.
*
* @hide
*/
@@ -889,8 +889,8 @@
public static final int INSTALL_FAILED_ALREADY_EXISTS = -1;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the package archive file is invalid.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the package archive file is invalid.
*
* @hide
*/
@@ -898,8 +898,8 @@
public static final int INSTALL_FAILED_INVALID_APK = -2;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the URI passed in is invalid.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the URI passed in is invalid.
*
* @hide
*/
@@ -907,9 +907,9 @@
public static final int INSTALL_FAILED_INVALID_URI = -3;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the package manager service found that
- * the device didn't have enough storage space to install the app.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the package manager service found that the device didn't have enough storage space to
+ * install the app.
*
* @hide
*/
@@ -917,9 +917,8 @@
public static final int INSTALL_FAILED_INSUFFICIENT_STORAGE = -4;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if a package is already installed with
- * the same name.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if a package is already installed with the same name.
*
* @hide
*/
@@ -927,9 +926,8 @@
public static final int INSTALL_FAILED_DUPLICATE_PACKAGE = -5;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the requested shared user does not
- * exist.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the requested shared user does not exist.
*
* @hide
*/
@@ -937,10 +935,9 @@
public static final int INSTALL_FAILED_NO_SHARED_USER = -6;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if a previously installed package of the
- * same name has a different signature than the new package (and the old
- * package's data was not removed).
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if a previously installed package of the same name has a different signature than the new
+ * package (and the old package's data was not removed).
*
* @hide
*/
@@ -948,10 +945,9 @@
public static final int INSTALL_FAILED_UPDATE_INCOMPATIBLE = -7;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package is requested a shared
- * user which is already installed on the device and does not have matching
- * signature.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package is requested a shared user which is already installed on the device and
+ * does not have matching signature.
*
* @hide
*/
@@ -959,9 +955,8 @@
public static final int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE = -8;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package uses a shared library
- * that is not available.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package uses a shared library that is not available.
*
* @hide
*/
@@ -969,9 +964,8 @@
public static final int INSTALL_FAILED_MISSING_SHARED_LIBRARY = -9;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package uses a shared library
- * that is not available.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package uses a shared library that is not available.
*
* @hide
*/
@@ -979,10 +973,9 @@
public static final int INSTALL_FAILED_REPLACE_COULDNT_DELETE = -10;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package failed while
- * optimizing and validating its dex files, either because there was not
- * enough storage or the validation failed.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package failed while optimizing and validating its dex files, either because there
+ * was not enough storage or the validation failed.
*
* @hide
*/
@@ -990,9 +983,9 @@
public static final int INSTALL_FAILED_DEXOPT = -11;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package failed because the
- * current SDK version is older than that required by the package.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package failed because the current SDK version is older than that required by the
+ * package.
*
* @hide
*/
@@ -1000,10 +993,9 @@
public static final int INSTALL_FAILED_OLDER_SDK = -12;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package failed because it
- * contains a content provider with the same authority as a provider already
- * installed in the system.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package failed because it contains a content provider with the same authority as a
+ * provider already installed in the system.
*
* @hide
*/
@@ -1011,9 +1003,9 @@
public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package failed because the
- * current SDK version is newer than that required by the package.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package failed because the current SDK version is newer than that required by the
+ * package.
*
* @hide
*/
@@ -1021,10 +1013,9 @@
public static final int INSTALL_FAILED_NEWER_SDK = -14;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package failed because it has
- * specified that it is a test-only package and the caller has not supplied
- * the {@link #INSTALL_ALLOW_TEST} flag.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package failed because it has specified that it is a test-only package and the
+ * caller has not supplied the {@link #INSTALL_ALLOW_TEST} flag.
*
* @hide
*/
@@ -1032,9 +1023,9 @@
public static final int INSTALL_FAILED_TEST_ONLY = -15;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the package being installed contains
- * native code, but none that is compatible with the device's CPU_ABI.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the package being installed contains native code, but none that is compatible with the
+ * device's CPU_ABI.
*
* @hide
*/
@@ -1042,9 +1033,8 @@
public static final int INSTALL_FAILED_CPU_ABI_INCOMPATIBLE = -16;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package uses a feature that is
- * not available.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package uses a feature that is not available.
*
* @hide
*/
@@ -1053,9 +1043,9 @@
// ------ Errors related to sdcard
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if a secure container mount point
- * couldn't be accessed on external media.
+ * Installation return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if a secure container mount point couldn't be
+ * accessed on external media.
*
* @hide
*/
@@ -1063,9 +1053,8 @@
public static final int INSTALL_FAILED_CONTAINER_ERROR = -18;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package couldn't be installed
- * in the specified install location.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package couldn't be installed in the specified install location.
*
* @hide
*/
@@ -1073,9 +1062,9 @@
public static final int INSTALL_FAILED_INVALID_INSTALL_LOCATION = -19;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package couldn't be installed
- * in the specified install location because the media is not available.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package couldn't be installed in the specified install location because the media
+ * is not available.
*
* @hide
*/
@@ -1083,9 +1072,8 @@
public static final int INSTALL_FAILED_MEDIA_UNAVAILABLE = -20;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package couldn't be installed
- * because the verification timed out.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package couldn't be installed because the verification timed out.
*
* @hide
*/
@@ -1093,9 +1081,8 @@
public static final int INSTALL_FAILED_VERIFICATION_TIMEOUT = -21;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package couldn't be installed
- * because the verification did not succeed.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package couldn't be installed because the verification did not succeed.
*
* @hide
*/
@@ -1103,9 +1090,8 @@
public static final int INSTALL_FAILED_VERIFICATION_FAILURE = -22;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the package changed from what the
- * calling program expected.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the package changed from what the calling program expected.
*
* @hide
*/
@@ -1113,28 +1099,25 @@
public static final int INSTALL_FAILED_PACKAGE_CHANGED = -23;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package is assigned a
- * different UID than it previously held.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package is assigned a different UID than it previously held.
*
* @hide
*/
public static final int INSTALL_FAILED_UID_CHANGED = -24;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package has an older version
- * code than the currently installed package.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package has an older version code than the currently installed package.
*
* @hide
*/
public static final int INSTALL_FAILED_VERSION_DOWNGRADE = -25;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the old package has target SDK high
- * enough to support runtime permission and the new package has target SDK
- * low enough to not support runtime permissions.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the old package has target SDK high enough to support runtime permission and the new
+ * package has target SDK low enough to not support runtime permissions.
*
* @hide
*/
@@ -1142,9 +1125,8 @@
public static final int INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE = -26;
/**
- * Installation return code: this is passed to the
- * {@link IPackageInstallObserver} if the new package attempts to downgrade the
- * target sandbox version of the app.
+ * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+ * if the new package attempts to downgrade the target sandbox version of the app.
*
* @hide
*/
@@ -1152,9 +1134,9 @@
public static final int INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE = -27;
/**
- * Installation parse return code: this is passed to the
- * {@link IPackageInstallObserver} if the parser was given a path that is
- * not a file, or does not end with the expected '.apk' extension.
+ * Installation parse return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the parser was given a path that is not a
+ * file, or does not end with the expected '.apk' extension.
*
* @hide
*/
@@ -1162,8 +1144,8 @@
public static final int INSTALL_PARSE_FAILED_NOT_APK = -100;
/**
- * Installation parse return code: this is passed to the
- * {@link IPackageInstallObserver} if the parser was unable to retrieve the
+ * Installation parse return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the parser was unable to retrieve the
* AndroidManifest.xml file.
*
* @hide
@@ -1172,8 +1154,8 @@
public static final int INSTALL_PARSE_FAILED_BAD_MANIFEST = -101;
/**
- * Installation parse return code: this is passed to the
- * {@link IPackageInstallObserver} if the parser encountered an unexpected
+ * Installation parse return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the parser encountered an unexpected
* exception.
*
* @hide
@@ -1182,9 +1164,9 @@
public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102;
/**
- * Installation parse return code: this is passed to the
- * {@link IPackageInstallObserver} if the parser did not find any
- * certificates in the .apk.
+ * Installation parse return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the parser did not find any certificates in
+ * the .apk.
*
* @hide
*/
@@ -1192,9 +1174,9 @@
public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103;
/**
- * Installation parse return code: this is passed to the
- * {@link IPackageInstallObserver} if the parser found inconsistent
- * certificates on the files in the .apk.
+ * Installation parse return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the parser found inconsistent certificates on
+ * the files in the .apk.
*
* @hide
*/
@@ -1202,8 +1184,8 @@
public static final int INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES = -104;
/**
- * Installation parse return code: this is passed to the
- * {@link IPackageInstallObserver} if the parser encountered a
+ * Installation parse return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the parser encountered a
* CertificateEncodingException in one of the files in the .apk.
*
* @hide
@@ -1212,9 +1194,9 @@
public static final int INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING = -105;
/**
- * Installation parse return code: this is passed to the
- * {@link IPackageInstallObserver} if the parser encountered a bad or
- * missing package name in the manifest.
+ * Installation parse return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the parser encountered a bad or missing
+ * package name in the manifest.
*
* @hide
*/
@@ -1222,9 +1204,9 @@
public static final int INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME = -106;
/**
- * Installation parse return code: this is passed to the
- * {@link IPackageInstallObserver} if the parser encountered a bad shared
- * user id name in the manifest.
+ * Installation parse return code: tthis is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the parser encountered a bad shared user id
+ * name in the manifest.
*
* @hide
*/
@@ -1232,8 +1214,8 @@
public static final int INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID = -107;
/**
- * Installation parse return code: this is passed to the
- * {@link IPackageInstallObserver} if the parser encountered some structural
+ * Installation parse return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the parser encountered some structural
* problem in the manifest.
*
* @hide
@@ -1242,9 +1224,9 @@
public static final int INSTALL_PARSE_FAILED_MANIFEST_MALFORMED = -108;
/**
- * Installation parse return code: this is passed to the
- * {@link IPackageInstallObserver} if the parser did not find any actionable
- * tags (instrumentation or application) in the manifest.
+ * Installation parse return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the parser did not find any actionable tags
+ * (instrumentation or application) in the manifest.
*
* @hide
*/
@@ -1252,9 +1234,9 @@
public static final int INSTALL_PARSE_FAILED_MANIFEST_EMPTY = -109;
/**
- * Installation failed return code: this is passed to the
- * {@link IPackageInstallObserver} if the system failed to install the
- * package because of system issues.
+ * Installation failed return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the system failed to install the package
+ * because of system issues.
*
* @hide
*/
@@ -1262,24 +1244,23 @@
public static final int INSTALL_FAILED_INTERNAL_ERROR = -110;
/**
- * Installation failed return code: this is passed to the
- * {@link IPackageInstallObserver} if the system failed to install the
- * package because the user is restricted from installing apps.
+ * Installation failed return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the system failed to install the package
+ * because the user is restricted from installing apps.
*
* @hide
*/
public static final int INSTALL_FAILED_USER_RESTRICTED = -111;
/**
- * Installation failed return code: this is passed to the
- * {@link IPackageInstallObserver} if the system failed to install the
- * package because it is attempting to define a permission that is already
- * defined by some existing package.
+ * Installation failed return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the system failed to install the package
+ * because it is attempting to define a permission that is already defined by some existing
+ * package.
* <p>
- * The package name of the app which has already defined the permission is
- * passed to a {@link PackageInstallObserver}, if any, as the
- * {@link #EXTRA_FAILURE_EXISTING_PACKAGE} string extra; and the name of the
- * permission being redefined is passed in the
+ * The package name of the app which has already defined the permission is passed to a
+ * {@link PackageInstallObserver}, if any, as the {@link #EXTRA_FAILURE_EXISTING_PACKAGE} string
+ * extra; and the name of the permission being redefined is passed in the
* {@link #EXTRA_FAILURE_EXISTING_PERMISSION} string extra.
*
* @hide
@@ -1287,10 +1268,9 @@
public static final int INSTALL_FAILED_DUPLICATE_PERMISSION = -112;
/**
- * Installation failed return code: this is passed to the
- * {@link IPackageInstallObserver} if the system failed to install the
- * package because its packaged native code did not match any of the ABIs
- * supported by the system.
+ * Installation failed return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the system failed to install the package
+ * because its packaged native code did not match any of the ABIs supported by the system.
*
* @hide
*/
@@ -4718,16 +4698,6 @@
@Deprecated
public abstract void installPackage(
Uri packageURI,
- IPackageInstallObserver observer,
- @InstallFlags int flags,
- String installerPackageName);
- /**
- * @deprecated replaced by {@link PackageInstaller}
- * @hide
- */
- @Deprecated
- public abstract void installPackage(
- Uri packageURI,
PackageInstallObserver observer,
@InstallFlags int flags,
String installerPackageName);
@@ -5743,25 +5713,6 @@
}
/** {@hide} */
- public static class LegacyPackageInstallObserver extends PackageInstallObserver {
- private final IPackageInstallObserver mLegacy;
-
- public LegacyPackageInstallObserver(IPackageInstallObserver legacy) {
- mLegacy = legacy;
- }
-
- @Override
- public void onPackageInstalled(String basePackageName, int returnCode, String msg,
- Bundle extras) {
- if (mLegacy == null) return;
- try {
- mLegacy.packageInstalled(basePackageName, returnCode);
- } catch (RemoteException ignored) {
- }
- }
- }
-
- /** {@hide} */
public static class LegacyPackageDeleteObserver extends PackageDeleteObserver {
private final IPackageDeleteObserver mLegacy;
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index d4699a8..49f357e 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -73,7 +73,7 @@
* {@link #onUpgrade} will be used to upgrade the database; if the database is
* newer, {@link #onDowngrade} will be used to downgrade the database
*/
- public SQLiteOpenHelper(@NonNull Context context, @Nullable String name,
+ public SQLiteOpenHelper(@Nullable Context context, @Nullable String name,
@Nullable CursorFactory factory, int version) {
this(context, name, factory, version, null);
}
@@ -95,7 +95,7 @@
* @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
* corruption, or null to use the default error handler.
*/
- public SQLiteOpenHelper(@NonNull Context context, @Nullable String name,
+ public SQLiteOpenHelper(@Nullable Context context, @Nullable String name,
@Nullable CursorFactory factory, int version,
@Nullable DatabaseErrorHandler errorHandler) {
this(context, name, factory, version, 0, errorHandler);
@@ -116,7 +116,7 @@
* Please note that {@link SQLiteDatabase#CREATE_IF_NECESSARY} flag will always be
* set when the helper opens the database
*/
- public SQLiteOpenHelper(@NonNull Context context, @Nullable String name, int version,
+ public SQLiteOpenHelper(@Nullable Context context, @Nullable String name, int version,
@NonNull SQLiteDatabase.OpenParams openParams) {
this(context, name, version, 0, openParams.toBuilder());
}
@@ -144,7 +144,7 @@
* @see #onUpgrade(SQLiteDatabase, int, int)
* @hide
*/
- public SQLiteOpenHelper(@NonNull Context context, @Nullable String name,
+ public SQLiteOpenHelper(@Nullable Context context, @Nullable String name,
@Nullable CursorFactory factory, int version,
int minimumSupportedVersion, @Nullable DatabaseErrorHandler errorHandler) {
this(context, name, version, minimumSupportedVersion,
@@ -153,10 +153,9 @@
mOpenParamsBuilder.setErrorHandler(errorHandler);
}
- private SQLiteOpenHelper(@NonNull Context context, @Nullable String name, int version,
+ private SQLiteOpenHelper(@Nullable Context context, @Nullable String name, int version,
int minimumSupportedVersion,
@NonNull SQLiteDatabase.OpenParams.Builder openParamsBuilder) {
- Preconditions.checkNotNull(context);
Preconditions.checkNotNull(openParamsBuilder);
if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 46ad3f0..3a3048e 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1280,11 +1280,11 @@
* <ul>
* <li>Processed (but stalling): any non-RAW format with a stallDurations > 0.
* Typically {@link android.graphics.ImageFormat#JPEG JPEG format}.</li>
- * <li>Raw formats: {@link android.graphics.ImageFormat#RAW_SENSOR RAW_SENSOR}, {@link android.graphics.ImageFormat#RAW10 RAW10}, or {@link android.graphics.ImageFormat#RAW12 RAW12}.</li>
- * <li>Processed (but not-stalling): any non-RAW format without a stall duration.
- * Typically {@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888},
- * {@link android.graphics.ImageFormat#NV21 NV21}, or
- * {@link android.graphics.ImageFormat#YV12 YV12}.</li>
+ * <li>Raw formats: {@link android.graphics.ImageFormat#RAW_SENSOR RAW_SENSOR}, {@link android.graphics.ImageFormat#RAW10 RAW10}, or
+ * {@link android.graphics.ImageFormat#RAW12 RAW12}.</li>
+ * <li>Processed (but not-stalling): any non-RAW format without a stall duration. Typically
+ * {@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888},
+ * {@link android.graphics.ImageFormat#NV21 NV21}, or {@link android.graphics.ImageFormat#YV12 YV12}.</li>
* </ul>
* <p><b>Range of valid values:</b><br></p>
* <p>For processed (and stalling) format streams, >= 1.</p>
@@ -1376,8 +1376,7 @@
* CPU resources that will consume more power. The image format for this kind of an output stream can
* be any non-<code>RAW</code> and supported format provided by {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}.</p>
* <p>A processed and stalling format is defined as any non-RAW format with a stallDurations
- * > 0. Typically only the {@link android.graphics.ImageFormat#JPEG JPEG format} is a
- * stalling format.</p>
+ * > 0. Typically only the {@link android.graphics.ImageFormat#JPEG JPEG format} is a stalling format.</p>
* <p>For full guarantees, query {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration } with a
* processed format -- it will return a non-0 value for a stalling stream.</p>
* <p>LEGACY devices will support up to 1 processing/stalling stream.</p>
@@ -1535,8 +1534,7 @@
new Key<int[]>("android.request.availableRequestKeys", int[].class);
/**
- * <p>A list of all keys that the camera device has available
- * to use with {@link android.hardware.camera2.CaptureResult }.</p>
+ * <p>A list of all keys that the camera device has available to use with {@link android.hardware.camera2.CaptureResult }.</p>
* <p>Attempting to get a key from a CaptureResult that is not
* listed here will always return a <code>null</code> value. Getting a key from
* a CaptureResult that is listed here will generally never return a <code>null</code>
@@ -1561,8 +1559,7 @@
new Key<int[]>("android.request.availableResultKeys", int[].class);
/**
- * <p>A list of all keys that the camera device has available
- * to use with {@link android.hardware.camera2.CameraCharacteristics }.</p>
+ * <p>A list of all keys that the camera device has available to use with {@link android.hardware.camera2.CameraCharacteristics }.</p>
* <p>This entry follows the same rules as
* android.request.availableResultKeys (except that it applies for
* CameraCharacteristics instead of CaptureResult). See above for more
@@ -1843,8 +1840,6 @@
* <p>See {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration} and
* android.scaler.availableStallDurations for more details about
* calculating the max frame rate.</p>
- * <p>(Keep in sync with
- * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration })</p>
* <p><b>Units</b>: (format, width, height, ns) x n</p>
* <p>This key is available on all devices.</p>
*
@@ -1905,14 +1900,13 @@
* <ul>
* <li>{@link android.graphics.ImageFormat#YUV_420_888 }</li>
* <li>{@link android.graphics.ImageFormat#RAW10 }</li>
+ * <li>{@link android.graphics.ImageFormat#RAW12 }</li>
* </ul>
* <p>All other formats may or may not have an allowed stall duration on
* a per-capability basis; refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
* for more details.</p>
* <p>See {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration} for more information about
* calculating the max frame rate (absent stalls).</p>
- * <p>(Keep up to date with
- * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration } )</p>
* <p><b>Units</b>: (format, width, height, ns) x n</p>
* <p>This key is available on all devices.</p>
*
@@ -2195,9 +2189,9 @@
* the raw buffers produced by this sensor.</p>
* <p>If a camera device supports raw sensor formats, either this or
* {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} is the maximum dimensions for the raw
- * output formats listed in {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} (this depends on
- * whether or not the image sensor returns buffers containing pixels that are not
- * part of the active array region for blacklevel calibration or other purposes).</p>
+ * output formats listed in {@link android.hardware.camera2.params.StreamConfigurationMap }
+ * (this depends on whether or not the image sensor returns buffers containing pixels that
+ * are not part of the active array region for blacklevel calibration or other purposes).</p>
* <p>Some parts of the full pixel array may not receive light from the scene,
* or be otherwise inactive. The {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} key
* defines the rectangle of active pixels that will be included in processed image
@@ -2205,7 +2199,6 @@
* <p><b>Units</b>: Pixels</p>
* <p>This key is available on all devices.</p>
*
- * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
* @see CameraCharacteristics#SENSOR_INFO_PHYSICAL_SIZE
* @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
*/
@@ -2838,7 +2831,7 @@
* <p>See the individual level enums for full descriptions of the supported capabilities. The
* {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} entry describes the device's capabilities at a
* finer-grain level, if needed. In addition, many controls have their available settings or
- * ranges defined in individual {@link android.hardware.camera2.CameraCharacteristics } entries.</p>
+ * ranges defined in individual entries from {@link android.hardware.camera2.CameraCharacteristics }.</p>
* <p>Some features are not part of any particular hardware level or capability and must be
* queried separately. These include:</p>
* <ul>
@@ -2973,7 +2966,6 @@
* <p>See {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration} and
* android.scaler.availableStallDurations for more details about
* calculating the max frame rate.</p>
- * <p>(Keep in sync with {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration })</p>
* <p><b>Units</b>: (format, width, height, ns) x n</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Limited capability</b> -
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 8c8c49f..4b57018 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -587,8 +587,8 @@
* then the list of resolutions for YUV_420_888 from {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes } contains at
* least one resolution >= 8 megapixels, with a minimum frame duration of <= 1/20
* s.</p>
- * <p>If the device supports the {@link android.graphics.ImageFormat#RAW10 }, {@link android.graphics.ImageFormat#RAW12 }, then those can also be captured at the same rate
- * as the maximum-size YUV_420_888 resolution is.</p>
+ * <p>If the device supports the {@link android.graphics.ImageFormat#RAW10 }, {@link android.graphics.ImageFormat#RAW12 }, then those can also be
+ * captured at the same rate as the maximum-size YUV_420_888 resolution is.</p>
* <p>If the device supports the PRIVATE_REPROCESSING capability, then the same guarantees
* as for the YUV_420_888 format also apply to the {@link android.graphics.ImageFormat#PRIVATE } format.</p>
* <p>In addition, the {@link CameraCharacteristics#SYNC_MAX_LATENCY android.sync.maxLatency} field is guaranted to have a value between 0
@@ -610,25 +610,22 @@
* following:</p>
* <ul>
* <li>One input stream is supported, that is, <code>{@link CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS android.request.maxNumInputStreams} == 1</code>.</li>
- * <li>{@link android.graphics.ImageFormat#YUV_420_888 } is supported as an output/input format, that is,
- * YUV_420_888 is included in the lists of formats returned by
- * {@link android.hardware.camera2.params.StreamConfigurationMap#getInputFormats } and
- * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputFormats }.</li>
+ * <li>{@link android.graphics.ImageFormat#YUV_420_888 } is supported as an output/input
+ * format, that is, YUV_420_888 is included in the lists of formats returned by {@link android.hardware.camera2.params.StreamConfigurationMap#getInputFormats } and {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputFormats }.</li>
* <li>{@link android.hardware.camera2.params.StreamConfigurationMap#getValidOutputFormatsForInput }
* returns non-empty int[] for each supported input format returned by {@link android.hardware.camera2.params.StreamConfigurationMap#getInputFormats }.</li>
* <li>Each size returned by {@link android.hardware.camera2.params.StreamConfigurationMap#getInputSizes getInputSizes(YUV_420_888)} is also included in {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes getOutputSizes(YUV_420_888)}</li>
- * <li>Using {@link android.graphics.ImageFormat#YUV_420_888 } does not cause a frame rate drop
- * relative to the sensor's maximum capture rate (at that resolution).</li>
+ * <li>Using {@link android.graphics.ImageFormat#YUV_420_888 } does not cause a frame rate
+ * drop relative to the sensor's maximum capture rate (at that resolution).</li>
* <li>{@link android.graphics.ImageFormat#YUV_420_888 } will be reprocessable into both
* {@link android.graphics.ImageFormat#YUV_420_888 } and {@link android.graphics.ImageFormat#JPEG } formats.</li>
* <li>The maximum available resolution for {@link android.graphics.ImageFormat#YUV_420_888 } streams (both input/output) will match the
* maximum available resolution of {@link android.graphics.ImageFormat#JPEG } streams.</li>
* <li>Static metadata {@link CameraCharacteristics#REPROCESS_MAX_CAPTURE_STALL android.reprocess.maxCaptureStall}.</li>
* <li>Only the below controls are effective for reprocessing requests and will be present
- * in capture results. The reprocess requests are from the original capture results that
- * are associated with the intermediate {@link android.graphics.ImageFormat#YUV_420_888 }
- * output buffers. All other controls in the reprocess requests will be ignored by the
- * camera device.<ul>
+ * in capture results. The reprocess requests are from the original capture results
+ * that are associated with the intermediate {@link android.graphics.ImageFormat#YUV_420_888 } output buffers. All other controls in the
+ * reprocess requests will be ignored by the camera device.<ul>
* <li>android.jpeg.*</li>
* <li>{@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}</li>
* <li>{@link CaptureRequest#EDGE_MODE android.edge.mode}</li>
@@ -654,13 +651,13 @@
* <p>The camera device can produce depth measurements from its field of view.</p>
* <p>This capability requires the camera device to support the following:</p>
* <ul>
- * <li>{@link android.graphics.ImageFormat#DEPTH16 } is supported as an output format.</li>
- * <li>{@link android.graphics.ImageFormat#DEPTH_POINT_CLOUD } is optionally supported as an
- * output format.</li>
- * <li>This camera device, and all camera devices with the same {@link CameraCharacteristics#LENS_FACING android.lens.facing},
- * will list the following calibration entries in both
- * {@link android.hardware.camera2.CameraCharacteristics } and
- * {@link android.hardware.camera2.CaptureResult }:<ul>
+ * <li>{@link android.graphics.ImageFormat#DEPTH16 } is supported as
+ * an output format.</li>
+ * <li>{@link android.graphics.ImageFormat#DEPTH_POINT_CLOUD } is
+ * optionally supported as an output format.</li>
+ * <li>This camera device, and all camera devices with the same {@link CameraCharacteristics#LENS_FACING android.lens.facing}, will
+ * list the following calibration metadata entries in both {@link android.hardware.camera2.CameraCharacteristics }
+ * and {@link android.hardware.camera2.CaptureResult }:<ul>
* <li>{@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}</li>
* <li>{@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}</li>
* <li>{@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration}</li>
@@ -674,8 +671,7 @@
* </ul>
* <p>Generally, depth output operates at a slower frame rate than standard color capture,
* so the DEPTH16 and DEPTH_POINT_CLOUD formats will commonly have a stall duration that
- * should be accounted for (see
- * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }).
+ * should be accounted for (see {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }).
* On a device that supports both depth and color-based output, to enable smooth preview,
* using a repeating burst is recommended, where a depth-output target is only included
* once every N frames, where N is the ratio between preview output rate and depth output
@@ -692,23 +688,19 @@
public static final int REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT = 8;
/**
- * <p>The device supports constrained high speed video recording (frame rate >=120fps)
- * use case. The camera device will support high speed capture session created by
- * {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedCaptureSession }, which
- * only accepts high speed request lists created by
- * {@link android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession#createHighSpeedRequestList }.</p>
- * <p>A camera device can still support high speed video streaming by advertising the high speed
- * FPS ranges in {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges}. For this case, all normal
- * capture request per frame control and synchronization requirements will apply to
- * the high speed fps ranges, the same as all other fps ranges. This capability describes
- * the capability of a specialized operating mode with many limitations (see below), which
- * is only targeted at high speed video recording.</p>
- * <p>The supported high speed video sizes and fps ranges are specified in
- * {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoFpsRanges }.
- * To get desired output frame rates, the application is only allowed to select video size
- * and FPS range combinations provided by
- * {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoSizes }.
- * The fps range can be controlled via {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE android.control.aeTargetFpsRange}.</p>
+ * <p>The device supports constrained high speed video recording (frame rate >=120fps) use
+ * case. The camera device will support high speed capture session created by {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedCaptureSession }, which
+ * only accepts high speed request lists created by {@link android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession#createHighSpeedRequestList }.</p>
+ * <p>A camera device can still support high speed video streaming by advertising the high
+ * speed FPS ranges in {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges}. For this case, all
+ * normal capture request per frame control and synchronization requirements will apply
+ * to the high speed fps ranges, the same as all other fps ranges. This capability
+ * describes the capability of a specialized operating mode with many limitations (see
+ * below), which is only targeted at high speed video recording.</p>
+ * <p>The supported high speed video sizes and fps ranges are specified in {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoFpsRanges }.
+ * To get desired output frame rates, the application is only allowed to select video
+ * size and FPS range combinations provided by {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoSizes }. The
+ * fps range can be controlled via {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE android.control.aeTargetFpsRange}.</p>
* <p>In this capability, the camera device will override aeMode, awbMode, and afMode to
* ON, AUTO, and CONTINUOUS_VIDEO, respectively. All post-processing block mode
* controls will be overridden to be FAST. Therefore, no manual control of capture
@@ -743,19 +735,16 @@
* frame rate. If the destination surface is from preview window, the actual preview frame
* rate will be bounded by the screen refresh rate.</p>
* <p>The camera device will only support up to 2 high speed simultaneous output surfaces
- * (preview and recording surfaces)
- * in this mode. Above controls will be effective only if all of below conditions are true:</p>
+ * (preview and recording surfaces) in this mode. Above controls will be effective only
+ * if all of below conditions are true:</p>
* <ul>
* <li>The application creates a camera capture session with no more than 2 surfaces via
* {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedCaptureSession }. The
- * targeted surfaces must be preview surface (either from
- * {@link android.view.SurfaceView } or {@link android.graphics.SurfaceTexture }) or
- * recording surface(either from {@link android.media.MediaRecorder#getSurface } or
- * {@link android.media.MediaCodec#createInputSurface }).</li>
+ * targeted surfaces must be preview surface (either from {@link android.view.SurfaceView } or {@link android.graphics.SurfaceTexture }) or recording
+ * surface(either from {@link android.media.MediaRecorder#getSurface } or {@link android.media.MediaCodec#createInputSurface }).</li>
* <li>The stream sizes are selected from the sizes reported by
* {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoSizes }.</li>
- * <li>The FPS ranges are selected from
- * {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoFpsRanges }.</li>
+ * <li>The FPS ranges are selected from {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoFpsRanges }.</li>
* </ul>
* <p>When above conditions are NOT satistied,
* {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedCaptureSession }
@@ -1038,8 +1027,7 @@
/**
* <p>This camera device is running in backward compatibility mode.</p>
- * <p>Only the stream configurations listed in the <code>LEGACY</code> table in the {@link android.hardware.camera2.CameraDevice#createCaptureSession createCaptureSession}
- * documentation are supported.</p>
+ * <p>Only the stream configurations listed in the <code>LEGACY</code> table in the {@link android.hardware.camera2.CameraDevice#createCaptureSession createCaptureSession} documentation are supported.</p>
* <p>A <code>LEGACY</code> device does not support per-frame control, manual sensor control, manual
* post-processing, arbitrary cropping regions, and has relaxed performance constraints.
* No additional capabilities beyond <code>BACKWARD_COMPATIBLE</code> will ever be listed by a
@@ -1061,8 +1049,7 @@
* <p>This camera device is capable of YUV reprocessing and RAW data capture, in addition to
* FULL-level capabilities.</p>
* <p>The stream configurations listed in the <code>LEVEL_3</code>, <code>RAW</code>, <code>FULL</code>, <code>LEGACY</code> and
- * <code>LIMITED</code> tables in the {@link android.hardware.camera2.CameraDevice#createCaptureSession createCaptureSession}
- * documentation are guaranteed to be supported.</p>
+ * <code>LIMITED</code> tables in the {@link android.hardware.camera2.CameraDevice#createCaptureSession createCaptureSession} documentation are guaranteed to be supported.</p>
* <p>The following additional capabilities are guaranteed to be supported:</p>
* <ul>
* <li><code>YUV_REPROCESSING</code> capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains
@@ -2155,12 +2142,13 @@
public static final int EDGE_MODE_HIGH_QUALITY = 2;
/**
- * <p>Edge enhancement is applied at different levels for different output streams,
- * based on resolution. Streams at maximum recording resolution (see {@link android.hardware.camera2.CameraDevice#createCaptureSession }) or below have
- * edge enhancement applied, while higher-resolution streams have no edge enhancement
- * applied. The level of edge enhancement for low-resolution streams is tuned so that
- * frame rate is not impacted, and the quality is equal to or better than FAST (since it
- * is only applied to lower-resolution outputs, quality may improve from FAST).</p>
+ * <p>Edge enhancement is applied at different
+ * levels for different output streams, based on resolution. Streams at maximum recording
+ * resolution (see {@link android.hardware.camera2.CameraDevice#createCaptureSession })
+ * or below have edge enhancement applied, while higher-resolution streams have no edge
+ * enhancement applied. The level of edge enhancement for low-resolution streams is tuned
+ * so that frame rate is not impacted, and the quality is equal to or better than FAST
+ * (since it is only applied to lower-resolution outputs, quality may improve from FAST).</p>
* <p>This mode is intended to be used by applications operating in a zero-shutter-lag mode
* with YUV or PRIVATE reprocessing, where the application continuously captures
* high-resolution intermediate buffers into a circular buffer, from which a final image is
@@ -2287,12 +2275,12 @@
/**
* <p>Noise reduction is applied at different levels for different output streams,
- * based on resolution. Streams at maximum recording resolution (see {@link android.hardware.camera2.CameraDevice#createCaptureSession }) or below have noise
- * reduction applied, while higher-resolution streams have MINIMAL (if supported) or no
- * noise reduction applied (if MINIMAL is not supported.) The degree of noise reduction
- * for low-resolution streams is tuned so that frame rate is not impacted, and the quality
- * is equal to or better than FAST (since it is only applied to lower-resolution outputs,
- * quality may improve from FAST).</p>
+ * based on resolution. Streams at maximum recording resolution (see {@link android.hardware.camera2.CameraDevice#createCaptureSession })
+ * or below have noise reduction applied, while higher-resolution streams have MINIMAL (if
+ * supported) or no noise reduction applied (if MINIMAL is not supported.) The degree of
+ * noise reduction for low-resolution streams is tuned so that frame rate is not impacted,
+ * and the quality is equal to or better than FAST (since it is only applied to
+ * lower-resolution outputs, quality may improve from FAST).</p>
* <p>This mode is intended to be used by applications operating in a zero-shutter-lag mode
* with YUV or PRIVATE reprocessing, where the application continuously captures
* high-resolution intermediate buffers into a circular buffer, from which a final image is
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index c41fc02..0262ecb 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -680,7 +680,7 @@
* FAST or HIGH_QUALITY will yield a picture with the same white point
* as what was produced by the camera device in the earlier frame.</p>
* <p>The expected processing pipeline is as follows:</p>
- * <p><img alt="White balance processing pipeline" src="../../../../images/camera2/metadata/android.colorCorrection.mode/processing_pipeline.png" /></p>
+ * <p><img alt="White balance processing pipeline" src="/reference/images/camera2/metadata/android.colorCorrection.mode/processing_pipeline.png" /></p>
* <p>The white balance is encoded by two values, a 4-channel white-balance
* gain vector (applied in the Bayer domain), and a 3x3 color transform
* matrix (applied after demosaic).</p>
@@ -1470,10 +1470,10 @@
* <p>When set to AUTO, the individual algorithm controls in
* android.control.* are in effect, such as {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}.</p>
* <p>When set to USE_SCENE_MODE, the individual controls in
- * android.control.* are mostly disabled, and the camera device implements
- * one of the scene mode settings (such as ACTION, SUNSET, or PARTY)
- * as it wishes. The camera device scene mode 3A settings are provided by
- * {@link android.hardware.camera2.CaptureResult capture results}.</p>
+ * android.control.* are mostly disabled, and the camera device
+ * implements one of the scene mode settings (such as ACTION,
+ * SUNSET, or PARTY) as it wishes. The camera device scene mode
+ * 3A settings are provided by {@link android.hardware.camera2.CaptureResult capture results}.</p>
* <p>When set to OFF_KEEP_STATE, it is similar to OFF mode, the only difference
* is that this frame will not be used by camera device background 3A statistics
* update, as if this frame is never captured. This mode can be used in the scenario
@@ -2268,45 +2268,35 @@
* can run concurrently to the rest of the camera pipeline, but
* cannot process more than 1 capture at a time.</li>
* </ul>
- * <p>The necessary information for the application, given the model above,
- * is provided via the {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} field using
+ * <p>The necessary information for the application, given the model above, is provided via
* {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration }.
- * These are used to determine the maximum frame rate / minimum frame
- * duration that is possible for a given stream configuration.</p>
+ * These are used to determine the maximum frame rate / minimum frame duration that is
+ * possible for a given stream configuration.</p>
* <p>Specifically, the application can use the following rules to
* determine the minimum frame duration it can request from the camera
* device:</p>
* <ol>
- * <li>Let the set of currently configured input/output streams
- * be called <code>S</code>.</li>
- * <li>Find the minimum frame durations for each stream in <code>S</code>, by looking
- * it up in {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} using {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration }
- * (with its respective size/format). Let this set of frame durations be
- * called <code>F</code>.</li>
- * <li>For any given request <code>R</code>, the minimum frame duration allowed
- * for <code>R</code> is the maximum out of all values in <code>F</code>. Let the streams
- * used in <code>R</code> be called <code>S_r</code>.</li>
+ * <li>Let the set of currently configured input/output streams be called <code>S</code>.</li>
+ * <li>Find the minimum frame durations for each stream in <code>S</code>, by looking it up in {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration }
+ * (with its respective size/format). Let this set of frame durations be called <code>F</code>.</li>
+ * <li>For any given request <code>R</code>, the minimum frame duration allowed for <code>R</code> is the maximum
+ * out of all values in <code>F</code>. Let the streams used in <code>R</code> be called <code>S_r</code>.</li>
* </ol>
* <p>If none of the streams in <code>S_r</code> have a stall time (listed in {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }
- * using its respective size/format), then the frame duration in <code>F</code>
- * determines the steady state frame rate that the application will get
- * if it uses <code>R</code> as a repeating request. Let this special kind of
- * request be called <code>Rsimple</code>.</p>
- * <p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved
- * by a single capture of a new request <code>Rstall</code> (which has at least
- * one in-use stream with a non-0 stall time) and if <code>Rstall</code> has the
- * same minimum frame duration this will not cause a frame rate loss
- * if all buffers from the previous <code>Rstall</code> have already been
- * delivered.</p>
- * <p>For more details about stalling, see
- * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }.</p>
+ * using its respective size/format), then the frame duration in <code>F</code> determines the steady
+ * state frame rate that the application will get if it uses <code>R</code> as a repeating request. Let
+ * this special kind of request be called <code>Rsimple</code>.</p>
+ * <p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved by a single capture of a
+ * new request <code>Rstall</code> (which has at least one in-use stream with a non-0 stall time) and if
+ * <code>Rstall</code> has the same minimum frame duration this will not cause a frame rate loss if all
+ * buffers from the previous <code>Rstall</code> have already been delivered.</p>
+ * <p>For more details about stalling, see {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }.</p>
* <p>This control is only effective if {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} or {@link CaptureRequest#CONTROL_MODE android.control.mode} is set to
* OFF; otherwise the auto-exposure algorithm will override this value.</p>
* <p><b>Units</b>: Nanoseconds</p>
* <p><b>Range of valid values:</b><br>
- * See {@link CameraCharacteristics#SENSOR_INFO_MAX_FRAME_DURATION android.sensor.info.maxFrameDuration},
- * {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}. The duration
- * is capped to <code>max(duration, exposureTime + overhead)</code>.</p>
+ * See {@link CameraCharacteristics#SENSOR_INFO_MAX_FRAME_DURATION android.sensor.info.maxFrameDuration}, {@link android.hardware.camera2.params.StreamConfigurationMap }.
+ * The duration is capped to <code>max(duration, exposureTime + overhead)</code>.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Full capability</b> -
* Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
@@ -2315,7 +2305,6 @@
* @see CaptureRequest#CONTROL_AE_MODE
* @see CaptureRequest#CONTROL_MODE
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
- * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
* @see CameraCharacteristics#SENSOR_INFO_MAX_FRAME_DURATION
*/
@PublicKey
@@ -2584,11 +2573,11 @@
* <p>Linear mapping:</p>
* <pre><code>android.tonemap.curveRed = [ 0, 0, 1.0, 1.0 ]
* </code></pre>
- * <p><img alt="Linear mapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png" /></p>
+ * <p><img alt="Linear mapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png" /></p>
* <p>Invert mapping:</p>
* <pre><code>android.tonemap.curveRed = [ 0, 1.0, 1.0, 0 ]
* </code></pre>
- * <p><img alt="Inverting mapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png" /></p>
+ * <p><img alt="Inverting mapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png" /></p>
* <p>Gamma 1/2.2 mapping, with 16 control points:</p>
* <pre><code>android.tonemap.curveRed = [
* 0.0000, 0.0000, 0.0667, 0.2920, 0.1333, 0.4002, 0.2000, 0.4812,
@@ -2596,7 +2585,7 @@
* 0.5333, 0.7515, 0.6000, 0.7928, 0.6667, 0.8317, 0.7333, 0.8685,
* 0.8000, 0.9035, 0.8667, 0.9370, 0.9333, 0.9691, 1.0000, 1.0000 ]
* </code></pre>
- * <p><img alt="Gamma = 1/2.2 tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png" /></p>
+ * <p><img alt="Gamma = 1/2.2 tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png" /></p>
* <p>Standard sRGB gamma mapping, per IEC 61966-2-1:1999, with 16 control points:</p>
* <pre><code>android.tonemap.curveRed = [
* 0.0000, 0.0000, 0.0667, 0.2864, 0.1333, 0.4007, 0.2000, 0.4845,
@@ -2604,7 +2593,7 @@
* 0.5333, 0.7569, 0.6000, 0.7977, 0.6667, 0.8360, 0.7333, 0.8721,
* 0.8000, 0.9063, 0.8667, 0.9389, 0.9333, 0.9701, 1.0000, 1.0000 ]
* </code></pre>
- * <p><img alt="sRGB tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png" /></p>
+ * <p><img alt="sRGB tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png" /></p>
* <p><b>Range of valid values:</b><br>
* 0-1 on both input and output coordinates, normalized
* as a floating-point value such that 0 == black and 1 == white.</p>
@@ -2646,11 +2635,11 @@
* <p>Linear mapping:</p>
* <pre><code>curveRed = [ (0, 0), (1.0, 1.0) ]
* </code></pre>
- * <p><img alt="Linear mapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png" /></p>
+ * <p><img alt="Linear mapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png" /></p>
* <p>Invert mapping:</p>
* <pre><code>curveRed = [ (0, 1.0), (1.0, 0) ]
* </code></pre>
- * <p><img alt="Inverting mapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png" /></p>
+ * <p><img alt="Inverting mapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png" /></p>
* <p>Gamma 1/2.2 mapping, with 16 control points:</p>
* <pre><code>curveRed = [
* (0.0000, 0.0000), (0.0667, 0.2920), (0.1333, 0.4002), (0.2000, 0.4812),
@@ -2658,7 +2647,7 @@
* (0.5333, 0.7515), (0.6000, 0.7928), (0.6667, 0.8317), (0.7333, 0.8685),
* (0.8000, 0.9035), (0.8667, 0.9370), (0.9333, 0.9691), (1.0000, 1.0000) ]
* </code></pre>
- * <p><img alt="Gamma = 1/2.2 tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png" /></p>
+ * <p><img alt="Gamma = 1/2.2 tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png" /></p>
* <p>Standard sRGB gamma mapping, per IEC 61966-2-1:1999, with 16 control points:</p>
* <pre><code>curveRed = [
* (0.0000, 0.0000), (0.0667, 0.2864), (0.1333, 0.4007), (0.2000, 0.4845),
@@ -2666,7 +2655,7 @@
* (0.5333, 0.7569), (0.6000, 0.7977), (0.6667, 0.8360), (0.7333, 0.8721),
* (0.8000, 0.9063), (0.8667, 0.9389), (0.9333, 0.9701), (1.0000, 1.0000) ]
* </code></pre>
- * <p><img alt="sRGB tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png" /></p>
+ * <p><img alt="sRGB tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png" /></p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Full capability</b> -
* Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
@@ -2756,9 +2745,9 @@
* PRESET_CURVE</p>
* <p>The tonemap curve will be defined by specified standard.</p>
* <p>sRGB (approximated by 16 control points):</p>
- * <p><img alt="sRGB tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png" /></p>
+ * <p><img alt="sRGB tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png" /></p>
* <p>Rec. 709 (approximated by 16 control points):</p>
- * <p><img alt="Rec. 709 tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png" /></p>
+ * <p><img alt="Rec. 709 tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png" /></p>
* <p>Note that above figures show a 16 control points approximation of preset
* curves. Camera devices may apply a different approximation to the curve.</p>
* <p><b>Possible values:</b>
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 6d80c20..cfad098 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -390,7 +390,7 @@
* FAST or HIGH_QUALITY will yield a picture with the same white point
* as what was produced by the camera device in the earlier frame.</p>
* <p>The expected processing pipeline is as follows:</p>
- * <p><img alt="White balance processing pipeline" src="../../../../images/camera2/metadata/android.colorCorrection.mode/processing_pipeline.png" /></p>
+ * <p><img alt="White balance processing pipeline" src="/reference/images/camera2/metadata/android.colorCorrection.mode/processing_pipeline.png" /></p>
* <p>The white balance is encoded by two values, a 4-channel white-balance
* gain vector (applied in the Bayer domain), and a 3x3 color transform
* matrix (applied after demosaic).</p>
@@ -1975,10 +1975,10 @@
* <p>When set to AUTO, the individual algorithm controls in
* android.control.* are in effect, such as {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}.</p>
* <p>When set to USE_SCENE_MODE, the individual controls in
- * android.control.* are mostly disabled, and the camera device implements
- * one of the scene mode settings (such as ACTION, SUNSET, or PARTY)
- * as it wishes. The camera device scene mode 3A settings are provided by
- * {@link android.hardware.camera2.CaptureResult capture results}.</p>
+ * android.control.* are mostly disabled, and the camera device
+ * implements one of the scene mode settings (such as ACTION,
+ * SUNSET, or PARTY) as it wishes. The camera device scene mode
+ * 3A settings are provided by {@link android.hardware.camera2.CaptureResult capture results}.</p>
* <p>When set to OFF_KEEP_STATE, it is similar to OFF mode, the only difference
* is that this frame will not be used by camera device background 3A statistics
* update, as if this frame is never captured. This mode can be used in the scenario
@@ -3108,45 +3108,35 @@
* can run concurrently to the rest of the camera pipeline, but
* cannot process more than 1 capture at a time.</li>
* </ul>
- * <p>The necessary information for the application, given the model above,
- * is provided via the {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} field using
+ * <p>The necessary information for the application, given the model above, is provided via
* {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration }.
- * These are used to determine the maximum frame rate / minimum frame
- * duration that is possible for a given stream configuration.</p>
+ * These are used to determine the maximum frame rate / minimum frame duration that is
+ * possible for a given stream configuration.</p>
* <p>Specifically, the application can use the following rules to
* determine the minimum frame duration it can request from the camera
* device:</p>
* <ol>
- * <li>Let the set of currently configured input/output streams
- * be called <code>S</code>.</li>
- * <li>Find the minimum frame durations for each stream in <code>S</code>, by looking
- * it up in {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} using {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration }
- * (with its respective size/format). Let this set of frame durations be
- * called <code>F</code>.</li>
- * <li>For any given request <code>R</code>, the minimum frame duration allowed
- * for <code>R</code> is the maximum out of all values in <code>F</code>. Let the streams
- * used in <code>R</code> be called <code>S_r</code>.</li>
+ * <li>Let the set of currently configured input/output streams be called <code>S</code>.</li>
+ * <li>Find the minimum frame durations for each stream in <code>S</code>, by looking it up in {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration }
+ * (with its respective size/format). Let this set of frame durations be called <code>F</code>.</li>
+ * <li>For any given request <code>R</code>, the minimum frame duration allowed for <code>R</code> is the maximum
+ * out of all values in <code>F</code>. Let the streams used in <code>R</code> be called <code>S_r</code>.</li>
* </ol>
* <p>If none of the streams in <code>S_r</code> have a stall time (listed in {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }
- * using its respective size/format), then the frame duration in <code>F</code>
- * determines the steady state frame rate that the application will get
- * if it uses <code>R</code> as a repeating request. Let this special kind of
- * request be called <code>Rsimple</code>.</p>
- * <p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved
- * by a single capture of a new request <code>Rstall</code> (which has at least
- * one in-use stream with a non-0 stall time) and if <code>Rstall</code> has the
- * same minimum frame duration this will not cause a frame rate loss
- * if all buffers from the previous <code>Rstall</code> have already been
- * delivered.</p>
- * <p>For more details about stalling, see
- * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }.</p>
+ * using its respective size/format), then the frame duration in <code>F</code> determines the steady
+ * state frame rate that the application will get if it uses <code>R</code> as a repeating request. Let
+ * this special kind of request be called <code>Rsimple</code>.</p>
+ * <p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved by a single capture of a
+ * new request <code>Rstall</code> (which has at least one in-use stream with a non-0 stall time) and if
+ * <code>Rstall</code> has the same minimum frame duration this will not cause a frame rate loss if all
+ * buffers from the previous <code>Rstall</code> have already been delivered.</p>
+ * <p>For more details about stalling, see {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }.</p>
* <p>This control is only effective if {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} or {@link CaptureRequest#CONTROL_MODE android.control.mode} is set to
* OFF; otherwise the auto-exposure algorithm will override this value.</p>
* <p><b>Units</b>: Nanoseconds</p>
* <p><b>Range of valid values:</b><br>
- * See {@link CameraCharacteristics#SENSOR_INFO_MAX_FRAME_DURATION android.sensor.info.maxFrameDuration},
- * {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}. The duration
- * is capped to <code>max(duration, exposureTime + overhead)</code>.</p>
+ * See {@link CameraCharacteristics#SENSOR_INFO_MAX_FRAME_DURATION android.sensor.info.maxFrameDuration}, {@link android.hardware.camera2.params.StreamConfigurationMap }.
+ * The duration is capped to <code>max(duration, exposureTime + overhead)</code>.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Full capability</b> -
* Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
@@ -3155,7 +3145,6 @@
* @see CaptureRequest#CONTROL_AE_MODE
* @see CaptureRequest#CONTROL_MODE
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
- * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
* @see CameraCharacteristics#SENSOR_INFO_MAX_FRAME_DURATION
*/
@PublicKey
@@ -3408,9 +3397,8 @@
* layout key (see {@link CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT android.sensor.info.colorFilterArrangement}), i.e. the
* nth value given corresponds to the black level offset for the nth
* color channel listed in the CFA.</p>
- * <p>This key will be available if {@link CameraCharacteristics#SENSOR_OPTICAL_BLACK_REGIONS android.sensor.opticalBlackRegions} is
- * available or the camera device advertises this key via
- * {@link android.hardware.camera2.CameraCharacteristics#getAvailableCaptureResultKeys }.</p>
+ * <p>This key will be available if {@link CameraCharacteristics#SENSOR_OPTICAL_BLACK_REGIONS android.sensor.opticalBlackRegions} is available or the
+ * camera device advertises this key via {@link android.hardware.camera2.CameraCharacteristics#getAvailableCaptureResultKeys }.</p>
* <p><b>Range of valid values:</b><br>
* >= 0 for each.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
@@ -3640,13 +3628,13 @@
* </code></pre>
* <p>The low-resolution scaling map images for each channel are
* (displayed using nearest-neighbor interpolation):</p>
- * <p><img alt="Red lens shading map" src="../../../../images/camera2/metadata/android.statistics.lensShadingMap/red_shading.png" />
- * <img alt="Green (even rows) lens shading map" src="../../../../images/camera2/metadata/android.statistics.lensShadingMap/green_e_shading.png" />
- * <img alt="Green (odd rows) lens shading map" src="../../../../images/camera2/metadata/android.statistics.lensShadingMap/green_o_shading.png" />
- * <img alt="Blue lens shading map" src="../../../../images/camera2/metadata/android.statistics.lensShadingMap/blue_shading.png" /></p>
+ * <p><img alt="Red lens shading map" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/red_shading.png" />
+ * <img alt="Green (even rows) lens shading map" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/green_e_shading.png" />
+ * <img alt="Green (odd rows) lens shading map" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/green_o_shading.png" />
+ * <img alt="Blue lens shading map" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/blue_shading.png" /></p>
* <p>As a visualization only, inverting the full-color map to recover an
* image of a gray wall (using bicubic interpolation for visual quality) as captured by the sensor gives:</p>
- * <p><img alt="Image of a uniform white wall (inverse shading map)" src="../../../../images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png" /></p>
+ * <p><img alt="Image of a uniform white wall (inverse shading map)" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png" /></p>
* <p><b>Range of valid values:</b><br>
* Each gain factor is >= 1</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
@@ -3707,14 +3695,14 @@
* </code></pre>
* <p>The low-resolution scaling map images for each channel are
* (displayed using nearest-neighbor interpolation):</p>
- * <p><img alt="Red lens shading map" src="../../../../images/camera2/metadata/android.statistics.lensShadingMap/red_shading.png" />
- * <img alt="Green (even rows) lens shading map" src="../../../../images/camera2/metadata/android.statistics.lensShadingMap/green_e_shading.png" />
- * <img alt="Green (odd rows) lens shading map" src="../../../../images/camera2/metadata/android.statistics.lensShadingMap/green_o_shading.png" />
- * <img alt="Blue lens shading map" src="../../../../images/camera2/metadata/android.statistics.lensShadingMap/blue_shading.png" /></p>
+ * <p><img alt="Red lens shading map" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/red_shading.png" />
+ * <img alt="Green (even rows) lens shading map" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/green_e_shading.png" />
+ * <img alt="Green (odd rows) lens shading map" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/green_o_shading.png" />
+ * <img alt="Blue lens shading map" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/blue_shading.png" /></p>
* <p>As a visualization only, inverting the full-color map to recover an
* image of a gray wall (using bicubic interpolation for visual quality)
* as captured by the sensor gives:</p>
- * <p><img alt="Image of a uniform white wall (inverse shading map)" src="../../../../images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png" /></p>
+ * <p><img alt="Image of a uniform white wall (inverse shading map)" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png" /></p>
* <p>Note that the RAW image data might be subject to lens shading
* correction not reported on this map. Query
* {@link CameraCharacteristics#SENSOR_INFO_LENS_SHADING_APPLIED android.sensor.info.lensShadingApplied} to see if RAW image data has subject
@@ -3947,11 +3935,11 @@
* <p>Linear mapping:</p>
* <pre><code>android.tonemap.curveRed = [ 0, 0, 1.0, 1.0 ]
* </code></pre>
- * <p><img alt="Linear mapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png" /></p>
+ * <p><img alt="Linear mapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png" /></p>
* <p>Invert mapping:</p>
* <pre><code>android.tonemap.curveRed = [ 0, 1.0, 1.0, 0 ]
* </code></pre>
- * <p><img alt="Inverting mapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png" /></p>
+ * <p><img alt="Inverting mapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png" /></p>
* <p>Gamma 1/2.2 mapping, with 16 control points:</p>
* <pre><code>android.tonemap.curveRed = [
* 0.0000, 0.0000, 0.0667, 0.2920, 0.1333, 0.4002, 0.2000, 0.4812,
@@ -3959,7 +3947,7 @@
* 0.5333, 0.7515, 0.6000, 0.7928, 0.6667, 0.8317, 0.7333, 0.8685,
* 0.8000, 0.9035, 0.8667, 0.9370, 0.9333, 0.9691, 1.0000, 1.0000 ]
* </code></pre>
- * <p><img alt="Gamma = 1/2.2 tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png" /></p>
+ * <p><img alt="Gamma = 1/2.2 tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png" /></p>
* <p>Standard sRGB gamma mapping, per IEC 61966-2-1:1999, with 16 control points:</p>
* <pre><code>android.tonemap.curveRed = [
* 0.0000, 0.0000, 0.0667, 0.2864, 0.1333, 0.4007, 0.2000, 0.4845,
@@ -3967,7 +3955,7 @@
* 0.5333, 0.7569, 0.6000, 0.7977, 0.6667, 0.8360, 0.7333, 0.8721,
* 0.8000, 0.9063, 0.8667, 0.9389, 0.9333, 0.9701, 1.0000, 1.0000 ]
* </code></pre>
- * <p><img alt="sRGB tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png" /></p>
+ * <p><img alt="sRGB tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png" /></p>
* <p><b>Range of valid values:</b><br>
* 0-1 on both input and output coordinates, normalized
* as a floating-point value such that 0 == black and 1 == white.</p>
@@ -4009,11 +3997,11 @@
* <p>Linear mapping:</p>
* <pre><code>curveRed = [ (0, 0), (1.0, 1.0) ]
* </code></pre>
- * <p><img alt="Linear mapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png" /></p>
+ * <p><img alt="Linear mapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png" /></p>
* <p>Invert mapping:</p>
* <pre><code>curveRed = [ (0, 1.0), (1.0, 0) ]
* </code></pre>
- * <p><img alt="Inverting mapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png" /></p>
+ * <p><img alt="Inverting mapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png" /></p>
* <p>Gamma 1/2.2 mapping, with 16 control points:</p>
* <pre><code>curveRed = [
* (0.0000, 0.0000), (0.0667, 0.2920), (0.1333, 0.4002), (0.2000, 0.4812),
@@ -4021,7 +4009,7 @@
* (0.5333, 0.7515), (0.6000, 0.7928), (0.6667, 0.8317), (0.7333, 0.8685),
* (0.8000, 0.9035), (0.8667, 0.9370), (0.9333, 0.9691), (1.0000, 1.0000) ]
* </code></pre>
- * <p><img alt="Gamma = 1/2.2 tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png" /></p>
+ * <p><img alt="Gamma = 1/2.2 tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png" /></p>
* <p>Standard sRGB gamma mapping, per IEC 61966-2-1:1999, with 16 control points:</p>
* <pre><code>curveRed = [
* (0.0000, 0.0000), (0.0667, 0.2864), (0.1333, 0.4007), (0.2000, 0.4845),
@@ -4029,7 +4017,7 @@
* (0.5333, 0.7569), (0.6000, 0.7977), (0.6667, 0.8360), (0.7333, 0.8721),
* (0.8000, 0.9063), (0.8667, 0.9389), (0.9333, 0.9701), (1.0000, 1.0000) ]
* </code></pre>
- * <p><img alt="sRGB tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png" /></p>
+ * <p><img alt="sRGB tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png" /></p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Full capability</b> -
* Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
@@ -4119,9 +4107,9 @@
* PRESET_CURVE</p>
* <p>The tonemap curve will be defined by specified standard.</p>
* <p>sRGB (approximated by 16 control points):</p>
- * <p><img alt="sRGB tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png" /></p>
+ * <p><img alt="sRGB tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png" /></p>
* <p>Rec. 709 (approximated by 16 control points):</p>
- * <p><img alt="Rec. 709 tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png" /></p>
+ * <p><img alt="Rec. 709 tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png" /></p>
* <p>Note that above figures show a 16 control points approximation of preset
* curves. Camera devices may apply a different approximation to the curve.</p>
* <p><b>Possible values:</b>
diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java
index aaf6c57..7fc7836 100644
--- a/core/java/android/hardware/location/ContextHubInfo.java
+++ b/core/java/android/hardware/location/ContextHubInfo.java
@@ -16,6 +16,7 @@
package android.hardware.location;
import android.annotation.SystemApi;
+import android.hardware.contexthub.V1_0.ContextHub;
import android.os.Parcel;
import android.os.Parcelable;
@@ -31,22 +32,53 @@
private String mVendor;
private String mToolchain;
private int mPlatformVersion;
- private int mStaticSwVersion;
private int mToolchainVersion;
private float mPeakMips;
private float mStoppedPowerDrawMw;
private float mSleepPowerDrawMw;
private float mPeakPowerDrawMw;
private int mMaxPacketLengthBytes;
+ private byte mChreApiMajorVersion;
+ private byte mChreApiMinorVersion;
+ private short mChrePatchVersion;
+ private long mChrePlatformId;
private int[] mSupportedSensors;
private MemoryRegion[] mMemoryRegions;
+ /*
+ * TODO(b/66965339): Deprecate this constructor and the setter methods, and mark private fields
+ * as final when the ContextHubService JNI code is removed.
+ */
public ContextHubInfo() {
}
/**
+ * @hide
+ */
+ public ContextHubInfo(ContextHub contextHub) {
+ mId = contextHub.hubId;
+ mName = contextHub.name;
+ mVendor = contextHub.vendor;
+ mToolchain = contextHub.toolchain;
+ mPlatformVersion = contextHub.platformVersion;
+ mToolchainVersion = contextHub.toolchainVersion;
+ mPeakMips = contextHub.peakMips;
+ mStoppedPowerDrawMw = contextHub.stoppedPowerDrawMw;
+ mSleepPowerDrawMw = contextHub.sleepPowerDrawMw;
+ mPeakPowerDrawMw = contextHub.peakPowerDrawMw;
+ mMaxPacketLengthBytes = contextHub.maxSupportedMsgLen;
+ mChrePlatformId = contextHub.chrePlatformId;
+ mChreApiMajorVersion = contextHub.chreApiMajorVersion;
+ mChreApiMinorVersion = contextHub.chreApiMinorVersion;
+ mChrePatchVersion = contextHub.chrePatchVersion;
+
+ mSupportedSensors = new int[0];
+ mMemoryRegions = new MemoryRegion[0];
+ }
+
+ /**
* returns the maximum number of bytes that can be sent per message to the hub
*
* @return int - maximum bytes that can be transmitted in a
@@ -173,7 +205,7 @@
* @return int - platform version number
*/
public int getStaticSwVersion() {
- return mStaticSwVersion;
+ return (mChreApiMajorVersion << 24) | (mChreApiMinorVersion << 16) | (mChrePatchVersion);
}
/**
@@ -183,9 +215,7 @@
*
* @hide
*/
- public void setStaticSwVersion(int staticSwVersion) {
- mStaticSwVersion = staticSwVersion;
- }
+ public void setStaticSwVersion(int staticSwVersion) {}
/**
* get the tool chain version
@@ -345,23 +375,66 @@
mMemoryRegions = Arrays.copyOf(memoryRegions, memoryRegions.length);
}
+ /**
+ * @return the CHRE platform ID as defined in chre/version.h
+ *
+ * TODO(b/67734082): Expose as public API
+ * @hide
+ */
+ public long getChrePlatformId() {
+ return mChrePlatformId;
+ }
+
+ /**
+ * @return the CHRE API's major version as defined in chre/version.h
+ *
+ * TODO(b/67734082): Expose as public API
+ * @hide
+ */
+ public byte getChreApiMajorVersion() {
+ return mChreApiMajorVersion;
+ }
+
+ /**
+ * @return the CHRE API's minor version as defined in chre/version.h
+ *
+ * TODO(b/67734082): Expose as public API
+ * @hide
+ */
+ public byte getChreApiMinorVersion() {
+ return mChreApiMinorVersion;
+ }
+
+ /**
+ * @return the CHRE patch version as defined in chre/version.h
+ *
+ * TODO(b/67734082): Expose as public API
+ * @hide
+ */
+ public short getChrePatchVersion() {
+ return mChrePatchVersion;
+ }
+
@Override
public String toString() {
- String retVal = "";
- retVal += "Id : " + mId;
- retVal += ", Name : " + mName;
- retVal += "\n\tVendor : " + mVendor;
- retVal += ", ToolChain : " + mToolchain;
- retVal += "\n\tPlatformVersion : " + mPlatformVersion;
- retVal += ", StaticSwVersion : " + mStaticSwVersion;
- retVal += "\n\tPeakMips : " + mPeakMips;
- retVal += ", StoppedPowerDraw : " + mStoppedPowerDrawMw + " mW";
- retVal += ", PeakPowerDraw : " + mPeakPowerDrawMw + " mW";
- retVal += ", MaxPacketLength : " + mMaxPacketLengthBytes + " Bytes";
- retVal += "\n\tSupported sensors : " + Arrays.toString(mSupportedSensors);
- retVal += "\n\tMemory Regions : " + Arrays.toString(mMemoryRegions);
+ String retVal = "";
+ retVal += "Id : " + mId;
+ retVal += ", Name : " + mName;
+ retVal += "\n\tVendor : " + mVendor;
+ retVal += ", Toolchain : " + mToolchain;
+ retVal += ", Toolchain version: 0x" + Integer.toHexString(mToolchainVersion);
+ retVal += "\n\tPlatformVersion : 0x" + Integer.toHexString(mPlatformVersion);
+ retVal += ", SwVersion : "
+ + mChreApiMajorVersion + "." + mChreApiMinorVersion + "." + mChrePatchVersion;
+ retVal += ", CHRE platform ID: 0x" + Long.toHexString(mChrePlatformId);
+ retVal += "\n\tPeakMips : " + mPeakMips;
+ retVal += ", StoppedPowerDraw : " + mStoppedPowerDrawMw + " mW";
+ retVal += ", PeakPowerDraw : " + mPeakPowerDrawMw + " mW";
+ retVal += ", MaxPacketLength : " + mMaxPacketLengthBytes + " Bytes";
+ retVal += "\n\tSupported sensors : " + Arrays.toString(mSupportedSensors);
+ retVal += "\n\tMemory Regions : " + Arrays.toString(mMemoryRegions);
- return retVal;
+ return retVal;
}
private ContextHubInfo(Parcel in) {
@@ -371,12 +444,15 @@
mToolchain = in.readString();
mPlatformVersion = in.readInt();
mToolchainVersion = in.readInt();
- mStaticSwVersion = in.readInt();
mPeakMips = in.readFloat();
mStoppedPowerDrawMw = in.readFloat();
mSleepPowerDrawMw = in.readFloat();
mPeakPowerDrawMw = in.readFloat();
mMaxPacketLengthBytes = in.readInt();
+ mChrePlatformId = in.readLong();
+ mChreApiMajorVersion = in.readByte();
+ mChreApiMinorVersion = in.readByte();
+ mChrePatchVersion = (short) in.readInt();
int numSupportedSensors = in.readInt();
mSupportedSensors = new int[numSupportedSensors];
@@ -395,12 +471,15 @@
out.writeString(mToolchain);
out.writeInt(mPlatformVersion);
out.writeInt(mToolchainVersion);
- out.writeInt(mStaticSwVersion);
out.writeFloat(mPeakMips);
out.writeFloat(mStoppedPowerDrawMw);
out.writeFloat(mSleepPowerDrawMw);
out.writeFloat(mPeakPowerDrawMw);
out.writeInt(mMaxPacketLengthBytes);
+ out.writeLong(mChrePlatformId);
+ out.writeByte(mChreApiMajorVersion);
+ out.writeByte(mChreApiMinorVersion);
+ out.writeInt(mChrePatchVersion);
out.writeInt(mSupportedSensors.length);
out.writeIntArray(mSupportedSensors);
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 935f5f3..6ebf3b9 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -103,7 +103,7 @@
/**
* A hardware serial number, if available. Alphanumeric only, case-insensitive.
- * For apps targeting SDK higher than {@link Build.VERSION_CODES#N_MR1} this
+ * For apps targeting SDK higher than {@link Build.VERSION_CODES#O_MR1} this
* field is set to {@link Build#UNKNOWN}.
*
* @deprecated Use {@link #getSerial()} instead.
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 07c6055..f2e0bdd 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -22,6 +22,7 @@
import android.opengl.EGL14;
import android.os.Build;
import android.os.SystemProperties;
+import android.provider.Settings;
import android.util.Log;
import dalvik.system.VMRuntime;
@@ -29,18 +30,110 @@
import java.io.File;
/** @hide */
-public final class GraphicsEnvironment {
+public class GraphicsEnvironment {
+
+ private static final GraphicsEnvironment sInstance = new GraphicsEnvironment();
+
+ /**
+ * Returns the shared {@link GraphicsEnvironment} instance.
+ */
+ public static GraphicsEnvironment getInstance() {
+ return sInstance;
+ }
private static final boolean DEBUG = false;
private static final String TAG = "GraphicsEnvironment";
private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
+ private ClassLoader mClassLoader;
+ private String mLayerPath;
+ private String mDebugLayerPath;
+
+ /**
+ * Set up GraphicsEnvironment
+ */
+ public void setup(Context context) {
+ setupGpuLayers(context);
+ chooseDriver(context);
+ }
+
+ /**
+ * Check whether application is debuggable
+ */
+ private static boolean isDebuggable(Context context) {
+ return (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) > 0;
+ }
+
+ /**
+ * Store the layer paths available to the loader.
+ */
+ public void setLayerPaths(ClassLoader classLoader,
+ String layerPath,
+ String debugLayerPath) {
+ // We have to store these in the class because they are set up before we
+ // have access to the Context to properly set up GraphicsEnvironment
+ mClassLoader = classLoader;
+ mLayerPath = layerPath;
+ mDebugLayerPath = debugLayerPath;
+ }
+
+ /**
+ * Set up layer search paths for all apps
+ * If debuggable, check for additional debug settings
+ */
+ private void setupGpuLayers(Context context) {
+
+ String layerPaths = "";
+
+ // Only enable additional debug functionality if the following conditions are met:
+ // 1. App is debuggable
+ // 2. ENABLE_GPU_DEBUG_LAYERS is true
+ // 3. Package name is equal to GPU_DEBUG_APP
+
+ if (isDebuggable(context)) {
+
+ int enable = Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.ENABLE_GPU_DEBUG_LAYERS, 0);
+
+ if (enable != 0) {
+
+ String gpuDebugApp = Settings.Global.getString(context.getContentResolver(),
+ Settings.Global.GPU_DEBUG_APP);
+
+ String packageName = context.getPackageName();
+
+ if ((gpuDebugApp != null && packageName != null)
+ && (!gpuDebugApp.isEmpty() && !packageName.isEmpty())
+ && gpuDebugApp.equals(packageName)) {
+ Log.i(TAG, "GPU debug layers enabled for " + packageName);
+
+ // Prepend the debug layer path as a searchable path.
+ // This will ensure debug layers added will take precedence over
+ // the layers specified by the app.
+ layerPaths = mDebugLayerPath + ":";
+
+ String layers = Settings.Global.getString(context.getContentResolver(),
+ Settings.Global.GPU_DEBUG_LAYERS);
+
+ Log.i(TAG, "Debug layer list: " + layers);
+ if (layers != null && !layers.isEmpty()) {
+ setDebugLayers(layers);
+ }
+ }
+ }
+
+ }
+
+ // Include the app's lib directory in all cases
+ layerPaths += mLayerPath;
+
+ setLayerPaths(mClassLoader, layerPaths);
+ }
+
/**
* Choose whether the current process should use the builtin or an updated driver.
- *
- * @hide
*/
- public static void chooseDriver(Context context) {
+ private static void chooseDriver(Context context) {
String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
if (driverPackageName == null || driverPackageName.isEmpty()) {
return;
@@ -99,8 +192,6 @@
* on a separate thread, it can usually be finished well before the UI is ready to be drawn.
*
* Should only be called after chooseDriver().
- *
- * @hide
*/
public static void earlyInitEGL() {
Thread eglInitThread = new Thread(
@@ -124,6 +215,7 @@
return null;
}
+ private static native void setLayerPaths(ClassLoader classLoader, String layerPaths);
+ private static native void setDebugLayers(String layers);
private static native void setDriverPath(String path);
-
}
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 5d96fd3..0620fa3 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -35,6 +35,10 @@
* DO NOT MOVE - UserManager.h depends on the ordering of this function.
*/
int getCredentialOwnerProfile(int userHandle);
+ int getProfileParentId(int userHandle);
+ /*
+ * END OF DO NOT MOVE
+ */
UserInfo createUser(in String name, int flags);
UserInfo createProfileForUser(in String name, int flags, int userHandle,
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 10adb5a..d092018 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -191,6 +191,7 @@
* {@link #readSparseArray(ClassLoader)}.
*/
public final class Parcel {
+
private static final boolean DEBUG_RECYCLE = false;
private static final boolean DEBUG_ARRAY_MAP = false;
private static final String TAG = "Parcel";
@@ -209,6 +210,12 @@
private RuntimeException mStack;
+ /**
+ * Whether or not to parcel the stack trace of an exception. This has a performance
+ * impact, so should only be included in specific processes and only on debug builds.
+ */
+ private static boolean sParcelExceptionStackTrace;
+
private static final int POOL_SIZE = 6;
private static final Parcel[] sOwnedPool = new Parcel[POOL_SIZE];
private static final Parcel[] sHolderPool = new Parcel[POOL_SIZE];
@@ -325,6 +332,11 @@
private static native void nativeWriteInterfaceToken(long nativePtr, String interfaceName);
private static native void nativeEnforceInterface(long nativePtr, String interfaceName);
+ /** Last time exception with a stack trace was written */
+ private static volatile long sLastWriteExceptionStackTrace;
+ /** Used for throttling of writing stack trace, which is costly */
+ private static final int WRITE_EXCEPTION_STACK_TRACE_THRESHOLD_MS = 1000;
+
@CriticalNative
private static native long nativeGetBlobAshmemSize(long nativePtr);
@@ -1696,6 +1708,11 @@
}
}
+ /** @hide For debugging purposes */
+ public static void setStackTraceParceling(boolean enabled) {
+ sParcelExceptionStackTrace = enabled;
+ }
+
/**
* Special function for writing an exception result at the header of
* a parcel, to be used when returning an exception from a transaction.
@@ -1753,6 +1770,27 @@
throw new RuntimeException(e);
}
writeString(e.getMessage());
+ final long timeNow = sParcelExceptionStackTrace ? SystemClock.elapsedRealtime() : 0;
+ if (sParcelExceptionStackTrace && (timeNow - sLastWriteExceptionStackTrace
+ > WRITE_EXCEPTION_STACK_TRACE_THRESHOLD_MS)) {
+ sLastWriteExceptionStackTrace = timeNow;
+ final int sizePosition = dataPosition();
+ writeInt(0); // Header size will be filled in later
+ StackTraceElement[] stackTrace = e.getStackTrace();
+ final int truncatedSize = Math.min(stackTrace.length, 5);
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < truncatedSize; i++) {
+ sb.append("\tat ").append(stackTrace[i]);
+ }
+ writeString(sb.toString());
+ final int payloadPosition = dataPosition();
+ setDataPosition(sizePosition);
+ // Write stack trace header size. Used in native side to skip the header
+ writeInt(payloadPosition - sizePosition);
+ setDataPosition(payloadPosition);
+ } else {
+ writeInt(0);
+ }
switch (code) {
case EX_SERVICE_SPECIFIC:
writeInt(((ServiceSpecificException) e).errorCode);
@@ -1818,7 +1856,19 @@
int code = readExceptionCode();
if (code != 0) {
String msg = readString();
- readException(code, msg);
+ String remoteStackTrace = null;
+ final int remoteStackPayloadSize = readInt();
+ if (remoteStackPayloadSize > 0) {
+ remoteStackTrace = readString();
+ }
+ Exception e = createException(code, msg);
+ // Attach remote stack trace if availalble
+ if (remoteStackTrace != null) {
+ RemoteException cause = new RemoteException(
+ "Remote stack trace:\n" + remoteStackTrace, null, false, false);
+ e.initCause(cause);
+ }
+ SneakyThrow.sneakyThrow(e);
}
}
@@ -1863,32 +1913,41 @@
* @param msg The exception message.
*/
public final void readException(int code, String msg) {
+ SneakyThrow.sneakyThrow(createException(code, msg));
+ }
+
+ /**
+ * Creates an exception with the given message.
+ *
+ * @param code Used to determine which exception class to throw.
+ * @param msg The exception message.
+ */
+ private Exception createException(int code, String msg) {
switch (code) {
case EX_PARCELABLE:
if (readInt() > 0) {
- SneakyThrow.sneakyThrow(
- (Exception) readParcelable(Parcelable.class.getClassLoader()));
+ return (Exception) readParcelable(Parcelable.class.getClassLoader());
} else {
- throw new RuntimeException(msg + " [missing Parcelable]");
+ return new RuntimeException(msg + " [missing Parcelable]");
}
case EX_SECURITY:
- throw new SecurityException(msg);
+ return new SecurityException(msg);
case EX_BAD_PARCELABLE:
- throw new BadParcelableException(msg);
+ return new BadParcelableException(msg);
case EX_ILLEGAL_ARGUMENT:
- throw new IllegalArgumentException(msg);
+ return new IllegalArgumentException(msg);
case EX_NULL_POINTER:
- throw new NullPointerException(msg);
+ return new NullPointerException(msg);
case EX_ILLEGAL_STATE:
- throw new IllegalStateException(msg);
+ return new IllegalStateException(msg);
case EX_NETWORK_MAIN_THREAD:
- throw new NetworkOnMainThreadException();
+ return new NetworkOnMainThreadException();
case EX_UNSUPPORTED_OPERATION:
- throw new UnsupportedOperationException(msg);
+ return new UnsupportedOperationException(msg);
case EX_SERVICE_SPECIFIC:
- throw new ServiceSpecificException(readInt(), msg);
+ return new ServiceSpecificException(readInt(), msg);
}
- throw new RuntimeException("Unknown exception code: " + code
+ return new RuntimeException("Unknown exception code: " + code
+ " msg " + msg);
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index dd4825e..0fce7a4 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -527,8 +527,7 @@
ServiceType.SOUND,
ServiceType.BATTERY_STATS,
ServiceType.DATA_SAVER,
- ServiceType.FORCE_ALL_APPS_STANDBY_JOBS,
- ServiceType.FORCE_ALL_APPS_STANDBY_ALARMS,
+ ServiceType.FORCE_ALL_APPS_STANDBY,
ServiceType.OPTIONAL_SENSORS,
})
public @interface ServiceType {
@@ -545,14 +544,9 @@
int DATA_SAVER = 10;
/**
- * Whether the job scheduler should force app standby on all apps on battery saver or not.
+ * Whether to enable force-app-standby on all apps or not.
*/
- int FORCE_ALL_APPS_STANDBY_JOBS = 11;
-
- /**
- * Whether the alarm manager should force app standby on all apps on battery saver or not.
- */
- int FORCE_ALL_APPS_STANDBY_ALARMS = 12;
+ int FORCE_ALL_APPS_STANDBY = 11;
/**
* Whether to disable non-essential sensors. (e.g. edge sensors.)
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index b5d62e5..0874d93 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -151,6 +151,9 @@
*/
public static final int OTA_UPDATE_UID = 1061;
+ /** {@hide} */
+ public static final int NOBODY_UID = 9999;
+
/**
* Defines the start of a range of UIDs (and GIDs), going from this
* number to {@link #LAST_APPLICATION_UID} that are reserved for assigning
diff --git a/core/java/android/os/RemoteException.java b/core/java/android/os/RemoteException.java
index 6d25fc1..4e8b971 100644
--- a/core/java/android/os/RemoteException.java
+++ b/core/java/android/os/RemoteException.java
@@ -30,6 +30,12 @@
super(message);
}
+ /** @hide */
+ public RemoteException(String message, Throwable cause, boolean enableSuppression,
+ boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+
/** {@hide} */
public RuntimeException rethrowAsRuntimeException() {
throw new RuntimeException(this);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 6decc30..9945755 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9854,6 +9854,27 @@
public static final String WAIT_FOR_DEBUGGER = "wait_for_debugger";
/**
+ * Allow GPU debug layers?
+ * 0 = no
+ * 1 = yes
+ * @hide
+ */
+ public static final String ENABLE_GPU_DEBUG_LAYERS = "enable_gpu_debug_layers";
+
+ /**
+ * App allowed to load GPU debug layers
+ * @hide
+ */
+ public static final String GPU_DEBUG_APP = "gpu_debug_app";
+
+ /**
+ * Ordered GPU debug layer list
+ * i.e. <layer1>:<layer2>:...:<layerN>
+ * @hide
+ */
+ public static final String GPU_DEBUG_LAYERS = "gpu_debug_layers";
+
+ /**
* Control whether the process CPU usage meter should be shown.
*
* @deprecated This functionality is no longer available as of
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
index 080482b..6fc689a 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -18,6 +18,7 @@
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.app.ActivityManager;
import android.app.INotificationManager;
import android.app.Service;
@@ -200,7 +201,11 @@
return mProvider;
}
- private boolean isBound() {
+ /**
+ * @hide
+ */
+ @TestApi
+ public boolean isBound() {
if (mProvider == null) {
Log.w(TAG, "Condition provider service not yet bound.");
return false;
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index 2c83fc4..8c90156 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -355,21 +355,21 @@
final Locale locale = localeFromContext(context);
final MeasureFormat measureFormat = MeasureFormat.getInstance(
locale, MeasureFormat.FormatWidth.SHORT);
- if (days >= 2) {
+ if (days >= 2 || (days > 0 && hours == 0)) {
days += (hours+12)/24;
return measureFormat.format(new Measure(days, MeasureUnit.DAY));
} else if (days > 0) {
return measureFormat.formatMeasures(
new Measure(days, MeasureUnit.DAY),
new Measure(hours, MeasureUnit.HOUR));
- } else if (hours >= 2) {
+ } else if (hours >= 2 || (hours > 0 && minutes == 0)) {
hours += (minutes+30)/60;
return measureFormat.format(new Measure(hours, MeasureUnit.HOUR));
} else if (hours > 0) {
return measureFormat.formatMeasures(
new Measure(hours, MeasureUnit.HOUR),
new Measure(minutes, MeasureUnit.MINUTE));
- } else if (minutes >= 2) {
+ } else if (minutes >= 2 || (minutes > 0 && seconds == 0)) {
minutes += (seconds+30)/60;
return measureFormat.format(new Measure(minutes, MeasureUnit.MINUTE));
} else if (minutes > 0) {
diff --git a/core/java/android/util/AndroidException.java b/core/java/android/util/AndroidException.java
index dfe00c9b..1345ddf 100644
--- a/core/java/android/util/AndroidException.java
+++ b/core/java/android/util/AndroidException.java
@@ -34,5 +34,11 @@
public AndroidException(Exception cause) {
super(cause);
}
+
+ /** @hide */
+ protected AndroidException(String message, Throwable cause, boolean enableSuppression,
+ boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
};
diff --git a/core/java/com/android/internal/app/IAssistDataReceiver.aidl b/core/java/android/util/MutableInt.java
similarity index 64%
copy from core/java/com/android/internal/app/IAssistDataReceiver.aidl
copy to core/java/android/util/MutableInt.java
index 9c9ffef..a3d8606 100644
--- a/core/java/com/android/internal/app/IAssistDataReceiver.aidl
+++ b/core/java/android/util/MutableInt.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2011 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.
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-package com.android.internal.app;
+package android.util;
-import android.graphics.Bitmap;
-import android.os.Bundle;
+/**
+ */
+public final class MutableInt {
+ public int value;
-/** @hide */
-oneway interface IAssistDataReceiver {
- void onHandleAssistData(in Bundle resultData);
- void onHandleAssistScreenshot(in Bitmap screenshot);
+ public MutableInt(int value) {
+ this.value = value;
+ }
}
diff --git a/core/java/com/android/internal/app/IAssistDataReceiver.aidl b/core/java/android/util/MutableLong.java
similarity index 64%
copy from core/java/com/android/internal/app/IAssistDataReceiver.aidl
copy to core/java/android/util/MutableLong.java
index 9c9ffef..575068e 100644
--- a/core/java/com/android/internal/app/IAssistDataReceiver.aidl
+++ b/core/java/android/util/MutableLong.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2011 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.
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-package com.android.internal.app;
+package android.util;
-import android.graphics.Bitmap;
-import android.os.Bundle;
+/**
+ */
+public final class MutableLong {
+ public long value;
-/** @hide */
-oneway interface IAssistDataReceiver {
- void onHandleAssistData(in Bundle resultData);
- void onHandleAssistScreenshot(in Bitmap screenshot);
+ public MutableLong(long value) {
+ this.value = value;
+ }
}
diff --git a/core/java/android/view/Gravity.java b/core/java/android/view/Gravity.java
index 232ff25..defa58e 100644
--- a/core/java/android/view/Gravity.java
+++ b/core/java/android/view/Gravity.java
@@ -446,49 +446,52 @@
*/
public static String toString(int gravity) {
final StringBuilder result = new StringBuilder();
- if ((gravity & FILL) != 0) {
+ if ((gravity & FILL) == FILL) {
result.append("FILL").append(' ');
} else {
- if ((gravity & FILL_VERTICAL) != 0) {
+ if ((gravity & FILL_VERTICAL) == FILL_VERTICAL) {
result.append("FILL_VERTICAL").append(' ');
} else {
- if ((gravity & TOP) != 0) {
+ if ((gravity & TOP) == TOP) {
result.append("TOP").append(' ');
}
- if ((gravity & BOTTOM) != 0) {
+ if ((gravity & BOTTOM) == BOTTOM) {
result.append("BOTTOM").append(' ');
}
}
- if ((gravity & FILL_HORIZONTAL) != 0) {
+ if ((gravity & FILL_HORIZONTAL) == FILL_HORIZONTAL) {
result.append("FILL_HORIZONTAL").append(' ');
} else {
- if ((gravity & START) != 0) {
+ if ((gravity & START) == START) {
result.append("START").append(' ');
- } else if ((gravity & LEFT) != 0) {
+ } else if ((gravity & LEFT) == LEFT) {
result.append("LEFT").append(' ');
}
- if ((gravity & END) != 0) {
+ if ((gravity & END) == END) {
result.append("END").append(' ');
- } else if ((gravity & RIGHT) != 0) {
+ } else if ((gravity & RIGHT) == RIGHT) {
result.append("RIGHT").append(' ');
}
}
}
- if ((gravity & CENTER) != 0) {
+ if ((gravity & CENTER) == CENTER) {
result.append("CENTER").append(' ');
} else {
- if ((gravity & CENTER_VERTICAL) != 0) {
+ if ((gravity & CENTER_VERTICAL) == CENTER_VERTICAL) {
result.append("CENTER_VERTICAL").append(' ');
}
- if ((gravity & CENTER_HORIZONTAL) != 0) {
+ if ((gravity & CENTER_HORIZONTAL) == CENTER_HORIZONTAL) {
result.append("CENTER_HORIZONTAL").append(' ');
}
}
- if ((gravity & DISPLAY_CLIP_VERTICAL) != 0) {
+ if (result.length() == 0) {
+ result.append("NO GRAVITY").append(' ');
+ }
+ if ((gravity & DISPLAY_CLIP_VERTICAL) == DISPLAY_CLIP_VERTICAL) {
result.append("DISPLAY_CLIP_VERTICAL").append(' ');
}
- if ((gravity & DISPLAY_CLIP_VERTICAL) != 0) {
- result.append("DISPLAY_CLIP_VERTICAL").append(' ');
+ if ((gravity & DISPLAY_CLIP_HORIZONTAL) == DISPLAY_CLIP_HORIZONTAL) {
+ result.append("DISPLAY_CLIP_HORIZONTAL").append(' ');
}
result.deleteCharAt(result.length() - 1);
return result.toString();
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 65bde49..29032a7 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -16,13 +16,13 @@
package android.view;
-import com.android.internal.app.IAssistDataReceiver;
import com.android.internal.os.IResultReceiver;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
+import android.app.IAssistDataReceiver;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 9515040..c4a7160 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -19,7 +19,6 @@
import android.animation.Animator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
-import android.graphics.Canvas;
import android.graphics.CanvasProperty;
import android.graphics.Paint;
import android.util.SparseIntArray;
@@ -281,12 +280,9 @@
setTarget(mViewTarget.mRenderNode);
}
- public void setTarget(Canvas canvas) {
- if (!(canvas instanceof DisplayListCanvas)) {
- throw new IllegalArgumentException("Not a GLES20RecordingCanvas");
- }
- final DisplayListCanvas recordingCanvas = (DisplayListCanvas) canvas;
- setTarget(recordingCanvas.mNode);
+ /** Sets the animation target to the owning view of the DisplayListCanvas */
+ public void setTarget(DisplayListCanvas canvas) {
+ setTarget(canvas.mNode);
}
private void setTarget(RenderNode node) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index be09fe8..19ce43f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4163,6 +4163,11 @@
*/
private static boolean sUseDefaultFocusHighlight;
+ /**
+ * True if zero-sized views can be focused.
+ */
+ private static boolean sCanFocusZeroSized;
+
private String mTransitionName;
static class TintInfo {
@@ -4245,6 +4250,8 @@
OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
OnCapturedPointerListener mOnCapturedPointerListener;
+
+ private ArrayList<OnKeyFallbackListener> mKeyFallbackListeners;
}
ListenerInfo mListenerInfo;
@@ -4743,6 +4750,8 @@
sUseDefaultFocusHighlight = context.getResources().getBoolean(
com.android.internal.R.bool.config_useDefaultFocusHighlight);
+ sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
+
sCompatibilityDone = true;
}
}
@@ -6950,6 +6959,7 @@
void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
mPrivateFlags &= ~PFLAG_FOCUSED;
+ clearParentsWantFocus();
if (propagate && mParent != null) {
mParent.clearChildFocus(this);
@@ -10931,8 +10941,9 @@
* descendants.
*
* A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
- * false), or if it is focusable and it is not focusable in touch mode
- * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
+ * false), or if it can't be focused due to other conditions (not focusable in touch mode
+ * ({@link #isFocusableInTouchMode}) while the device is in touch mode, not visible, not
+ * enabled, or has no size).
*
* See also {@link #focusSearch(int)}, which is what you call to say that you
* have focus, and you want your parent to look for the next one.
@@ -10970,17 +10981,17 @@
*/
@TestApi
public boolean restoreFocusNotInCluster() {
- return requestFocus(View.FOCUS_DOWN);
+ return requestFocus();
}
/**
* Gives focus to the default-focus view in the view hierarchy that has this view as a root.
- * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
+ * If the default-focus view cannot be found, falls back to calling {@link #requestFocus()}.
*
* @return Whether this view or one of its descendants actually took focus
*/
public boolean restoreDefaultFocus() {
- return requestFocus(View.FOCUS_DOWN);
+ return requestFocus();
}
/**
@@ -11039,9 +11050,7 @@
private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
// need to be focusable
- if ((mViewFlags & FOCUSABLE) != FOCUSABLE
- || (mViewFlags & VISIBILITY_MASK) != VISIBLE
- || (mViewFlags & ENABLED_MASK) != ENABLED) {
+ if (!canTakeFocus()) {
return false;
}
@@ -11056,10 +11065,21 @@
return false;
}
+ if (!isLaidOut()) {
+ mPrivateFlags |= PFLAG_WANTS_FOCUS;
+ }
+
handleFocusGainInternal(direction, previouslyFocusedRect);
return true;
}
+ void clearParentsWantFocus() {
+ if (mParent instanceof View) {
+ ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
+ ((View) mParent).clearParentsWantFocus();
+ }
+ }
+
/**
* Call this to try to give focus to a specific view or to one of its descendants. This is a
* special variant of {@link #requestFocus() } that will allow views that are not focusable in
@@ -13431,6 +13451,13 @@
mAttachInfo.mUnbufferedDispatchRequested = true;
}
+ private boolean canTakeFocus() {
+ return ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
+ && ((mViewFlags & FOCUSABLE) == FOCUSABLE)
+ && ((mViewFlags & ENABLED_MASK) == ENABLED)
+ && (sCanFocusZeroSized || !isLaidOut() || (mBottom > mTop) && (mRight > mLeft));
+ }
+
/**
* Set flags controlling behavior of this view.
*
@@ -13450,6 +13477,7 @@
return;
}
int privateFlags = mPrivateFlags;
+ boolean shouldNotifyFocusableAvailable = false;
// If focusable is auto, update the FOCUSABLE bit.
int focusableChangedByAuto = 0;
@@ -13488,7 +13516,7 @@
|| focusableChangedByAuto == 0
|| viewRootImpl == null
|| viewRootImpl.mThread == Thread.currentThread()) {
- mParent.focusableViewAvailable(this);
+ shouldNotifyFocusableAvailable = true;
}
}
}
@@ -13511,10 +13539,7 @@
// about in case nothing has focus. even if this specific view
// isn't focusable, it may contain something that is, so let
// the root view try to give this focus if nothing else does.
- if ((mParent != null) && ((mViewFlags & ENABLED_MASK) == ENABLED)
- && (mBottom > mTop) && (mRight > mLeft)) {
- mParent.focusableViewAvailable(this);
- }
+ shouldNotifyFocusableAvailable = true;
}
}
@@ -13523,17 +13548,18 @@
// a view becoming enabled should notify the parent as long as the view is also
// visible and the parent wasn't already notified by becoming visible during this
// setFlags invocation.
- if ((mViewFlags & VISIBILITY_MASK) == VISIBLE
- && ((changed & VISIBILITY_MASK) == 0)) {
- if ((mParent != null) && (mViewFlags & ENABLED_MASK) == ENABLED) {
- mParent.focusableViewAvailable(this);
- }
- }
+ shouldNotifyFocusableAvailable = true;
} else {
if (hasFocus()) clearFocus();
}
}
+ if (shouldNotifyFocusableAvailable) {
+ if (mParent != null && canTakeFocus()) {
+ mParent.focusableViewAvailable(this);
+ }
+ }
+
/* Check if the GONE bit has changed */
if ((changed & GONE) != 0) {
needGlobalAttributesUpdate(false);
@@ -20032,15 +20058,58 @@
}
}
+ final boolean wasLaidOut = isLaidOut();
+
mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
+ if (!wasLaidOut && isFocused()) {
+ mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
+ if (canTakeFocus()) {
+ // We have a robust focus, so parents should no longer be wanting focus.
+ clearParentsWantFocus();
+ } else if (!getViewRootImpl().isInLayout()) {
+ // This is a weird case. Most-likely the user, rather than ViewRootImpl, called
+ // layout. In this case, there's no guarantee that parent layouts will be evaluated
+ // and thus the safest action is to clear focus here.
+ clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
+ clearParentsWantFocus();
+ } else if (!hasParentWantsFocus()) {
+ // original requestFocus was likely on this view directly, so just clear focus
+ clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
+ }
+ // otherwise, we let parents handle re-assigning focus during their layout passes.
+ } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
+ mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
+ View focused = findFocus();
+ if (focused != null) {
+ // Try to restore focus as close as possible to our starting focus.
+ if (!restoreDefaultFocus() && !hasParentWantsFocus()) {
+ // Give up and clear focus once we've reached the top-most parent which wants
+ // focus.
+ focused.clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
+ }
+ }
+ }
+
if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
notifyEnterOrExitForAutoFillIfNeeded(true);
}
}
+ private boolean hasParentWantsFocus() {
+ ViewParent parent = mParent;
+ while (parent instanceof ViewGroup) {
+ ViewGroup pv = (ViewGroup) parent;
+ if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
+ return true;
+ }
+ parent = pv.mParent;
+ }
+ return false;
+ }
+
/**
* Called from layout when this view should
* assign a size and position to each of its children.
@@ -20147,6 +20216,23 @@
mOverlay.getOverlayView().setRight(newWidth);
mOverlay.getOverlayView().setBottom(newHeight);
}
+ // If this isn't laid out yet, focus assignment will be handled during the "deferment/
+ // backtracking" of requestFocus during layout, so don't touch focus here.
+ if (!sCanFocusZeroSized && isLaidOut()) {
+ if (newWidth <= 0 || newHeight <= 0) {
+ if (hasFocus()) {
+ clearFocus();
+ if (mParent instanceof ViewGroup) {
+ ((ViewGroup) mParent).clearFocusedInCluster();
+ }
+ }
+ clearAccessibilityFocus();
+ } else if (oldWidth <= 0 || oldHeight <= 0) {
+ if (mParent != null && canTakeFocus()) {
+ mParent.focusableViewAvailable(this);
+ }
+ }
+ }
rebuildOutline();
}
@@ -25194,6 +25280,29 @@
}
/**
+ * Interface definition for a callback to be invoked when a hardware key event is
+ * dispatched to this view during the fallback phase. This means no view in the hierarchy
+ * has handled this event.
+ */
+ public interface OnKeyFallbackListener {
+ /**
+ * Called when a hardware key is dispatched to a view in the fallback phase. This allows
+ * listeners to respond to events after the view hierarchy has had a chance to respond.
+ * <p>Key presses in software keyboards will generally NOT trigger this method,
+ * although some may elect to do so in some situations. Do not assume a
+ * software input method has to be key-based; even if it is, it may use key presses
+ * in a different way than you expect, so there is no way to reliably catch soft
+ * input key presses.
+ *
+ * @param v The view the key has been dispatched to.
+ * @param event The KeyEvent object containing full information about
+ * the event.
+ * @return True if the listener has consumed the event, false otherwise.
+ */
+ boolean onKeyFallback(View v, KeyEvent event);
+ }
+
+ /**
* Interface definition for a callback to be invoked when a touch event is
* dispatched to this view. The callback will be invoked before the touch
* event is given to the view.
@@ -26866,4 +26975,56 @@
}
return mTooltipInfo.mTooltipPopup.getContentView();
}
+
+ /**
+ * Allows this view to handle {@link KeyEvent}s which weren't handled by normal dispatch. This
+ * occurs after the normal view hierarchy dispatch, but before the window callback. By default,
+ * this will dispatch into all the listeners registered via
+ * {@link #addKeyFallbackListener(OnKeyFallbackListener)} in last-in-first-out order (most
+ * recently added will receive events first).
+ *
+ * @param event A not-previously-handled event.
+ * @return {@code true} if the event was handled, {@code false} otherwise.
+ * @see #addKeyFallbackListener
+ */
+ public boolean onKeyFallback(@NonNull KeyEvent event) {
+ if (mListenerInfo != null && mListenerInfo.mKeyFallbackListeners != null) {
+ for (int i = mListenerInfo.mKeyFallbackListeners.size() - 1; i >= 0; --i) {
+ if (mListenerInfo.mKeyFallbackListeners.get(i).onKeyFallback(this, event)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Adds a listener which will receive unhandled {@link KeyEvent}s.
+ * @param listener the receiver of fallback {@link KeyEvent}s.
+ * @see #onKeyFallback(KeyEvent)
+ */
+ public void addKeyFallbackListener(OnKeyFallbackListener listener) {
+ ArrayList<OnKeyFallbackListener> fallbacks = getListenerInfo().mKeyFallbackListeners;
+ if (fallbacks == null) {
+ fallbacks = new ArrayList<>();
+ getListenerInfo().mKeyFallbackListeners = fallbacks;
+ }
+ fallbacks.add(listener);
+ }
+
+ /**
+ * Removes a listener which will receive unhandled {@link KeyEvent}s.
+ * @param listener the receiver of fallback {@link KeyEvent}s.
+ * @see #onKeyFallback(KeyEvent)
+ */
+ public void removeKeyFallbackListener(OnKeyFallbackListener listener) {
+ if (mListenerInfo != null) {
+ if (mListenerInfo.mKeyFallbackListeners != null) {
+ mListenerInfo.mKeyFallbackListeners.remove(listener);
+ if (mListenerInfo.mKeyFallbackListeners.isEmpty()) {
+ mListenerInfo.mKeyFallbackListeners = null;
+ }
+ }
+ }
+ }
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 929beae..d0fcc5d 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3215,22 +3215,31 @@
}
int descendantFocusability = getDescendantFocusability();
+ boolean result;
switch (descendantFocusability) {
case FOCUS_BLOCK_DESCENDANTS:
- return super.requestFocus(direction, previouslyFocusedRect);
+ result = super.requestFocus(direction, previouslyFocusedRect);
+ break;
case FOCUS_BEFORE_DESCENDANTS: {
final boolean took = super.requestFocus(direction, previouslyFocusedRect);
- return took ? took : onRequestFocusInDescendants(direction, previouslyFocusedRect);
+ result = took ? took : onRequestFocusInDescendants(direction,
+ previouslyFocusedRect);
+ break;
}
case FOCUS_AFTER_DESCENDANTS: {
final boolean took = onRequestFocusInDescendants(direction, previouslyFocusedRect);
- return took ? took : super.requestFocus(direction, previouslyFocusedRect);
+ result = took ? took : super.requestFocus(direction, previouslyFocusedRect);
+ break;
}
default:
throw new IllegalStateException("descendant focusability must be "
+ "one of FOCUS_BEFORE_DESCENDANTS, FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS "
+ "but is " + descendantFocusability);
}
+ if (result && !isLaidOut() && ((mPrivateFlags & PFLAG_WANTS_FOCUS) == 0)) {
+ mPrivateFlags |= PFLAG_WANTS_FOCUS;
+ }
+ return result;
}
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e30496f..e9509b7 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -73,6 +73,7 @@
import android.util.MergedConfiguration;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.util.TimeUtils;
import android.util.TypedValue;
import android.view.Surface.OutOfResourcesException;
@@ -362,6 +363,8 @@
InputStage mFirstPostImeInputStage;
InputStage mSyntheticInputStage;
+ private final KeyFallbackManager mKeyFallbackManager = new KeyFallbackManager();
+
boolean mWindowAttributesChanged = false;
int mWindowAttributesChangesFlag = 0;
@@ -4764,6 +4767,13 @@
private int processKeyEvent(QueuedInputEvent q) {
final KeyEvent event = (KeyEvent)q.mEvent;
+ mKeyFallbackManager.mDispatched = false;
+
+ if (mKeyFallbackManager.hasFocus()
+ && mKeyFallbackManager.dispatchUnique(mView, event)) {
+ return FINISH_HANDLED;
+ }
+
// Deliver the key to the view hierarchy.
if (mView.dispatchKeyEvent(event)) {
return FINISH_HANDLED;
@@ -4773,6 +4783,10 @@
return FINISH_NOT_HANDLED;
}
+ if (mKeyFallbackManager.dispatchUnique(mView, event)) {
+ return FINISH_HANDLED;
+ }
+
int groupNavigationDirection = 0;
if (event.getAction() == KeyEvent.ACTION_DOWN
@@ -7529,6 +7543,16 @@
}
}
+ /**
+ * Dispatches a KeyEvent to all registered key fallback handlers.
+ *
+ * @param event
+ * @return {@code true} if the event was handled, {@code false} otherwise.
+ */
+ public boolean dispatchKeyFallbackEvent(KeyEvent event) {
+ return mKeyFallbackManager.dispatch(mView, event);
+ }
+
class TakenSurfaceHolder extends BaseSurfaceHolder {
@Override
public boolean onAllowLockCanvas() {
@@ -8093,4 +8117,92 @@
run();
}
}
+
+ private static class KeyFallbackManager {
+
+ // This is used to ensure that key-fallback events are only dispatched once. We attempt
+ // to dispatch more than once in order to achieve a certain order. Specifically, if we
+ // are in an Activity or Dialog (and have a Window.Callback), the keyfallback events should
+ // be dispatched after the view hierarchy, but before the Activity. However, if we aren't
+ // in an activity, we still want key fallbacks to be dispatched.
+ boolean mDispatched = false;
+
+ SparseBooleanArray mCapturedKeys = new SparseBooleanArray();
+ WeakReference<View> mFallbackReceiver = null;
+ int mVisitCount = 0;
+
+ private void updateCaptureState(KeyEvent event) {
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ mCapturedKeys.append(event.getKeyCode(), true);
+ }
+ if (event.getAction() == KeyEvent.ACTION_UP) {
+ mCapturedKeys.delete(event.getKeyCode());
+ }
+ }
+
+ boolean dispatch(View root, KeyEvent event) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "KeyFallback dispatch");
+ mDispatched = true;
+
+ updateCaptureState(event);
+
+ if (mFallbackReceiver != null) {
+ View target = mFallbackReceiver.get();
+ if (mCapturedKeys.size() == 0) {
+ mFallbackReceiver = null;
+ }
+ if (target != null && target.isAttachedToWindow()) {
+ return target.onKeyFallback(event);
+ }
+ // consume anyways so that we don't feed uncaptured key events to other views
+ return true;
+ }
+
+ boolean result = dispatchInZOrder(root, event);
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ return result;
+ }
+
+ private boolean dispatchInZOrder(View view, KeyEvent evt) {
+ if (view instanceof ViewGroup) {
+ ViewGroup vg = (ViewGroup) view;
+ ArrayList<View> orderedViews = vg.buildOrderedChildList();
+ if (orderedViews != null) {
+ try {
+ for (int i = orderedViews.size() - 1; i >= 0; --i) {
+ View v = orderedViews.get(i);
+ if (dispatchInZOrder(v, evt)) {
+ return true;
+ }
+ }
+ } finally {
+ orderedViews.clear();
+ }
+ } else {
+ for (int i = vg.getChildCount() - 1; i >= 0; --i) {
+ View v = vg.getChildAt(i);
+ if (dispatchInZOrder(v, evt)) {
+ return true;
+ }
+ }
+ }
+ }
+ if (view.onKeyFallback(evt)) {
+ mFallbackReceiver = new WeakReference<>(view);
+ return true;
+ }
+ return false;
+ }
+
+ boolean hasFocus() {
+ return mFallbackReceiver != null;
+ }
+
+ boolean dispatchUnique(View root, KeyEvent event) {
+ if (mDispatched) {
+ return false;
+ }
+ return dispatch(root, event);
+ }
+ }
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 85251d4..5fddfba 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -431,7 +431,11 @@
}
}
- return super.dispatchKeyEvent(event);
+ if (super.dispatchKeyEvent(event)) {
+ return true;
+ }
+
+ return (getViewRootImpl() != null) && getViewRootImpl().dispatchKeyFallbackEvent(event);
}
public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 91bc681..22bfcc3 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -30,6 +30,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
/**
@@ -134,6 +135,13 @@
}
/**
+ * Checks if given map is null or has zero elements.
+ */
+ public static boolean isEmpty(@Nullable Map<?, ?> map) {
+ return map == null || map.isEmpty();
+ }
+
+ /**
* Checks if given array is null or has zero elements.
*/
public static <T> boolean isEmpty(@Nullable T[] array) {
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 3552e43..9d036dc 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -42,7 +42,6 @@
"com_google_android_gles_jni_EGLImpl.cpp",
"com_google_android_gles_jni_GLImpl.cpp", // TODO: .arm
"android_app_Activity.cpp",
- "android_app_ApplicationLoaders.cpp",
"android_app_NativeActivity.cpp",
"android_app_admin_SecurityLog.cpp",
"android_opengl_EGL14.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 8977891..2a65cde 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -187,7 +187,6 @@
extern int register_android_app_backup_FullBackup(JNIEnv *env);
extern int register_android_app_Activity(JNIEnv *env);
extern int register_android_app_ActivityThread(JNIEnv *env);
-extern int register_android_app_ApplicationLoaders(JNIEnv *env);
extern int register_android_app_NativeActivity(JNIEnv *env);
extern int register_android_media_RemoteDisplay(JNIEnv *env);
extern int register_android_util_jar_StrictJarFile(JNIEnv* env);
@@ -1456,7 +1455,6 @@
REG_JNI(register_android_app_backup_FullBackup),
REG_JNI(register_android_app_Activity),
REG_JNI(register_android_app_ActivityThread),
- REG_JNI(register_android_app_ApplicationLoaders),
REG_JNI(register_android_app_NativeActivity),
REG_JNI(register_android_util_jar_StrictJarFile),
REG_JNI(register_android_view_InputChannel),
diff --git a/core/jni/android_app_ApplicationLoaders.cpp b/core/jni/android_app_ApplicationLoaders.cpp
deleted file mode 100644
index 8bbf24a..0000000
--- a/core/jni/android_app_ApplicationLoaders.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "ApplicationLoaders"
-
-#include <nativehelper/ScopedUtfChars.h>
-#include <nativeloader/native_loader.h>
-#include <vulkan/vulkan_loader_data.h>
-
-#include "core_jni_helpers.h"
-
-static void setupVulkanLayerPath_native(JNIEnv* env, jobject clazz,
- jobject classLoader, jstring librarySearchPath) {
- android_namespace_t* ns = android::FindNamespaceByClassLoader(env, classLoader);
- ScopedUtfChars layerPathChars(env, librarySearchPath);
-
- vulkan::LoaderData& loader_data = vulkan::LoaderData::GetInstance();
- if (loader_data.layer_path.empty()) {
- loader_data.layer_path = layerPathChars.c_str();
- loader_data.app_namespace = ns;
- } else {
- ALOGV("Vulkan layer search path already set, not clobbering with '%s' for namespace %p'",
- layerPathChars.c_str(), ns);
- }
-}
-
-static const JNINativeMethod g_methods[] = {
- { "setupVulkanLayerPath", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V",
- reinterpret_cast<void*>(setupVulkanLayerPath_native) },
-};
-
-static const char* const kApplicationLoadersName = "android/app/ApplicationLoaders";
-
-namespace android
-{
-
-int register_android_app_ApplicationLoaders(JNIEnv* env) {
- return RegisterMethodsOrDie(env, kApplicationLoadersName, g_methods, NELEM(g_methods));
-}
-
-} // namespace android
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index f749488..4ecfd4b 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -18,6 +18,7 @@
#include <graphicsenv/GraphicsEnv.h>
#include <nativehelper/ScopedUtfChars.h>
+#include <nativeloader/native_loader.h>
#include "core_jni_helpers.h"
namespace {
@@ -27,8 +28,23 @@
android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str());
}
+void setLayerPaths_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring layerPaths) {
+ android_namespace_t* appNamespace = android::FindNamespaceByClassLoader(env, classLoader);
+ ScopedUtfChars layerPathsChars(env, layerPaths);
+ android::GraphicsEnv::getInstance().setLayerPaths(appNamespace, layerPathsChars.c_str());
+}
+
+void setDebugLayers_native(JNIEnv* env, jobject clazz, jstring layers) {
+ if (layers != nullptr) {
+ ScopedUtfChars layersChars(env, layers);
+ android::GraphicsEnv::getInstance().setDebugLayers(layersChars.c_str());
+ }
+}
+
const JNINativeMethod g_methods[] = {
{ "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
+ { "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) },
+ { "setDebugLayers", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayers_native) },
};
const char* const kGraphicsEnvironmentName = "android/os/GraphicsEnvironment";
diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp
index ac79249..4e88a83 100644
--- a/core/jni/android_text_StaticLayout.cpp
+++ b/core/jni/android_text_StaticLayout.cpp
@@ -120,14 +120,13 @@
class Run {
public:
- Run(int32_t start, int32_t end) : mStart(start), mEnd(end) {}
+ Run(int32_t start, int32_t end) : mRange(start, end) {}
virtual ~Run() {}
virtual void addTo(minikin::LineBreaker* lineBreaker) = 0;
protected:
- const int32_t mStart;
- const int32_t mEnd;
+ minikin::Range mRange;
private:
// Forbid copy and assign.
@@ -143,7 +142,7 @@
mIsRtl(isRtl) {}
void addTo(minikin::LineBreaker* lineBreaker) override {
- lineBreaker->addStyleRun(&mPaint, mCollection, mStart, mEnd, mIsRtl);
+ lineBreaker->addStyleRun(&mPaint, mCollection, mRange, mIsRtl);
}
private:
@@ -158,7 +157,7 @@
: Run(start, end), mWidth(width), mLocaleListId(localeListId) {}
void addTo(minikin::LineBreaker* lineBreaker) override {
- lineBreaker->addReplacement(mStart, mEnd, mWidth, mLocaleListId);
+ lineBreaker->addReplacement(mRange, mWidth, mLocaleListId);
}
private:
@@ -273,7 +272,7 @@
static jint nComputeLineBreaks(JNIEnv* env, jclass, jlong nativePtr,
// Inputs
- jcharArray text,
+ jcharArray javaText,
jint length,
jfloat firstWidth,
jint firstWidthLineCount,
@@ -294,11 +293,10 @@
StaticLayoutNative* builder = toNative(nativePtr);
+ ScopedCharArrayRO text(env, javaText);
+
// TODO: Reorganize minikin APIs.
- minikin::LineBreaker b;
- b.resize(length);
- env->GetCharArrayRegion(text, 0, length, b.buffer());
- b.setText();
+ minikin::LineBreaker b(minikin::U16StringPiece(text.get(), length));
if (variableTabStops == nullptr) {
b.setTabStops(nullptr, 0, defaultTabStop);
} else {
@@ -321,7 +319,6 @@
env->SetFloatArrayRegion(charWidths, 0, b.size(), b.charWidths());
- b.finish();
builder->clearRuns();
return static_cast<jint>(nBreaks);
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index 764288c..5d5aea2 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -305,6 +305,9 @@
optional SettingProto preferred_network_mode = 226;
optional SettingProto debug_app = 227;
optional SettingProto wait_for_debugger = 228;
+ optional SettingProto enable_gpu_debug_layers = 342;
+ optional SettingProto gpu_debug_app = 343;
+ optional SettingProto gpu_debug_layers = 344;
optional SettingProto low_power_mode = 229;
optional SettingProto low_power_mode_trigger_level = 230;
optional SettingProto always_finish_activities = 231;
@@ -384,7 +387,7 @@
optional SettingProto enable_deletion_helper_no_threshold_toggle = 340;
optional SettingProto notification_snooze_options = 341;
- // Next tag = 342;
+ // Next tag = 345;
}
message SecureSettingsProto {
diff --git a/core/res/Android.mk b/core/res/Android.mk
index b066929..370a01f 100644
--- a/core/res/Android.mk
+++ b/core/res/Android.mk
@@ -29,6 +29,9 @@
# Framework doesn't need versioning since it IS the platform.
LOCAL_AAPT_FLAGS += --no-auto-version
+# Allow overlay to add resource
+LOCAL_AAPT_FLAGS += --auto-add-overlay
+
# Install this alongside the libraries.
LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES)
diff --git a/core/res/res/anim/slide_out_micro.xml b/core/res/res/anim/slide_out_micro.xml
index 01df0da..c647093 100644
--- a/core/res/res/anim/slide_out_micro.xml
+++ b/core/res/res/anim/slide_out_micro.xml
@@ -19,7 +19,7 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:zAdjustment="normal">
+ android:zAdjustment="top">
<translate android:fromYDelta="0" android:toYDelta="5%p"
android:duration="250"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
diff --git a/core/res/res/values-watch/styles_material.xml b/core/res/res/values-watch/styles_material.xml
index fd88102..6cef47d 100644
--- a/core/res/res/values-watch/styles_material.xml
+++ b/core/res/res/values-watch/styles_material.xml
@@ -39,8 +39,8 @@
<item name="taskOpenExitAnimation">@anim/slide_in_exit_micro</item>
<item name="taskCloseEnterAnimation">@null</item>
<item name="taskCloseExitAnimation">@anim/slide_out_micro</item>
- <item name="taskToFrontEnterAnimation">@anim/slide_in_enter_micro</item>
- <item name="taskToFrontExitAnimation">@anim/slide_in_exit_micro</item>
+ <item name="taskToFrontEnterAnimation">@null</item>
+ <item name="taskToFrontExitAnimation">@anim/slide_out_micro</item>
<item name="taskToBackEnterAnimation">@null</item>
<item name="taskToBackExitAnimation">@anim/slide_out_micro</item>
<item name="wallpaperOpenEnterAnimation">@null</item>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index d36ed63..0d35f4e 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -356,6 +356,9 @@
Settings.Global.USE_GOOGLE_MAIL,
Settings.Global.VT_IMS_ENABLED,
Settings.Global.WAIT_FOR_DEBUGGER,
+ Settings.Global.ENABLE_GPU_DEBUG_LAYERS,
+ Settings.Global.GPU_DEBUG_APP,
+ Settings.Global.GPU_DEBUG_LAYERS,
Settings.Global.NETWORK_ACCESS_TIMEOUT_MS,
Settings.Global.WARNING_TEMPERATURE,
Settings.Global.WEBVIEW_DATA_REDUCTION_PROXY_KEY,
diff --git a/core/tests/coretests/src/android/text/format/FormatterTest.java b/core/tests/coretests/src/android/text/format/FormatterTest.java
index 24e3646..dee51dc 100644
--- a/core/tests/coretests/src/android/text/format/FormatterTest.java
+++ b/core/tests/coretests/src/android/text/format/FormatterTest.java
@@ -117,13 +117,13 @@
assertEquals("2 days", Formatter.formatShortElapsedTime(mContext, 2 * DAY));
assertEquals("1 day, 23 hr",
Formatter.formatShortElapsedTime(mContext, 1 * DAY + 23 * HOUR + 59 * MINUTE));
- assertEquals("1 day, 0 hr",
+ assertEquals("1 day",
Formatter.formatShortElapsedTime(mContext, 1 * DAY + 59 * MINUTE));
- assertEquals("1 day, 0 hr", Formatter.formatShortElapsedTime(mContext, 1 * DAY));
+ assertEquals("1 day", Formatter.formatShortElapsedTime(mContext, 1 * DAY));
assertEquals("24 hr", Formatter.formatShortElapsedTime(mContext, 23 * HOUR + 30 * MINUTE));
assertEquals("3 hr", Formatter.formatShortElapsedTime(mContext, 2 * HOUR + 30 * MINUTE));
assertEquals("2 hr", Formatter.formatShortElapsedTime(mContext, 2 * HOUR));
- assertEquals("1 hr, 0 min", Formatter.formatShortElapsedTime(mContext, 1 * HOUR));
+ assertEquals("1 hr", Formatter.formatShortElapsedTime(mContext, 1 * HOUR));
assertEquals("60 min",
Formatter.formatShortElapsedTime(mContext, 59 * MINUTE + 30 * SECOND));
assertEquals("59 min",
@@ -132,7 +132,7 @@
assertEquals("2 min", Formatter.formatShortElapsedTime(mContext, 2 * MINUTE));
assertEquals("1 min, 59 sec",
Formatter.formatShortElapsedTime(mContext, 1 * MINUTE + 59 * SECOND + 999));
- assertEquals("1 min, 0 sec", Formatter.formatShortElapsedTime(mContext, 1 * MINUTE));
+ assertEquals("1 min", Formatter.formatShortElapsedTime(mContext, 1 * MINUTE));
assertEquals("59 sec", Formatter.formatShortElapsedTime(mContext, 59 * SECOND + 999));
assertEquals("1 sec", Formatter.formatShortElapsedTime(mContext, 1 * SECOND));
assertEquals("0 sec", Formatter.formatShortElapsedTime(mContext, 1));
@@ -154,9 +154,9 @@
mContext, 2 * DAY));
assertEquals("1 day, 23 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
mContext, 1 * DAY + 23 * HOUR + 59 * MINUTE));
- assertEquals("1 day, 0 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
+ assertEquals("1 day", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
mContext, 1 * DAY + 59 * MINUTE));
- assertEquals("1 day, 0 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
+ assertEquals("1 day", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
mContext, 1 * DAY));
assertEquals("24 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
mContext, 23 * HOUR + 30 * MINUTE));
@@ -164,9 +164,9 @@
mContext, 2 * HOUR + 30 * MINUTE));
assertEquals("2 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
mContext, 2 * HOUR));
- assertEquals("1 hr, 0 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
+ assertEquals("1 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
mContext, 1 * HOUR));
- assertEquals("1 hr, 0 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
+ assertEquals("1 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
mContext, 59 * MINUTE + 30 * SECOND));
assertEquals("59 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
mContext, 59 * MINUTE));
diff --git a/docs/html/reference/images/camera2/metadata/android.colorCorrection.mode/processing_pipeline.png b/docs/html/reference/images/camera2/metadata/android.colorCorrection.mode/processing_pipeline.png
new file mode 100644
index 0000000..7578b48
--- /dev/null
+++ b/docs/html/reference/images/camera2/metadata/android.colorCorrection.mode/processing_pipeline.png
Binary files differ
diff --git a/docs/html/reference/images/camera2/metadata/android.statistics.lensShadingMap/blue_shading.png b/docs/html/reference/images/camera2/metadata/android.statistics.lensShadingMap/blue_shading.png
new file mode 100644
index 0000000..7b10f6b
--- /dev/null
+++ b/docs/html/reference/images/camera2/metadata/android.statistics.lensShadingMap/blue_shading.png
Binary files differ
diff --git a/docs/html/reference/images/camera2/metadata/android.statistics.lensShadingMap/green_e_shading.png b/docs/html/reference/images/camera2/metadata/android.statistics.lensShadingMap/green_e_shading.png
new file mode 100644
index 0000000..41972cf
--- /dev/null
+++ b/docs/html/reference/images/camera2/metadata/android.statistics.lensShadingMap/green_e_shading.png
Binary files differ
diff --git a/docs/html/reference/images/camera2/metadata/android.statistics.lensShadingMap/green_o_shading.png b/docs/html/reference/images/camera2/metadata/android.statistics.lensShadingMap/green_o_shading.png
new file mode 100644
index 0000000..d26600b
--- /dev/null
+++ b/docs/html/reference/images/camera2/metadata/android.statistics.lensShadingMap/green_o_shading.png
Binary files differ
diff --git a/docs/html/reference/images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png b/docs/html/reference/images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png
new file mode 100644
index 0000000..1e7208e
--- /dev/null
+++ b/docs/html/reference/images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png
Binary files differ
diff --git a/docs/html/reference/images/camera2/metadata/android.statistics.lensShadingMap/red_shading.png b/docs/html/reference/images/camera2/metadata/android.statistics.lensShadingMap/red_shading.png
new file mode 100644
index 0000000..ecef3ae
--- /dev/null
+++ b/docs/html/reference/images/camera2/metadata/android.statistics.lensShadingMap/red_shading.png
Binary files differ
diff --git a/docs/html/reference/images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png b/docs/html/reference/images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png
new file mode 100644
index 0000000..a02fd89
--- /dev/null
+++ b/docs/html/reference/images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png
Binary files differ
diff --git a/docs/html/reference/images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png b/docs/html/reference/images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png
new file mode 100644
index 0000000..c309ac5
--- /dev/null
+++ b/docs/html/reference/images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png
Binary files differ
diff --git a/docs/html/reference/images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png b/docs/html/reference/images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png
new file mode 100644
index 0000000..414fad4
--- /dev/null
+++ b/docs/html/reference/images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png
Binary files differ
diff --git a/docs/html/reference/images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png b/docs/html/reference/images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png
new file mode 100644
index 0000000..c147a87
--- /dev/null
+++ b/docs/html/reference/images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png
Binary files differ
diff --git a/docs/html/reference/images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png b/docs/html/reference/images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png
new file mode 100644
index 0000000..4ce2125
--- /dev/null
+++ b/docs/html/reference/images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png
Binary files differ
diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index 3bf4f90..dea194e 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -36,138 +36,69 @@
private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
- private static final int OPACITY_ENTER_DURATION = 600;
- private static final int OPACITY_ENTER_DURATION_FAST = 120;
- private static final int OPACITY_EXIT_DURATION = 480;
+ private static final int OPACITY_DURATION = 80;
- // Hardware rendering properties.
- private CanvasProperty<Paint> mPropPaint;
- private CanvasProperty<Float> mPropRadius;
- private CanvasProperty<Float> mPropX;
- private CanvasProperty<Float> mPropY;
+ private ObjectAnimator mAnimator;
- // Software rendering properties.
private float mOpacity = 0;
/** Whether this ripple is bounded. */
private boolean mIsBounded;
- public RippleBackground(RippleDrawable owner, Rect bounds, boolean isBounded,
- boolean forceSoftware) {
- super(owner, bounds, forceSoftware);
+ private boolean mFocused = false;
+ private boolean mHovered = false;
+
+ public RippleBackground(RippleDrawable owner, Rect bounds, boolean isBounded) {
+ super(owner, bounds);
mIsBounded = isBounded;
}
public boolean isVisible() {
- return mOpacity > 0 || isHardwareAnimating();
+ return mOpacity > 0;
}
- @Override
- protected boolean drawSoftware(Canvas c, Paint p) {
- boolean hasContent = false;
-
+ public void draw(Canvas c, Paint p) {
final int origAlpha = p.getAlpha();
- final int alpha = (int) (origAlpha * mOpacity + 0.5f);
+ final int alpha = Math.min((int) (origAlpha * mOpacity + 0.5f), 255);
if (alpha > 0) {
p.setAlpha(alpha);
c.drawCircle(0, 0, mTargetRadius, p);
p.setAlpha(origAlpha);
- hasContent = true;
}
-
- return hasContent;
}
- @Override
- protected boolean drawHardware(DisplayListCanvas c) {
- c.drawCircle(mPropX, mPropY, mPropRadius, mPropPaint);
- return true;
- }
-
- @Override
- protected Animator createSoftwareEnter(boolean fast) {
- // Linear enter based on current opacity.
- final int maxDuration = fast ? OPACITY_ENTER_DURATION_FAST : OPACITY_ENTER_DURATION;
- final int duration = (int) ((1 - mOpacity) * maxDuration);
-
- final ObjectAnimator opacity = ObjectAnimator.ofFloat(this, OPACITY, 1);
- opacity.setAutoCancel(true);
- opacity.setDuration(duration);
- opacity.setInterpolator(LINEAR_INTERPOLATOR);
-
- return opacity;
- }
-
- @Override
- protected Animator createSoftwareExit() {
- final AnimatorSet set = new AnimatorSet();
-
- // Linear exit after enter is completed.
- final ObjectAnimator exit = ObjectAnimator.ofFloat(this, OPACITY, 0);
- exit.setInterpolator(LINEAR_INTERPOLATOR);
- exit.setDuration(OPACITY_EXIT_DURATION);
- exit.setAutoCancel(true);
-
- final AnimatorSet.Builder builder = set.play(exit);
-
- // Linear "fast" enter based on current opacity.
- final int fastEnterDuration = mIsBounded ?
- (int) ((1 - mOpacity) * OPACITY_ENTER_DURATION_FAST) : 0;
- if (fastEnterDuration > 0) {
- final ObjectAnimator enter = ObjectAnimator.ofFloat(this, OPACITY, 1);
- enter.setInterpolator(LINEAR_INTERPOLATOR);
- enter.setDuration(fastEnterDuration);
- enter.setAutoCancel(true);
-
- builder.after(enter);
+ public void setState(boolean focused, boolean hovered, boolean animateChanged) {
+ if (mHovered != hovered || mFocused != focused) {
+ mHovered = hovered;
+ mFocused = focused;
+ onStateChanged(animateChanged);
}
-
- return set;
}
- @Override
- protected RenderNodeAnimatorSet createHardwareExit(Paint p) {
- final RenderNodeAnimatorSet set = new RenderNodeAnimatorSet();
-
- final int targetAlpha = p.getAlpha();
- final int currentAlpha = (int) (mOpacity * targetAlpha + 0.5f);
- p.setAlpha(currentAlpha);
-
- mPropPaint = CanvasProperty.createPaint(p);
- mPropRadius = CanvasProperty.createFloat(mTargetRadius);
- mPropX = CanvasProperty.createFloat(0);
- mPropY = CanvasProperty.createFloat(0);
-
- final int fastEnterDuration = mIsBounded ?
- (int) ((1 - mOpacity) * OPACITY_ENTER_DURATION_FAST) : 0;
-
- // Linear exit after enter is completed.
- final RenderNodeAnimator exit = new RenderNodeAnimator(
- mPropPaint, RenderNodeAnimator.PAINT_ALPHA, 0);
- exit.setInterpolator(LINEAR_INTERPOLATOR);
- exit.setDuration(OPACITY_EXIT_DURATION);
- if (fastEnterDuration > 0) {
- exit.setStartDelay(fastEnterDuration);
- exit.setStartValue(targetAlpha);
+ private void onStateChanged(boolean animateChanged) {
+ float newOpacity = 0.0f;
+ if (mHovered) newOpacity += 1.0f;
+ if (mFocused) newOpacity += 1.0f;
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ mAnimator = null;
}
- set.add(exit);
-
- // Linear "fast" enter based on current opacity.
- if (fastEnterDuration > 0) {
- final RenderNodeAnimator enter = new RenderNodeAnimator(
- mPropPaint, RenderNodeAnimator.PAINT_ALPHA, targetAlpha);
- enter.setInterpolator(LINEAR_INTERPOLATOR);
- enter.setDuration(fastEnterDuration);
- set.add(enter);
+ if (animateChanged) {
+ mAnimator = ObjectAnimator.ofFloat(this, OPACITY, newOpacity);
+ mAnimator.setDuration(OPACITY_DURATION);
+ mAnimator.setInterpolator(LINEAR_INTERPOLATOR);
+ mAnimator.start();
+ } else {
+ mOpacity = newOpacity;
}
-
- return set;
}
- @Override
- protected void jumpValuesToExit() {
- mOpacity = 0;
+ public void jumpToFinal() {
+ if (mAnimator != null) {
+ mAnimator.end();
+ mAnimator = null;
+ }
}
private static abstract class BackgroundProperty extends FloatProperty<RippleBackground> {
diff --git a/graphics/java/android/graphics/drawable/RippleComponent.java b/graphics/java/android/graphics/drawable/RippleComponent.java
index e83513c..0e38826 100644
--- a/graphics/java/android/graphics/drawable/RippleComponent.java
+++ b/graphics/java/android/graphics/drawable/RippleComponent.java
@@ -27,23 +27,14 @@
import java.util.ArrayList;
/**
- * Abstract class that handles hardware/software hand-off and lifecycle for
- * animated ripple foreground and background components.
+ * Abstract class that handles size & positioning common to the ripple & focus states.
*/
abstract class RippleComponent {
- private final RippleDrawable mOwner;
+ protected final RippleDrawable mOwner;
/** Bounds used for computing max radius. May be modified by the owner. */
protected final Rect mBounds;
- /** Whether we can use hardware acceleration for the exit animation. */
- private boolean mHasDisplayListCanvas;
-
- private boolean mHasPendingHardwareAnimator;
- private RenderNodeAnimatorSet mHardwareAnimator;
-
- private Animator mSoftwareAnimator;
-
/** Whether we have an explicit maximum radius. */
private boolean mHasMaxRadius;
@@ -53,16 +44,9 @@
/** Screen density used to adjust pixel-based constants. */
protected float mDensityScale;
- /**
- * If set, force all ripple animations to not run on RenderThread, even if it would be
- * available.
- */
- private final boolean mForceSoftware;
-
- public RippleComponent(RippleDrawable owner, Rect bounds, boolean forceSoftware) {
+ public RippleComponent(RippleDrawable owner, Rect bounds) {
mOwner = owner;
mBounds = bounds;
- mForceSoftware = forceSoftware;
}
public void onBoundsChange() {
@@ -92,89 +76,6 @@
}
/**
- * Starts a ripple enter animation.
- *
- * @param fast whether the ripple should enter quickly
- */
- public final void enter(boolean fast) {
- cancel();
-
- mSoftwareAnimator = createSoftwareEnter(fast);
-
- if (mSoftwareAnimator != null) {
- mSoftwareAnimator.start();
- }
- }
-
- /**
- * Starts a ripple exit animation.
- */
- public final void exit() {
- cancel();
-
- if (mHasDisplayListCanvas) {
- // We don't have access to a canvas here, but we expect one on the
- // next frame. We'll start the render thread animation then.
- mHasPendingHardwareAnimator = true;
-
- // Request another frame.
- invalidateSelf();
- } else {
- mSoftwareAnimator = createSoftwareExit();
- mSoftwareAnimator.start();
- }
- }
-
- /**
- * Cancels all animations. Software animation values are left in the
- * current state, while hardware animation values jump to the end state.
- */
- public void cancel() {
- cancelSoftwareAnimations();
- endHardwareAnimations();
- }
-
- /**
- * Ends all animations, jumping values to the end state.
- */
- public void end() {
- endSoftwareAnimations();
- endHardwareAnimations();
- }
-
- /**
- * Draws the ripple to the canvas, inheriting the paint's color and alpha
- * properties.
- *
- * @param c the canvas to which the ripple should be drawn
- * @param p the paint used to draw the ripple
- * @return {@code true} if something was drawn, {@code false} otherwise
- */
- public boolean draw(Canvas c, Paint p) {
- final boolean hasDisplayListCanvas = !mForceSoftware && c.isHardwareAccelerated()
- && c instanceof DisplayListCanvas;
- if (mHasDisplayListCanvas != hasDisplayListCanvas) {
- mHasDisplayListCanvas = hasDisplayListCanvas;
-
- if (!hasDisplayListCanvas) {
- // We've switched from hardware to non-hardware mode. Panic.
- endHardwareAnimations();
- }
- }
-
- if (hasDisplayListCanvas) {
- final DisplayListCanvas hw = (DisplayListCanvas) c;
- startPendingAnimation(hw, p);
-
- if (mHardwareAnimator != null) {
- return drawHardware(hw);
- }
- }
-
- return drawSoftware(c, p);
- }
-
- /**
* Populates {@code bounds} with the maximum drawing bounds of the ripple
* relative to its center. The resulting bounds should be translated into
* parent drawable coordinates before use.
@@ -186,77 +87,10 @@
bounds.set(-r, -r, r, r);
}
- /**
- * Starts the pending hardware animation, if available.
- *
- * @param hw hardware canvas on which the animation should draw
- * @param p paint whose properties the hardware canvas should use
- */
- private void startPendingAnimation(DisplayListCanvas hw, Paint p) {
- if (mHasPendingHardwareAnimator) {
- mHasPendingHardwareAnimator = false;
-
- mHardwareAnimator = createHardwareExit(new Paint(p));
- mHardwareAnimator.start(hw);
-
- // Preemptively jump the software values to the end state now that
- // the hardware exit has read whatever values it needs.
- jumpValuesToExit();
- }
- }
-
- /**
- * Cancels any current software animations, leaving the values in their
- * current state.
- */
- private void cancelSoftwareAnimations() {
- if (mSoftwareAnimator != null) {
- mSoftwareAnimator.cancel();
- mSoftwareAnimator = null;
- }
- }
-
- /**
- * Ends any current software animations, jumping the values to their end
- * state.
- */
- private void endSoftwareAnimations() {
- if (mSoftwareAnimator != null) {
- mSoftwareAnimator.end();
- mSoftwareAnimator = null;
- }
- }
-
- /**
- * Ends any pending or current hardware animations.
- * <p>
- * Hardware animations can't synchronize values back to the software
- * thread, so there is no "cancel" equivalent.
- */
- private void endHardwareAnimations() {
- if (mHardwareAnimator != null) {
- mHardwareAnimator.end();
- mHardwareAnimator = null;
- }
-
- if (mHasPendingHardwareAnimator) {
- mHasPendingHardwareAnimator = false;
-
- // Manually jump values to their exited state. Normally we'd do that
- // later when starting the hardware exit, but we're aborting early.
- jumpValuesToExit();
- }
- }
-
protected final void invalidateSelf() {
mOwner.invalidateSelf(false);
}
- protected final boolean isHardwareAnimating() {
- return mHardwareAnimator != null && mHardwareAnimator.isRunning()
- || mHasPendingHardwareAnimator;
- }
-
protected final void onHotspotBoundsChanged() {
if (!mHasMaxRadius) {
final float halfWidth = mBounds.width() / 2.0f;
@@ -276,76 +110,4 @@
protected void onTargetRadiusChanged(float targetRadius) {
// Stub.
}
-
- protected abstract Animator createSoftwareEnter(boolean fast);
-
- protected abstract Animator createSoftwareExit();
-
- protected abstract RenderNodeAnimatorSet createHardwareExit(Paint p);
-
- protected abstract boolean drawHardware(DisplayListCanvas c);
-
- protected abstract boolean drawSoftware(Canvas c, Paint p);
-
- /**
- * Called when the hardware exit is cancelled. Jumps software values to end
- * state to ensure that software and hardware values are synchronized.
- */
- protected abstract void jumpValuesToExit();
-
- public static class RenderNodeAnimatorSet {
- private final ArrayList<RenderNodeAnimator> mAnimators = new ArrayList<>();
-
- public void add(RenderNodeAnimator anim) {
- mAnimators.add(anim);
- }
-
- public void clear() {
- mAnimators.clear();
- }
-
- public void start(DisplayListCanvas target) {
- if (target == null) {
- throw new IllegalArgumentException("Hardware canvas must be non-null");
- }
-
- final ArrayList<RenderNodeAnimator> animators = mAnimators;
- final int N = animators.size();
- for (int i = 0; i < N; i++) {
- final RenderNodeAnimator anim = animators.get(i);
- anim.setTarget(target);
- anim.start();
- }
- }
-
- public void cancel() {
- final ArrayList<RenderNodeAnimator> animators = mAnimators;
- final int N = animators.size();
- for (int i = 0; i < N; i++) {
- final RenderNodeAnimator anim = animators.get(i);
- anim.cancel();
- }
- }
-
- public void end() {
- final ArrayList<RenderNodeAnimator> animators = mAnimators;
- final int N = animators.size();
- for (int i = 0; i < N; i++) {
- final RenderNodeAnimator anim = animators.get(i);
- anim.end();
- }
- }
-
- public boolean isRunning() {
- final ArrayList<RenderNodeAnimator> animators = mAnimators;
- final int N = animators.size();
- for (int i = 0; i < N; i++) {
- final RenderNodeAnimator anim = animators.get(i);
- if (anim.isRunning()) {
- return true;
- }
- }
- return false;
- }
- }
}
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 1727eca..8b185f2 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -16,11 +16,6 @@
package android.graphics.drawable;
-import com.android.internal.R;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.ActivityInfo.Config;
@@ -42,6 +37,11 @@
import android.graphics.Shader;
import android.util.AttributeSet;
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
import java.util.Arrays;
@@ -135,9 +135,6 @@
private PorterDuffColorFilter mMaskColorFilter;
private boolean mHasValidMask;
- /** Whether we expect to draw a background when visible. */
- private boolean mBackgroundActive;
-
/** The current ripple. May be actively animating or pending entry. */
private RippleForeground mRipple;
@@ -217,7 +214,7 @@
}
if (mBackground != null) {
- mBackground.end();
+ mBackground.jumpToFinal();
}
cancelExitingRipples();
@@ -266,9 +263,9 @@
}
}
- setRippleActive(focused || (enabled && pressed));
+ setRippleActive(enabled && pressed);
- setBackgroundActive(hovered, hovered);
+ setBackgroundActive(hovered, focused);
return changed;
}
@@ -283,14 +280,13 @@
}
}
- private void setBackgroundActive(boolean active, boolean focused) {
- if (mBackgroundActive != active) {
- mBackgroundActive = active;
- if (active) {
- tryBackgroundEnter(focused);
- } else {
- tryBackgroundExit();
- }
+ private void setBackgroundActive(boolean hovered, boolean focused) {
+ if (mBackground == null && (hovered || focused)) {
+ mBackground = new RippleBackground(this, mHotspotBounds, isBounded());
+ mBackground.setup(mState.mMaxRadius, mDensity);
+ }
+ if (mBackground != null) {
+ mBackground.setState(focused, hovered, true);
}
}
@@ -327,10 +323,6 @@
tryRippleEnter();
}
- if (mBackgroundActive) {
- tryBackgroundEnter(false);
- }
-
// Skip animations, just show the correct final states.
jumpToCurrentState();
}
@@ -546,26 +538,6 @@
}
/**
- * Creates an active hotspot at the specified location.
- */
- private void tryBackgroundEnter(boolean focused) {
- if (mBackground == null) {
- final boolean isBounded = isBounded();
- mBackground = new RippleBackground(this, mHotspotBounds, isBounded, mForceSoftware);
- }
-
- mBackground.setup(mState.mMaxRadius, mDensity);
- mBackground.enter(focused);
- }
-
- private void tryBackgroundExit() {
- if (mBackground != null) {
- // Don't null out the background, we need it to draw!
- mBackground.exit();
- }
- }
-
- /**
* Attempts to start an enter animation for the active hotspot. Fails if
* there are too many animating ripples.
*/
@@ -593,7 +565,7 @@
}
mRipple.setup(mState.mMaxRadius, mDensity);
- mRipple.enter(false);
+ mRipple.enter();
}
/**
@@ -623,9 +595,7 @@
}
if (mBackground != null) {
- mBackground.end();
- mBackground = null;
- mBackgroundActive = false;
+ mBackground.setState(false, false, false);
}
cancelExitingRipples();
@@ -858,38 +828,8 @@
final float y = mHotspotBounds.exactCenterY();
canvas.translate(x, y);
- updateMaskShaderIfNeeded();
-
- // Position the shader to account for canvas translation.
- if (mMaskShader != null) {
- final Rect bounds = getBounds();
- mMaskMatrix.setTranslate(bounds.left - x, bounds.top - y);
- mMaskShader.setLocalMatrix(mMaskMatrix);
- }
-
- // Grab the color for the current state and cut the alpha channel in
- // half so that the ripple and background together yield full alpha.
- final int color = mState.mColor.getColorForState(getState(), Color.BLACK);
- final int halfAlpha = (Color.alpha(color) / 2) << 24;
final Paint p = getRipplePaint();
- if (mMaskColorFilter != null) {
- // The ripple timing depends on the paint's alpha value, so we need
- // to push just the alpha channel into the paint and let the filter
- // handle the full-alpha color.
- final int fullAlphaColor = color | (0xFF << 24);
- mMaskColorFilter.setColor(fullAlphaColor);
-
- p.setColor(halfAlpha);
- p.setColorFilter(mMaskColorFilter);
- p.setShader(mMaskShader);
- } else {
- final int halfAlphaColor = (color & 0xFFFFFF) | halfAlpha;
- p.setColor(halfAlphaColor);
- p.setColorFilter(null);
- p.setShader(null);
- }
-
if (background != null && background.isVisible()) {
background.draw(canvas, p);
}
@@ -912,13 +852,49 @@
mMask.draw(canvas);
}
- private Paint getRipplePaint() {
+ Paint getRipplePaint() {
if (mRipplePaint == null) {
mRipplePaint = new Paint();
mRipplePaint.setAntiAlias(true);
mRipplePaint.setStyle(Paint.Style.FILL);
}
- return mRipplePaint;
+
+ final float x = mHotspotBounds.exactCenterX();
+ final float y = mHotspotBounds.exactCenterY();
+
+ updateMaskShaderIfNeeded();
+
+ // Position the shader to account for canvas translation.
+ if (mMaskShader != null) {
+ final Rect bounds = getBounds();
+ mMaskMatrix.setTranslate(bounds.left - x, bounds.top - y);
+ mMaskShader.setLocalMatrix(mMaskMatrix);
+ }
+
+ // Grab the color for the current state and cut the alpha channel in
+ // half so that the ripple and background together yield full alpha.
+ final int color = mState.mColor.getColorForState(getState(), Color.BLACK);
+ final int halfAlpha = (Color.alpha(color) / 2) << 24;
+ final Paint p = mRipplePaint;
+
+ if (mMaskColorFilter != null) {
+ // The ripple timing depends on the paint's alpha value, so we need
+ // to push just the alpha channel into the paint and let the filter
+ // handle the full-alpha color.
+ final int fullAlphaColor = color | (0xFF << 24);
+ mMaskColorFilter.setColor(fullAlphaColor);
+
+ p.setColor(halfAlpha);
+ p.setColorFilter(mMaskColorFilter);
+ p.setShader(mMaskShader);
+ } else {
+ final int halfAlphaColor = (color & 0xFFFFFF) | halfAlpha;
+ p.setColor(halfAlphaColor);
+ p.setColorFilter(null);
+ p.setShader(null);
+ }
+
+ return p;
}
@Override
diff --git a/graphics/java/android/graphics/drawable/RippleForeground.java b/graphics/java/android/graphics/drawable/RippleForeground.java
index a675eaf..0b5020c 100644
--- a/graphics/java/android/graphics/drawable/RippleForeground.java
+++ b/graphics/java/android/graphics/drawable/RippleForeground.java
@@ -18,7 +18,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.graphics.Canvas;
@@ -29,8 +28,11 @@
import android.util.MathUtils;
import android.view.DisplayListCanvas;
import android.view.RenderNodeAnimator;
+import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
+import java.util.ArrayList;
+
/**
* Draws a ripple foreground.
*/
@@ -40,7 +42,7 @@
400f, 1.4f, 0);
// Pixel-based accelerations and velocities.
- private static final float WAVE_TOUCH_DOWN_ACCELERATION = 1024;
+ private static final float WAVE_TOUCH_DOWN_ACCELERATION = 2048;
private static final float WAVE_OPACITY_DECAY_VELOCITY = 3;
// Bounded ripple animation properties.
@@ -49,8 +51,9 @@
private static final int BOUNDED_OPACITY_EXIT_DURATION = 400;
private static final float MAX_BOUNDED_RADIUS = 350;
- private static final int RIPPLE_ENTER_DELAY = 80;
- private static final int OPACITY_ENTER_DURATION_FAST = 120;
+ private static final int OPACITY_ENTER_DURATION = 75;
+ private static final int OPACITY_EXIT_DURATION = 150;
+ private static final int OPACITY_HOLD_DURATION = OPACITY_ENTER_DURATION + 150;
// Parent-relative values for starting position.
private float mStartingX;
@@ -72,7 +75,7 @@
private float mBoundedRadius = 0;
// Software rendering properties.
- private float mOpacity = 1;
+ private float mOpacity = 0;
// Values used to tween between the start and end positions.
private float mTweenRadius = 0;
@@ -82,6 +85,22 @@
/** Whether this ripple has finished its exit animation. */
private boolean mHasFinishedExit;
+ /** Whether we can use hardware acceleration for the exit animation. */
+ private boolean mUsingProperties;
+
+ private long mEnterStartedAtMillis;
+
+ private ArrayList<RenderNodeAnimator> mPendingHwAnimators = new ArrayList<>();
+ private ArrayList<RenderNodeAnimator> mRunningHwAnimators = new ArrayList<>();
+
+ private ArrayList<Animator> mRunningSwAnimators = new ArrayList<>();
+
+ /**
+ * If set, force all ripple animations to not run on RenderThread, even if it would be
+ * available.
+ */
+ private final boolean mForceSoftware;
+
/**
* If we have a bound, don't start from 0. Start from 60% of the max out of width and height.
*/
@@ -89,8 +108,9 @@
public RippleForeground(RippleDrawable owner, Rect bounds, float startingX, float startingY,
boolean isBounded, boolean forceSoftware) {
- super(owner, bounds, forceSoftware);
+ super(owner, bounds);
+ mForceSoftware = forceSoftware;
mStartingX = startingX;
mStartingY = startingY;
@@ -109,10 +129,7 @@
clampStartingPosition();
}
- @Override
- protected boolean drawSoftware(Canvas c, Paint p) {
- boolean hasContent = false;
-
+ private void drawSoftware(Canvas c, Paint p) {
final int origAlpha = p.getAlpha();
final int alpha = (int) (origAlpha * mOpacity + 0.5f);
final float radius = getCurrentRadius();
@@ -122,16 +139,51 @@
p.setAlpha(alpha);
c.drawCircle(x, y, radius, p);
p.setAlpha(origAlpha);
- hasContent = true;
}
-
- return hasContent;
}
- @Override
- protected boolean drawHardware(DisplayListCanvas c) {
- c.drawCircle(mPropX, mPropY, mPropRadius, mPropPaint);
- return true;
+ private void startPending(DisplayListCanvas c) {
+ if (!mPendingHwAnimators.isEmpty()) {
+ for (int i = 0; i < mPendingHwAnimators.size(); i++) {
+ RenderNodeAnimator animator = mPendingHwAnimators.get(i);
+ animator.setTarget(c);
+ animator.start();
+ mRunningHwAnimators.add(animator);
+ }
+ mPendingHwAnimators.clear();
+ }
+ }
+
+ private void pruneHwFinished() {
+ if (!mRunningHwAnimators.isEmpty()) {
+ for (int i = mRunningHwAnimators.size() - 1; i >= 0; i--) {
+ if (!mRunningHwAnimators.get(i).isRunning()) {
+ mRunningHwAnimators.remove(i);
+ }
+ }
+ }
+ }
+
+ private void pruneSwFinished() {
+ if (!mRunningSwAnimators.isEmpty()) {
+ for (int i = mRunningSwAnimators.size() - 1; i >= 0; i--) {
+ if (!mRunningSwAnimators.get(i).isRunning()) {
+ mRunningSwAnimators.remove(i);
+ }
+ }
+ }
+ }
+
+ private void drawHardware(DisplayListCanvas c, Paint p) {
+ startPending(c);
+ pruneHwFinished();
+ if (mPropPaint != null) {
+ mUsingProperties = true;
+ c.drawCircle(mPropX, mPropY, mPropRadius, mPropPaint);
+ } else {
+ mUsingProperties = false;
+ drawSoftware(c, p);
+ }
}
/**
@@ -162,31 +214,115 @@
return mHasFinishedExit;
}
- @Override
- protected Animator createSoftwareEnter(boolean fast) {
+ private long computeFadeOutDelay() {
+ long timeSinceEnter = AnimationUtils.currentAnimationTimeMillis() - mEnterStartedAtMillis;
+ if (timeSinceEnter > 0 && timeSinceEnter < OPACITY_HOLD_DURATION) {
+ return OPACITY_HOLD_DURATION - timeSinceEnter;
+ }
+ return 0;
+ }
+
+ private void startSoftwareEnter() {
+ for (int i = 0; i < mRunningSwAnimators.size(); i++) {
+ mRunningSwAnimators.get(i).cancel();
+ }
+ mRunningSwAnimators.clear();
+
final int duration = getRadiusDuration();
final ObjectAnimator tweenRadius = ObjectAnimator.ofFloat(this, TWEEN_RADIUS, 1);
- tweenRadius.setAutoCancel(true);
tweenRadius.setDuration(duration);
tweenRadius.setInterpolator(DECELERATE_INTERPOLATOR);
- tweenRadius.setStartDelay(RIPPLE_ENTER_DELAY);
+ tweenRadius.start();
+ mRunningSwAnimators.add(tweenRadius);
final ObjectAnimator tweenOrigin = ObjectAnimator.ofFloat(this, TWEEN_ORIGIN, 1);
- tweenOrigin.setAutoCancel(true);
tweenOrigin.setDuration(duration);
tweenOrigin.setInterpolator(DECELERATE_INTERPOLATOR);
- tweenOrigin.setStartDelay(RIPPLE_ENTER_DELAY);
+ tweenOrigin.start();
+ mRunningSwAnimators.add(tweenOrigin);
final ObjectAnimator opacity = ObjectAnimator.ofFloat(this, OPACITY, 1);
- opacity.setAutoCancel(true);
- opacity.setDuration(OPACITY_ENTER_DURATION_FAST);
+ opacity.setDuration(OPACITY_ENTER_DURATION);
opacity.setInterpolator(LINEAR_INTERPOLATOR);
+ opacity.start();
+ mRunningSwAnimators.add(opacity);
+ }
- final AnimatorSet set = new AnimatorSet();
- set.play(tweenOrigin).with(tweenRadius).with(opacity);
+ private void startSoftwareExit() {
+ final ObjectAnimator opacity = ObjectAnimator.ofFloat(this, OPACITY, 0);
+ opacity.setDuration(OPACITY_EXIT_DURATION);
+ opacity.setInterpolator(LINEAR_INTERPOLATOR);
+ opacity.addListener(mAnimationListener);
+ opacity.setStartDelay(computeFadeOutDelay());
+ opacity.start();
+ mRunningSwAnimators.add(opacity);
+ }
- return set;
+ private void startHardwareEnter() {
+ if (mForceSoftware) { return; }
+ mPropX = CanvasProperty.createFloat(getCurrentX());
+ mPropY = CanvasProperty.createFloat(getCurrentY());
+ mPropRadius = CanvasProperty.createFloat(getCurrentRadius());
+ final Paint paint = mOwner.getRipplePaint();
+ mPropPaint = CanvasProperty.createPaint(paint);
+
+ final int radiusDuration = getRadiusDuration();
+
+ final RenderNodeAnimator radius = new RenderNodeAnimator(mPropRadius, mTargetRadius);
+ radius.setDuration(radiusDuration);
+ radius.setInterpolator(DECELERATE_INTERPOLATOR);
+ mPendingHwAnimators.add(radius);
+
+ final RenderNodeAnimator x = new RenderNodeAnimator(mPropX, mTargetX);
+ x.setDuration(radiusDuration);
+ x.setInterpolator(DECELERATE_INTERPOLATOR);
+ mPendingHwAnimators.add(x);
+
+ final RenderNodeAnimator y = new RenderNodeAnimator(mPropY, mTargetY);
+ y.setDuration(radiusDuration);
+ y.setInterpolator(DECELERATE_INTERPOLATOR);
+ mPendingHwAnimators.add(y);
+
+ final RenderNodeAnimator opacity = new RenderNodeAnimator(mPropPaint,
+ RenderNodeAnimator.PAINT_ALPHA, paint.getAlpha());
+ opacity.setDuration(OPACITY_ENTER_DURATION);
+ opacity.setInterpolator(LINEAR_INTERPOLATOR);
+ opacity.setStartValue(0);
+ mPendingHwAnimators.add(opacity);
+
+ invalidateSelf();
+ }
+
+ private void startHardwareExit() {
+ // Only run a hardware exit if we had a hardware enter to continue from
+ if (mForceSoftware || mPropPaint == null) return;
+
+ final RenderNodeAnimator opacity = new RenderNodeAnimator(mPropPaint,
+ RenderNodeAnimator.PAINT_ALPHA, 0);
+ opacity.setDuration(OPACITY_EXIT_DURATION);
+ opacity.setInterpolator(LINEAR_INTERPOLATOR);
+ opacity.addListener(mAnimationListener);
+ opacity.setStartDelay(computeFadeOutDelay());
+ mPendingHwAnimators.add(opacity);
+ invalidateSelf();
+ }
+
+ /**
+ * Starts a ripple enter animation.
+ */
+ public final void enter() {
+ mEnterStartedAtMillis = AnimationUtils.currentAnimationTimeMillis();
+ startSoftwareEnter();
+ startHardwareEnter();
+ }
+
+ /**
+ * Starts a ripple exit animation.
+ */
+ public final void exit() {
+ startSoftwareExit();
+ startHardwareExit();
}
private float getCurrentX() {
@@ -207,96 +343,23 @@
return MathUtils.lerp(mStartRadius, mTargetRadius, mTweenRadius);
}
- private int getOpacityExitDuration() {
- return (int) (1000 * mOpacity / WAVE_OPACITY_DECAY_VELOCITY + 0.5f);
- }
+ /**
+ * Draws the ripple to the canvas, inheriting the paint's color and alpha
+ * properties.
+ *
+ * @param c the canvas to which the ripple should be drawn
+ * @param p the paint used to draw the ripple
+ */
+ public void draw(Canvas c, Paint p) {
+ final boolean hasDisplayListCanvas = !mForceSoftware && c instanceof DisplayListCanvas;
- @Override
- protected Animator createSoftwareExit() {
- final int radiusDuration;
- final int originDuration;
- final int opacityDuration;
-
- radiusDuration = getRadiusDuration();
- originDuration = radiusDuration;
- opacityDuration = getOpacityExitDuration();
-
- final ObjectAnimator tweenRadius = ObjectAnimator.ofFloat(this, TWEEN_RADIUS, 1);
- tweenRadius.setAutoCancel(true);
- tweenRadius.setDuration(radiusDuration);
- tweenRadius.setInterpolator(DECELERATE_INTERPOLATOR);
-
- final ObjectAnimator tweenOrigin = ObjectAnimator.ofFloat(this, TWEEN_ORIGIN, 1);
- tweenOrigin.setAutoCancel(true);
- tweenOrigin.setDuration(originDuration);
- tweenOrigin.setInterpolator(DECELERATE_INTERPOLATOR);
-
- final ObjectAnimator opacity = ObjectAnimator.ofFloat(this, OPACITY, 0);
- opacity.setAutoCancel(true);
- opacity.setDuration(opacityDuration);
- opacity.setInterpolator(LINEAR_INTERPOLATOR);
-
- final AnimatorSet set = new AnimatorSet();
- set.play(tweenOrigin).with(tweenRadius).with(opacity);
- set.addListener(mAnimationListener);
-
- return set;
- }
-
- @Override
- protected RenderNodeAnimatorSet createHardwareExit(Paint p) {
- final int radiusDuration;
- final int originDuration;
- final int opacityDuration;
-
- radiusDuration = getRadiusDuration();
- originDuration = radiusDuration;
- opacityDuration = getOpacityExitDuration();
-
- final float startX = getCurrentX();
- final float startY = getCurrentY();
- final float startRadius = getCurrentRadius();
-
- p.setAlpha((int) (p.getAlpha() * mOpacity + 0.5f));
-
- mPropPaint = CanvasProperty.createPaint(p);
- mPropRadius = CanvasProperty.createFloat(startRadius);
- mPropX = CanvasProperty.createFloat(startX);
- mPropY = CanvasProperty.createFloat(startY);
-
- final RenderNodeAnimator radius = new RenderNodeAnimator(mPropRadius, mTargetRadius);
- radius.setDuration(radiusDuration);
- radius.setInterpolator(DECELERATE_INTERPOLATOR);
-
- final RenderNodeAnimator x = new RenderNodeAnimator(mPropX, mTargetX);
- x.setDuration(originDuration);
- x.setInterpolator(DECELERATE_INTERPOLATOR);
-
- final RenderNodeAnimator y = new RenderNodeAnimator(mPropY, mTargetY);
- y.setDuration(originDuration);
- y.setInterpolator(DECELERATE_INTERPOLATOR);
-
- final RenderNodeAnimator opacity = new RenderNodeAnimator(mPropPaint,
- RenderNodeAnimator.PAINT_ALPHA, 0);
- opacity.setDuration(opacityDuration);
- opacity.setInterpolator(LINEAR_INTERPOLATOR);
- opacity.addListener(mAnimationListener);
-
- final RenderNodeAnimatorSet set = new RenderNodeAnimatorSet();
- set.add(radius);
- set.add(opacity);
- set.add(x);
- set.add(y);
-
- return set;
- }
-
- @Override
- protected void jumpValuesToExit() {
- mOpacity = 0;
- mTweenX = 1;
- mTweenY = 1;
- mTweenRadius = 1;
+ pruneSwFinished();
+ if (hasDisplayListCanvas) {
+ final DisplayListCanvas hw = (DisplayListCanvas) c;
+ drawHardware(hw, p);
+ } else {
+ drawSoftware(c, p);
+ }
}
/**
@@ -319,10 +382,39 @@
}
}
+ /**
+ * Ends all animations, jumping values to the end state.
+ */
+ public void end() {
+ for (int i = 0; i < mRunningSwAnimators.size(); i++) {
+ mRunningSwAnimators.get(i).end();
+ }
+ mRunningSwAnimators.clear();
+ for (int i = 0; i < mRunningHwAnimators.size(); i++) {
+ mRunningHwAnimators.get(i).end();
+ }
+ mRunningHwAnimators.clear();
+ }
+
+ private void onAnimationPropertyChanged() {
+ if (!mUsingProperties) {
+ invalidateSelf();
+ }
+ }
+
private final AnimatorListenerAdapter mAnimationListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animator) {
mHasFinishedExit = true;
+ pruneHwFinished();
+ pruneSwFinished();
+
+ if (mRunningHwAnimators.isEmpty()) {
+ mPropPaint = null;
+ mPropRadius = null;
+ mPropX = null;
+ mPropY = null;
+ }
}
};
@@ -361,7 +453,7 @@
@Override
public void setValue(RippleForeground object, float value) {
object.mTweenRadius = value;
- object.invalidateSelf();
+ object.onAnimationPropertyChanged();
}
@Override
@@ -375,18 +467,18 @@
*/
private static final FloatProperty<RippleForeground> TWEEN_ORIGIN =
new FloatProperty<RippleForeground>("tweenOrigin") {
- @Override
- public void setValue(RippleForeground object, float value) {
- object.mTweenX = value;
- object.mTweenY = value;
- object.invalidateSelf();
- }
+ @Override
+ public void setValue(RippleForeground object, float value) {
+ object.mTweenX = value;
+ object.mTweenY = value;
+ object.onAnimationPropertyChanged();
+ }
- @Override
- public Float get(RippleForeground object) {
- return object.mTweenX;
- }
- };
+ @Override
+ public Float get(RippleForeground object) {
+ return object.mTweenX;
+ }
+ };
/**
* Property for animating opacity between 0 and its target value.
@@ -396,7 +488,7 @@
@Override
public void setValue(RippleForeground object, float value) {
object.mOpacity = value;
- object.invalidateSelf();
+ object.onAnimationPropertyChanged();
}
@Override
diff --git a/legacy-test/Android.mk b/legacy-test/Android.mk
index bec22c9..4c150c8 100644
--- a/legacy-test/Android.mk
+++ b/legacy-test/Android.mk
@@ -146,6 +146,7 @@
LOCAL_SRC_FILES := \
$(call all-java-files-under, src/android) \
$(call all-java-files-under, ../test-runner/src/android) \
+ $(call all-java-files-under, ../test-mock/src/android) \
$(call all-java-files-under, src/com)
LOCAL_MODULE := legacy-android-test
LOCAL_NO_STANDARD_LIBRARIES := true
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 24ce1e4..5c577ae 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -2,9 +2,10 @@
name: "hwui_defaults",
defaults: [
"hwui_static_deps",
- "skia_deps"
+ "skia_deps",
//"hwui_bugreport_font_cache_usage",
//"hwui_compile_for_perf",
+ "hwui_pgo",
],
cpp_std: "c++17",
@@ -109,6 +110,22 @@
include_dirs: ["frameworks/native/opengl/libs/GLES2"],
}
+// Build libhwui with PGO by default.
+// Location of PGO profile data is defined in build/soong/cc/pgo.go
+// and is separate from hwui.
+// To turn it off, set ANDROID_PGO_NO_PROFILE_USE environment variable
+// or set enable_profile_use property to false.
+cc_defaults {
+ name: "hwui_pgo",
+
+ pgo: {
+ instrumentation: true,
+ profile_file: "hwui/hwui.profdata",
+ benchmarks: ["hwui"],
+ enable_profile_use: false,
+ },
+}
+
// ------------------------
// library
// ------------------------
@@ -255,18 +272,6 @@
// Has moderate overhead
"hwui_enable_opengl_validation",
],
-
- // Build libhwui with PGO by default.
- // Location of PGO profile data is defined in build/soong/cc/pgo.go
- // and is separate from hwui.
- // To turn it off, set ANDROID_PGO_NO_PROFILE_USE environment variable
- // or set enable_profile_use property to false.
- pgo: {
- instrumentation: true,
- profile_file: "hwui/hwui.profdata",
- benchmarks: ["hwui"],
- enable_profile_use: false,
- },
}
// ------------------------
diff --git a/libs/protoutil/include/android/util/ProtoOutputStream.h b/libs/protoutil/include/android/util/ProtoOutputStream.h
index ce41849..faea9b2 100644
--- a/libs/protoutil/include/android/util/ProtoOutputStream.h
+++ b/libs/protoutil/include/android/util/ProtoOutputStream.h
@@ -110,6 +110,12 @@
void end(long long token);
/**
+ * Returns how many bytes are buffered in ProtoOutputStream.
+ * Notice, this is not the actual(compact) size of the output data.
+ */
+ size_t bytesWritten();
+
+ /**
* Flushes the protobuf data out to given fd. When the following functions are called,
* it is not able to write to ProtoOutputStream any more since the data is compact.
*/
diff --git a/libs/protoutil/src/ProtoOutputStream.cpp b/libs/protoutil/src/ProtoOutputStream.cpp
index 9d8ee72..1904d40 100644
--- a/libs/protoutil/src/ProtoOutputStream.cpp
+++ b/libs/protoutil/src/ProtoOutputStream.cpp
@@ -295,6 +295,12 @@
}
}
+size_t
+ProtoOutputStream::bytesWritten()
+{
+ return mBuffer.size();
+}
+
bool
ProtoOutputStream::compact() {
if (mCompact) return true;
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 1feea89..12e5744 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -91,10 +91,10 @@
* are only decrypted when the samples are delivered to the decoder.
* <p>
* MediaDrm methods throw {@link android.media.MediaDrm.MediaDrmStateException}
- * when a method is called on a MediaDrm object that has had an unrecoverable failure
- * in the DRM plugin or security hardware.
- * {@link android.media.MediaDrm.MediaDrmStateException} extends
- * {@link java.lang.IllegalStateException} with the addition of a developer-readable
+ * when a method is called on a MediaDrm object that has had an unrecoverable failure
+ * in the DRM plugin or security hardware.
+ * {@link android.media.MediaDrm.MediaDrmStateException} extends
+ * {@link java.lang.IllegalStateException} with the addition of a developer-readable
* diagnostic information string associated with the exception.
* <p>
* In the event of a mediaserver process crash or restart while a MediaDrm object
@@ -102,9 +102,9 @@
* To recover, the app must release the MediaDrm object, then create and initialize
* a new one.
* <p>
- * As {@link android.media.MediaDrmResetException} and
- * {@link android.media.MediaDrm.MediaDrmStateException} both extend
- * {@link java.lang.IllegalStateException}, they should be in an earlier catch()
+ * As {@link android.media.MediaDrmResetException} and
+ * {@link android.media.MediaDrm.MediaDrmStateException} both extend
+ * {@link java.lang.IllegalStateException}, they should be in an earlier catch()
* block than {@link java.lang.IllegalStateException} if handled separately.
* <p>
* <a name="Callbacks"></a>
@@ -165,7 +165,7 @@
/**
* Query if the given scheme identified by its UUID is supported on
- * this device, and whether the drm plugin is able to handle the
+ * this device, and whether the DRM plugin is able to handle the
* media container format specified by mimeType.
* @param uuid The UUID of the crypto scheme.
* @param mimeType The MIME type of the media container, e.g. "video/mp4"
@@ -745,7 +745,7 @@
* returned in KeyRequest.defaultUrl.
* <p>
* After the app has received the key request response from the server,
- * it should deliver to the response to the DRM engine plugin using the method
+ * it should deliver to the response to the MediaDrm instance using the method
* {@link #provideKeyResponse}.
*
* @param scope may be a sessionId or a keySetId, depending on the specified keyType.
@@ -781,7 +781,7 @@
/**
* A key response is received from the license server by the app, then it is
- * provided to the DRM engine plugin using provideKeyResponse. When the
+ * provided to the MediaDrm instance using provideKeyResponse. When the
* response is for an offline key request, a keySetId is returned that can be
* used to later restore the keys to a new session with the method
* {@link #restoreKeys}.
@@ -829,7 +829,7 @@
* in the form of {name, value} pairs. Since DRM license policies vary by vendor,
* the specific status field names are determined by each DRM vendor. Refer to your
* DRM provider documentation for definitions of the field names for a particular
- * DRM engine plugin.
+ * DRM plugin.
*
* @param sessionId the session ID for the DRM session
*/
@@ -897,11 +897,11 @@
@NonNull String certAuthority);
/**
- * After a provision response is received by the app, it is provided to the DRM
- * engine plugin using this method.
+ * After a provision response is received by the app, it is provided to the
+ * MediaDrm instance using this method.
*
* @param response the opaque provisioning response byte array to provide to the
- * DRM engine plugin.
+ * MediaDrm instance.
*
* @throws DeniedByServerException if the response indicates that the
* server rejected the request
@@ -912,7 +912,6 @@
}
@NonNull
- /* could there be a valid response with 0-sized certificate or key? */
private native Certificate provideProvisionResponseNative(@NonNull byte[] response)
throws DeniedByServerException;
@@ -953,26 +952,26 @@
/**
* Remove all secure stops without requiring interaction with the server.
*/
- public native void releaseAllSecureStops();
+ public native void releaseAllSecureStops();
/**
- * String property name: identifies the maker of the DRM engine plugin
+ * String property name: identifies the maker of the DRM plugin
*/
public static final String PROPERTY_VENDOR = "vendor";
/**
- * String property name: identifies the version of the DRM engine plugin
+ * String property name: identifies the version of the DRM plugin
*/
public static final String PROPERTY_VERSION = "version";
/**
- * String property name: describes the DRM engine plugin
+ * String property name: describes the DRM plugin
*/
public static final String PROPERTY_DESCRIPTION = "description";
/**
* String property name: a comma-separated list of cipher and mac algorithms
- * supported by CryptoSession. The list may be empty if the DRM engine
+ * supported by CryptoSession. The list may be empty if the DRM
* plugin does not support CryptoSession operations.
*/
public static final String PROPERTY_ALGORITHMS = "algorithms";
@@ -988,7 +987,7 @@
public @interface StringProperty {}
/**
- * Read a DRM engine plugin String property value, given the property name string.
+ * Read a MediaDrm String property value, given the property name string.
* <p>
* Standard fields names are:
* {@link #PROPERTY_VENDOR}, {@link #PROPERTY_VERSION},
@@ -998,6 +997,13 @@
public native String getPropertyString(@NonNull @StringProperty String propertyName);
/**
+ * Set a MediaDrm String property value, given the property name string
+ * and new value for the property.
+ */
+ public native void setPropertyString(@NonNull @StringProperty String propertyName,
+ @NonNull String value);
+
+ /**
* Byte array property name: the device unique identifier is established during
* device provisioning and provides a means of uniquely identifying each device.
*/
@@ -1011,7 +1017,7 @@
public @interface ArrayProperty {}
/**
- * Read a DRM engine plugin byte array property value, given the property name string.
+ * Read a MediaDrm byte array property value, given the property name string.
* <p>
* Standard fields names are {@link #PROPERTY_DEVICE_UNIQUE_ID}
*/
@@ -1019,17 +1025,13 @@
public native byte[] getPropertyByteArray(@ArrayProperty String propertyName);
/**
- * Set a DRM engine plugin String property value.
- */
- public native void setPropertyString(
- String propertyName, @NonNull String value);
-
- /**
- * Set a DRM engine plugin byte array property value.
- */
- public native void setPropertyByteArray(
+ * Set a MediaDrm byte array property value, given the property name string
+ * and new value for the property.
+ */
+ public native void setPropertyByteArray(@NonNull @ArrayProperty
String propertyName, @NonNull byte[] value);
+
private static final native void setCipherAlgorithmNative(
@NonNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull String algorithm);
@@ -1158,7 +1160,7 @@
* The algorithm string conforms to JCA Standard Names for Mac
* Algorithms and is case insensitive. For example "HmacSHA256".
* <p>
- * The list of supported algorithms for a DRM engine plugin can be obtained
+ * The list of supported algorithms for a DRM plugin can be obtained
* using the method {@link #getPropertyString} with the property name
* "algorithms".
*/
@@ -1272,7 +1274,7 @@
* storage, and used when invoking the signRSA method.
*
* @param response the opaque certificate response byte array to provide to the
- * DRM engine plugin.
+ * MediaDrm instance.
*
* @throws DeniedByServerException if the response indicates that the
* server rejected the request
diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java
index bdc0fda..31eb948 100644
--- a/media/java/android/media/MediaMetadata.java
+++ b/media/java/android/media/MediaMetadata.java
@@ -34,6 +34,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Set;
+import java.util.Objects;
/**
* Contains metadata about an item, such as the title, artist, etc.
@@ -616,6 +617,71 @@
};
/**
+ * Compares the contents of this object to another MediaMetadata object. It
+ * does not compare Bitmaps and Ratings as the media player can choose to
+ * forgo these fields depending on how you retrieve the MediaMetadata.
+ *
+ * @param o The Metadata object to compare this object against
+ * @return Whether or not the two objects have matching fields (excluding
+ * Bitmaps and Ratings)
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+
+ if (!(o instanceof MediaMetadata)) {
+ return false;
+ }
+
+ final MediaMetadata m = (MediaMetadata) o;
+
+ for (int i = 0; i < METADATA_KEYS_TYPE.size(); i++) {
+ String key = METADATA_KEYS_TYPE.keyAt(i);
+ switch (METADATA_KEYS_TYPE.valueAt(i)) {
+ case METADATA_TYPE_TEXT:
+ if (!Objects.equals(getString(key), m.getString(key))) {
+ return false;
+ }
+ break;
+ case METADATA_TYPE_LONG:
+ if (getLong(key) != m.getLong(key)) {
+ return false;
+ }
+ break;
+ default:
+ // Ignore ratings and bitmaps when comparing
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hashCode = 17;
+
+ for (int i = 0; i < METADATA_KEYS_TYPE.size(); i++) {
+ String key = METADATA_KEYS_TYPE.keyAt(i);
+ switch (METADATA_KEYS_TYPE.valueAt(i)) {
+ case METADATA_TYPE_TEXT:
+ hashCode = 31 * hashCode + Objects.hash(getString(key));
+ break;
+ case METADATA_TYPE_LONG:
+ hashCode = 31 * hashCode + Long.hashCode(getLong(key));
+ break;
+ default:
+ // Ignore ratings and bitmaps when comparing
+ break;
+ }
+ }
+
+ return hashCode;
+ }
+
+ /**
* Use to build MediaMetadata objects. The system defined metadata keys must
* use the appropriate data type.
*/
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 4bb16ff..26fd750 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -732,6 +732,11 @@
<!-- UI debug setting: profile time taken by hardware acceleration to render apps [CHAR LIMIT=25] -->
<string name="track_frame_time">Profile GPU rendering</string>
+ <!-- UI debug setting: enable gpu debug layers [CHAR LIMIT=25] -->
+ <string name="enable_gpu_debug_layers">Enable GPU debug layers</string>
+ <!-- UI debug setting: enable gpu debug layers summary [CHAR LIMIT=50] -->
+ <string name="enable_gpu_debug_layers_summary">Allow loading GPU debug layers for debug apps</string>
+
<!-- UI debug setting: scaling factor for window animations [CHAR LIMIT=25] -->
<string name="window_animation_scale_title">Window animation scale</string>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 41b205b..ba1c9e3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -869,6 +869,15 @@
dumpSetting(s, p,
Settings.Global.WAIT_FOR_DEBUGGER,
GlobalSettingsProto.WAIT_FOR_DEBUGGER);
+ dumpSetting(s, p,
+ Settings.Global.ENABLE_GPU_DEBUG_LAYERS,
+ GlobalSettingsProto.ENABLE_GPU_DEBUG_LAYERS);
+ dumpSetting(s, p,
+ Settings.Global.GPU_DEBUG_APP,
+ GlobalSettingsProto.GPU_DEBUG_APP);
+ dumpSetting(s, p,
+ Settings.Global.GPU_DEBUG_LAYERS,
+ GlobalSettingsProto.GPU_DEBUG_LAYERS);
// Settings.Global.SHOW_PROCESSES intentionally excluded since it's deprecated.
dumpSetting(s, p,
Settings.Global.LOW_POWER_MODE,
diff --git a/packages/SystemUI/shared/Android.mk b/packages/SystemUI/shared/Android.mk
index e177d1d..5f75f7d 100644
--- a/packages/SystemUI/shared/Android.mk
+++ b/packages/SystemUI/shared/Android.mk
@@ -30,7 +30,7 @@
include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := SharedDummyLib
+LOCAL_PACKAGE_NAME := SystemUISharedLib
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_JAVA_LIBRARIES := SystemUISharedLib
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index d82b010..cc4bc58 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -16,8 +16,8 @@
package com.android.systemui.shared.recents;
-import android.graphics.Bitmap;
import android.graphics.Rect;
+import com.android.systemui.shared.system.GraphicBufferCompat;
/**
* Temporary callbacks into SystemUI.
@@ -25,9 +25,8 @@
interface ISystemUiProxy {
/**
- * Proxies SurfaceControl.screenshot().
+ * Proxies SurfaceControl.screenshotToBuffer().
*/
- Bitmap screenshot(in Rect sourceCrop, int width, int height,
- int minLayer, int maxLayer, boolean useIdentityTransform,
- int rotation);
+ GraphicBufferCompat screenshot(in Rect sourceCrop, int width, int height, int minLayer,
+ int maxLayer, boolean useIdentityTransform, int rotation);
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoadPlan.java
index f92509d..4834bb1 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoadPlan.java
@@ -45,6 +45,11 @@
*/
public class RecentsTaskLoadPlan {
+ /** The set of conditions to preload tasks. */
+ public static class PreloadOptions {
+ public boolean loadTitles = true;
+ }
+
/** The set of conditions to load tasks. */
public static class Options {
public int runningTaskId = -1;
@@ -80,7 +85,8 @@
* Note: Do not lock, since this can be calling back to the loader, which separately also drives
* this call (callers should synchronize on the loader before making this call).
*/
- public void preloadPlan(RecentsTaskLoader loader, int runningTaskId, int currentUserId) {
+ public void preloadPlan(PreloadOptions opts, RecentsTaskLoader loader, int runningTaskId,
+ int currentUserId) {
Resources res = mContext.getResources();
ArrayList<Task> allTasks = new ArrayList<>();
if (mRawTasks == null) {
@@ -110,9 +116,12 @@
}
// Load the title, icon, and color
- String title = loader.getAndUpdateActivityTitle(taskKey, t.taskDescription);
- String titleDescription = loader.getAndUpdateContentDescription(taskKey,
- t.taskDescription);
+ String title = opts.loadTitles
+ ? loader.getAndUpdateActivityTitle(taskKey, t.taskDescription)
+ : "";
+ String titleDescription = opts.loadTitles
+ ? loader.getAndUpdateContentDescription(taskKey, t.taskDescription)
+ : "";
Drawable icon = isStackTask
? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false)
: null;
@@ -153,7 +162,7 @@
Resources res = mContext.getResources();
// Iterate through each of the tasks and load them according to the load conditions.
- ArrayList<Task> tasks = mStack.getStackTasks();
+ ArrayList<Task> tasks = mStack.getTasks();
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
Task task = tasks.get(i);
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java
index 9a991cf..0f68026 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java
@@ -32,6 +32,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan.Options;
+import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan.PreloadOptions;
import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.model.TaskKeyLruCache.EvictionCallback;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -155,7 +156,7 @@
int currentUserId) {
try {
Trace.beginSection("preloadPlan");
- plan.preloadPlan(this, runningTaskId, currentUserId);
+ plan.preloadPlan(new PreloadOptions(), this, runningTaskId, currentUserId);
} finally {
Trace.endSection();
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java
index 693379d..a369397 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java
@@ -19,7 +19,6 @@
import android.content.ComponentName;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.SparseArray;
import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.utilities.AnimationProps;
@@ -92,7 +91,7 @@
boolean dismissRecentsIfAllRemoved) {
if (mStackTaskList.contains(t)) {
mStackTaskList.remove(t);
- Task newFrontMostTask = getStackFrontMostTask();
+ Task newFrontMostTask = getFrontMostTask();
if (mCb != null) {
// Notify that a task has been removed
mCb.onStackTaskRemoved(this, t, newFrontMostTask, animation,
@@ -183,7 +182,7 @@
// Only callback for the removed tasks after the stack has updated
int removedTaskCount = removedTasks.size();
- Task newFrontMostTask = getStackFrontMostTask();
+ Task newFrontMostTask = getFrontMostTask();
for (int i = 0; i < removedTaskCount; i++) {
mCb.onStackTaskRemoved(this, removedTasks.get(i), newFrontMostTask,
AnimationProps.IMMEDIATE, false /* fromDockGesture */,
@@ -205,7 +204,7 @@
/**
* Gets the front-most task in the stack.
*/
- public Task getStackFrontMostTask() {
+ public Task getFrontMostTask() {
ArrayList<Task> stackTasks = mStackTaskList.getTasks();
if (stackTasks.isEmpty()) {
return null;
@@ -228,7 +227,7 @@
/**
* Returns the set of "active" (non-historical) tasks in the stack that have been used recently.
*/
- public ArrayList<Task> getStackTasks() {
+ public ArrayList<Task> getTasks() {
return mStackTaskList.getTasks();
}
@@ -242,16 +241,9 @@
}
/**
- * Returns the number of stacktasks.
- */
- public int getTaskCount() {
- return mStackTaskList.size();
- }
-
- /**
* Returns the number of stack tasks.
*/
- public int getStackTaskCount() {
+ public int getTaskCount() {
return mStackTaskList.size();
}
@@ -298,7 +290,7 @@
if (nextLaunchTarget != null) {
return nextLaunchTarget;
}
- return getStackTasks().get(getTaskCount() - 1);
+ return getTasks().get(getTaskCount() - 1);
}
private Task getNextLaunchTargetRaw() {
@@ -306,15 +298,15 @@
if (taskCount == 0) {
return null;
}
- int launchTaskIndex = indexOfStackTask(getLaunchTarget());
+ int launchTaskIndex = indexOfTask(getLaunchTarget());
if (launchTaskIndex != -1 && launchTaskIndex > 0) {
- return getStackTasks().get(launchTaskIndex - 1);
+ return getTasks().get(launchTaskIndex - 1);
}
return null;
}
/** Returns the index of this task in this current task stack */
- public int indexOfStackTask(Task t) {
+ public int indexOfTask(Task t) {
return mStackTaskList.indexOf(t);
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/AppTrace.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/AppTrace.java
new file mode 100644
index 0000000..0241c59
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/AppTrace.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.shared.recents.utilities;
+
+import static android.os.Trace.TRACE_TAG_APP;
+
+/**
+ * Helper class for internal trace functions.
+ */
+public class AppTrace {
+
+ /**
+ * Begins a new async trace section with the given {@param key} and {@param cookie}.
+ */
+ public static void start(String key, int cookie) {
+ android.os.Trace.asyncTraceBegin(TRACE_TAG_APP, key, cookie);
+ }
+
+ /**
+ * Begins a new async trace section with the given {@param key}.
+ */
+ public static void start(String key) {
+ android.os.Trace.asyncTraceBegin(TRACE_TAG_APP, key, 0);
+ }
+
+ /**
+ * Ends an existing async trace section with the given {@param key}.
+ */
+ public static void end(String key) {
+ android.os.Trace.asyncTraceEnd(TRACE_TAG_APP, key, 0);
+ }
+
+ /**
+ * Ends an existing async trace section with the given {@param key} and {@param cookie}.
+ */
+ public static void end(String key, int cookie) {
+ android.os.Trace.asyncTraceEnd(TRACE_TAG_APP, key, cookie);
+ }
+
+ /**
+ * Begins a new trace section with the given {@param key}. Can be nested.
+ */
+ public static void beginSection(String key) {
+ android.os.Trace.beginSection(key);
+ }
+
+ /**
+ * Ends an existing trace section started in the last {@link #beginSection(String)}.
+ */
+ public static void endSection() {
+ android.os.Trace.endSection();
+ }
+
+ /**
+ * Traces a counter value.
+ */
+ public static void count(String name, int count) {
+ android.os.Trace.traceCounter(TRACE_TAG_APP, name, count);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AnimateableViewBounds.java
similarity index 86%
rename from packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
rename to packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AnimateableViewBounds.java
index b598ec6..45728c4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AnimateableViewBounds.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.recents.views;
+package com.android.systemui.shared.recents.view;
import android.graphics.Outline;
import android.graphics.Rect;
@@ -24,22 +24,19 @@
import com.android.systemui.shared.recents.utilities.Utilities;
-/* An outline provider that has a clip and outline that can be animated. */
+/**
+ * An outline provider that has a clip and outline that can be animated.
+ */
public class AnimateableViewBounds extends ViewOutlineProvider {
private static final float MIN_ALPHA = 0.1f;
private static final float MAX_ALPHA = 0.8f;
protected View mSourceView;
- @ViewDebug.ExportedProperty(category="recents")
protected Rect mClipRect = new Rect();
- @ViewDebug.ExportedProperty(category="recents")
protected Rect mClipBounds = new Rect();
- @ViewDebug.ExportedProperty(category="recents")
protected Rect mLastClipBounds = new Rect();
- @ViewDebug.ExportedProperty(category="recents")
protected int mCornerRadius;
- @ViewDebug.ExportedProperty(category="recents")
protected float mAlpha = 1f;
public AnimateableViewBounds(View source, int cornerRadius) {
@@ -73,7 +70,7 @@
/**
* Sets the view outline alpha.
*/
- void setAlpha(float alpha) {
+ public void setAlpha(float alpha) {
if (Float.compare(alpha, mAlpha) != 0) {
mAlpha = alpha;
// TODO, If both clip and alpha change in the same frame, only invalidate once
@@ -88,28 +85,43 @@
return mAlpha;
}
- /** Sets the top clip. */
+ /**
+ * Sets the top clip.
+ */
public void setClipTop(int top) {
mClipRect.top = top;
updateClipBounds();
}
- /** Returns the top clip. */
+ /**
+ * @return the top clip.
+ */
public int getClipTop() {
return mClipRect.top;
}
- /** Sets the bottom clip. */
+ /**
+ * Sets the bottom clip.
+ */
public void setClipBottom(int bottom) {
mClipRect.bottom = bottom;
updateClipBounds();
}
- /** Returns the bottom clip. */
+ /**
+ * @return the bottom clip.
+ */
public int getClipBottom() {
return mClipRect.bottom;
}
+ /**
+ * @return the clip bounds.
+ */
+ public Rect getClipBounds() {
+ return mClipBounds;
+ }
+
protected void updateClipBounds() {
mClipBounds.set(Math.max(0, mClipRect.left), Math.max(0, mClipRect.top),
mSourceView.getWidth() - Math.max(0, mClipRect.right),
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AppTransitionAnimationSpecCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AppTransitionAnimationSpecCompat.java
new file mode 100644
index 0000000..ebdc884
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AppTransitionAnimationSpecCompat.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.shared.recents.view;
+
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.view.AppTransitionAnimationSpec;
+
+/**
+ * Wraps the internal app transition animation spec.
+ */
+public class AppTransitionAnimationSpecCompat {
+
+ private int mTaskId;
+ private Bitmap mBuffer;
+ private Rect mRect;
+
+ public AppTransitionAnimationSpecCompat(int taskId, Bitmap buffer, Rect rect) {
+ mTaskId = taskId;
+ mBuffer = buffer;
+ mRect = rect;
+ }
+
+ public AppTransitionAnimationSpec toAppTransitionAnimationSpec() {
+ return new AppTransitionAnimationSpec(mTaskId,
+ mBuffer != null ? mBuffer.createGraphicBufferHandle() : null, mRect);
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AppTransitionAnimationSpecsFuture.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AppTransitionAnimationSpecsFuture.java
index 7a24071..85d362a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AppTransitionAnimationSpecsFuture.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AppTransitionAnimationSpecsFuture.java
@@ -32,10 +32,10 @@
public abstract class AppTransitionAnimationSpecsFuture {
private final Handler mHandler;
- private FutureTask<List<AppTransitionAnimationSpec>> mComposeTask = new FutureTask<>(
- new Callable<List<AppTransitionAnimationSpec>>() {
+ private FutureTask<List<AppTransitionAnimationSpecCompat>> mComposeTask = new FutureTask<>(
+ new Callable<List<AppTransitionAnimationSpecCompat>>() {
@Override
- public List<AppTransitionAnimationSpec> call() throws Exception {
+ public List<AppTransitionAnimationSpecCompat> call() throws Exception {
return composeSpecs();
}
});
@@ -48,13 +48,15 @@
if (!mComposeTask.isDone()) {
mHandler.post(mComposeTask);
}
- List<AppTransitionAnimationSpec> specs = mComposeTask.get();
+ List<AppTransitionAnimationSpecCompat> specs = mComposeTask.get();
if (specs == null) {
return null;
}
AppTransitionAnimationSpec[] arr = new AppTransitionAnimationSpec[specs.size()];
- specs.toArray(arr);
+ for (int i = 0; i < specs.size(); i++) {
+ arr[i] = specs.get(i).toAppTransitionAnimationSpec();
+ }
return arr;
} catch (Exception e) {
return null;
@@ -83,5 +85,5 @@
mComposeTask.run();
}
- public abstract List<AppTransitionAnimationSpec> composeSpecs();
+ public abstract List<AppTransitionAnimationSpecCompat> composeSpecs();
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/RecentsTransition.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/RecentsTransition.java
index f8f86f0..ab89043 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/RecentsTransition.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/RecentsTransition.java
@@ -42,7 +42,7 @@
*/
public static ActivityOptions createAspectScaleAnimation(Context context, Handler handler,
boolean scaleUp, AppTransitionAnimationSpecsFuture animationSpecsFuture,
- final OnAnimationStartedListener animationStartCallback) {
+ final Runnable animationStartCallback) {
final OnAnimationStartedListener animStartedListener = new OnAnimationStartedListener() {
private boolean mHandled;
@@ -56,7 +56,7 @@
mHandled = true;
if (animationStartCallback != null) {
- animationStartCallback.onAnimationStarted();
+ animationStartCallback.run();
}
}
};
@@ -71,19 +71,14 @@
* Wraps a animation-start callback in a binder that can be called from window manager.
*/
public static IRemoteCallback wrapStartedListener(final Handler handler,
- final OnAnimationStartedListener listener) {
- if (listener == null) {
+ final Runnable animationStartCallback) {
+ if (animationStartCallback == null) {
return null;
}
return new IRemoteCallback.Stub() {
@Override
public void sendResult(Bundle data) throws RemoteException {
- handler.post(new Runnable() {
- @Override
- public void run() {
- listener.onAnimationStarted();
- }
- });
+ handler.post(animationStartCallback);
}
};
}
@@ -92,9 +87,9 @@
* @return a {@link GraphicBuffer} with the {@param view} drawn into it. Result can be null if
* we were unable to allocate a hardware bitmap.
*/
- public static GraphicBuffer drawViewIntoGraphicBuffer(int width, int height, final View view,
+ public static Bitmap drawViewIntoHardwareBitmap(int width, int height, final View view,
final float scale, final int eraseColor) {
- final Bitmap hwBitmap = createHardwareBitmap(width, height, new Consumer<Canvas>() {
+ return createHardwareBitmap(width, height, new Consumer<Canvas>() {
@Override
public void accept(Canvas c) {
c.scale(scale, scale);
@@ -106,7 +101,6 @@
}
}
});
- return hwBitmap != null ? hwBitmap.createGraphicBufferHandle() : null;
}
/**
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index db1583a..f6fab86 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -29,6 +29,7 @@
import android.app.ActivityManager.RecentTaskInfo;
import android.app.ActivityOptions;
import android.app.AppGlobals;
+import android.app.IAssistDataReceiver;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -39,7 +40,9 @@
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.IconDrawableFactory;
@@ -62,12 +65,14 @@
private final PackageManager mPackageManager;
private final IconDrawableFactory mDrawableFactory;
private final BackgroundExecutor mBackgroundExecutor;
+ private final TaskStackChangeListeners mTaskStackChangeListeners;
private ActivityManagerWrapper() {
final Context context = AppGlobals.getInitialApplication();
mPackageManager = context.getPackageManager();
mDrawableFactory = IconDrawableFactory.newInstance(context);
mBackgroundExecutor = BackgroundExecutor.get();
+ mTaskStackChangeListeners = new TaskStackChangeListeners(Looper.getMainLooper());
}
public static ActivityManagerWrapper getInstance() {
@@ -232,13 +237,54 @@
}
/**
+ * Starts the recents activity. The caller should manage the thread on which this is called.
+ */
+ public void startRecentsActivity(AssistDataReceiverCompat assistDataReceiver, Bundle options,
+ ActivityOptions opts, int userId, Consumer<Boolean> resultCallback,
+ Handler resultCallbackHandler) {
+ Bundle activityOptions = opts != null ? opts.toBundle() : null;
+ try {
+ IAssistDataReceiver receiver = null;
+ if (assistDataReceiver != null) {
+ receiver = new IAssistDataReceiver.Stub() {
+ public void onHandleAssistData(Bundle resultData) {
+ assistDataReceiver.onHandleAssistData(resultData);
+ }
+ public void onHandleAssistScreenshot(Bitmap screenshot) {
+ assistDataReceiver.onHandleAssistScreenshot(screenshot);
+ }
+ };
+ }
+ ActivityManager.getService().startRecentsActivity(receiver, options, activityOptions,
+ userId);
+ if (resultCallback != null) {
+ resultCallbackHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ resultCallback.accept(true);
+ }
+ });
+ }
+ } catch (Exception e) {
+ if (resultCallback != null) {
+ resultCallbackHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ resultCallback.accept(false);
+ }
+ });
+ }
+ }
+ }
+
+ /**
* Starts a task from Recents.
*
- * @see {@link #startActivityFromRecents(TaskKey, ActivityOptions, int, int, Consumer, Handler)}
+ * @see {@link #startActivityFromRecentsAsync(TaskKey, ActivityOptions, int, int, Consumer, Handler)}
*/
- public void startActivityFromRecents(Task.TaskKey taskKey, ActivityOptions options,
+ public void startActivityFromRecentsAsync(Task.TaskKey taskKey, ActivityOptions options,
Consumer<Boolean> resultCallback, Handler resultCallbackHandler) {
- startActivityFromRecents(taskKey, options, WINDOWING_MODE_UNDEFINED,
+ startActivityFromRecentsAsync(taskKey, options, WINDOWING_MODE_UNDEFINED,
ACTIVITY_TYPE_UNDEFINED, resultCallback, resultCallbackHandler);
}
@@ -248,7 +294,7 @@
* @param resultCallback The result success callback
* @param resultCallbackHandler The handler to receive the result callback
*/
- public void startActivityFromRecents(Task.TaskKey taskKey, ActivityOptions options,
+ public void startActivityFromRecentsAsync(Task.TaskKey taskKey, ActivityOptions options,
int windowingMode, int activityType, Consumer<Boolean> resultCallback,
Handler resultCallbackHandler) {
if (taskKey.windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
@@ -270,30 +316,66 @@
// Execute this from another thread such that we can do other things (like caching the
// bitmap for the thumbnail) while AM is busy starting our activity.
- mBackgroundExecutor.submit(() -> {
- try {
- ActivityManager.getService().startActivityFromRecents(taskKey.id,
- finalOptions == null ? null : finalOptions.toBundle());
- if (resultCallback != null) {
- resultCallbackHandler.post(() -> resultCallback.accept(true));
- }
- } catch (Exception e) {
- if (resultCallback != null) {
- resultCallbackHandler.post(() -> resultCallback.accept(false));
+ mBackgroundExecutor.submit(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ActivityManager.getService().startActivityFromRecents(taskKey.id,
+ finalOptions == null ? null : finalOptions.toBundle());
+ if (resultCallback != null) {
+ resultCallbackHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ resultCallback.accept(true);
+ }
+ });
+ }
+ } catch (Exception e) {
+ if (resultCallback != null) {
+ resultCallbackHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ resultCallback.accept(false);
+ }
+ });
+ }
}
}
});
}
/**
+ * Registers a task stack listener with the system.
+ * This should be called on the main thread.
+ */
+ public void registerTaskStackListener(TaskStackChangeListener listener) {
+ synchronized (mTaskStackChangeListeners) {
+ mTaskStackChangeListeners.addListener(ActivityManager.getService(), listener);
+ }
+ }
+
+ /**
+ * Unregisters a task stack listener with the system.
+ * This should be called on the main thread.
+ */
+ public void unregisterTaskStackListener(TaskStackChangeListener listener) {
+ synchronized (mTaskStackChangeListeners) {
+ mTaskStackChangeListeners.removeListener(listener);
+ }
+ }
+
+ /**
* Requests that the system close any open system windows (including other SystemUI).
*/
public void closeSystemWindows(String reason) {
- mBackgroundExecutor.submit(() -> {
- try {
- ActivityManager.getService().closeSystemDialogs(reason);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to close system windows", e);
+ mBackgroundExecutor.submit(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ActivityManager.getService().closeSystemDialogs(reason);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to close system windows", e);
+ }
}
});
}
@@ -302,11 +384,14 @@
* Removes a task by id.
*/
public void removeTask(int taskId) {
- mBackgroundExecutor.submit(() -> {
- try {
- ActivityManager.getService().removeTask(taskId);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to remove task=" + taskId, e);
+ mBackgroundExecutor.submit(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ActivityManager.getService().removeTask(taskId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to remove task=" + taskId, e);
+ }
}
});
}
diff --git a/core/java/com/android/internal/app/IAssistDataReceiver.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/system/AssistDataReceiverCompat.java
similarity index 66%
copy from core/java/com/android/internal/app/IAssistDataReceiver.aidl
copy to packages/SystemUI/shared/src/com/android/systemui/shared/system/AssistDataReceiverCompat.java
index 9c9ffef..cd943f6 100644
--- a/core/java/com/android/internal/app/IAssistDataReceiver.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/AssistDataReceiverCompat.java
@@ -11,16 +11,18 @@
* 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.
+ * limitations under the License
*/
-package com.android.internal.app;
+package com.android.systemui.shared.system;
import android.graphics.Bitmap;
import android.os.Bundle;
-/** @hide */
-oneway interface IAssistDataReceiver {
- void onHandleAssistData(in Bundle resultData);
- void onHandleAssistScreenshot(in Bitmap screenshot);
+/**
+ * Abstract class for assist data receivers.
+ */
+public abstract class AssistDataReceiverCompat {
+ public abstract void onHandleAssistData(Bundle resultData);
+ public abstract void onHandleAssistScreenshot(Bitmap screenshot);
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/BackgroundExecutor.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/BackgroundExecutor.java
index 26e1813..0bd89a7 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/BackgroundExecutor.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/BackgroundExecutor.java
@@ -16,6 +16,7 @@
package com.android.systemui.shared.system;
+import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@@ -37,9 +38,24 @@
}
/**
+ * Runs the given {@param callable} on one of the background executor threads.
+ */
+ public <T> Future<T> submit(Callable<T> callable) {
+ return mExecutorService.submit(callable);
+ }
+
+ /**
* Runs the given {@param runnable} on one of the background executor threads.
*/
public Future<?> submit(Runnable runnable) {
return mExecutorService.submit(runnable);
}
+
+ /**
+ * Runs the given {@param runnable} on one of the background executor threads. Return
+ * {@param result} when the future is resolved.
+ */
+ public <T> Future<T> submit(Runnable runnable, T result) {
+ return mExecutorService.submit(runnable, result);
+ }
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ChoreographerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ChoreographerCompat.java
new file mode 100644
index 0000000..4d422bb
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ChoreographerCompat.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.shared.system;
+
+import static android.view.Choreographer.CALLBACK_INPUT;
+
+import android.view.Choreographer;
+
+/**
+ * Wraps the internal choreographer.
+ */
+public class ChoreographerCompat {
+
+ /**
+ * Posts an input callback to the choreographer.
+ */
+ public static void postInputFrame(Choreographer choreographer, Runnable runnable) {
+ choreographer.postCallback(CALLBACK_INPUT, runnable, null);
+ }
+}
diff --git a/core/java/com/android/internal/app/IAssistDataReceiver.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/system/GraphicBufferCompat.aidl
similarity index 70%
copy from core/java/com/android/internal/app/IAssistDataReceiver.aidl
copy to packages/SystemUI/shared/src/com/android/systemui/shared/system/GraphicBufferCompat.aidl
index 9c9ffef..f9450ad 100644
--- a/core/java/com/android/internal/app/IAssistDataReceiver.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/GraphicBufferCompat.aidl
@@ -14,13 +14,6 @@
* limitations under the License.
*/
-package com.android.internal.app;
+package com.android.systemui.shared.system;
-import android.graphics.Bitmap;
-import android.os.Bundle;
-
-/** @hide */
-oneway interface IAssistDataReceiver {
- void onHandleAssistData(in Bundle resultData);
- void onHandleAssistScreenshot(in Bitmap screenshot);
-}
+parcelable GraphicBufferCompat;
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/GraphicBufferCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/GraphicBufferCompat.java
new file mode 100644
index 0000000..66b8fed
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/GraphicBufferCompat.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.shared.system;
+
+import android.graphics.Bitmap;
+import android.graphics.GraphicBuffer;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Wraps the internal graphic buffer.
+ */
+public class GraphicBufferCompat implements Parcelable {
+
+ private GraphicBuffer mBuffer;
+
+ public GraphicBufferCompat(GraphicBuffer buffer) {
+ mBuffer = buffer;
+ }
+
+ public GraphicBufferCompat(Parcel in) {
+ mBuffer = GraphicBuffer.CREATOR.createFromParcel(in);
+ }
+
+ public Bitmap toBitmap() {
+ return mBuffer != null
+ ? Bitmap.createHardwareBitmap(mBuffer)
+ : null;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ mBuffer.writeToParcel(dest, flags);
+ }
+
+ public static final Parcelable.Creator<GraphicBufferCompat> CREATOR
+ = new Parcelable.Creator<GraphicBufferCompat>() {
+ public GraphicBufferCompat createFromParcel(Parcel in) {
+ return new GraphicBufferCompat(in);
+ }
+
+ public GraphicBufferCompat[] newArray(int size) {
+ return new GraphicBufferCompat[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
index 36310f1..17cb0d8 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
@@ -20,6 +20,8 @@
import android.os.UserHandle;
import android.util.Log;
+import com.android.systemui.shared.recents.model.ThumbnailData;
+
/**
* An interface to track task stack changes. Classes should implement this instead of
* {@link android.app.ITaskStackListener} to reduce IPC calls from system services.
@@ -31,7 +33,7 @@
// Main thread callbacks
public void onTaskStackChanged() { }
- public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
+ public void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) { }
public void onActivityPinned(String packageName, int userId, int taskId, int stackId) { }
public void onActivityUnpinned() { }
public void onPinnedActivityRestartAttempt(boolean clearedTask) { }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 95fc96f..81c37a9 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -26,6 +26,8 @@
import android.os.Trace;
import android.util.Log;
+import com.android.systemui.shared.recents.model.ThumbnailData;
+
import java.util.ArrayList;
import java.util.List;
@@ -43,6 +45,7 @@
private final List<TaskStackChangeListener> mTmpListeners = new ArrayList<>();
private final Handler mHandler;
+ private boolean mRegistered;
public TaskStackChangeListeners(Looper looper) {
mHandler = new H(looper);
@@ -50,16 +53,21 @@
public void addListener(IActivityManager am, TaskStackChangeListener listener) {
mTaskStackListeners.add(listener);
- if (mTaskStackListeners.size() == 1) {
+ if (!mRegistered) {
// Register mTaskStackListener to IActivityManager only once if needed.
try {
am.registerTaskStackListener(this);
+ mRegistered = true;
} catch (Exception e) {
Log.w(TAG, "Failed to call registerTaskStackListener", e);
}
}
}
+ public void removeListener(TaskStackChangeListener listener) {
+ mTaskStackListeners.remove(listener);
+ }
+
@Override
public void onTaskStackChanged() throws RemoteException {
// Call the task changed callback for the non-ui thread listeners first
@@ -170,7 +178,7 @@
Trace.beginSection("onTaskSnapshotChanged");
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1,
- (TaskSnapshot) msg.obj);
+ new ThumbnailData((TaskSnapshot) msg.obj));
}
Trace.endSection();
break;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
new file mode 100644
index 0000000..1477558
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.system;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import android.graphics.Rect;
+import android.view.WindowManagerGlobal;
+
+public class WindowManagerWrapper {
+
+ private static final String TAG = "WindowManagerWrapper";
+
+ private static final WindowManagerWrapper sInstance = new WindowManagerWrapper();
+
+ public static WindowManagerWrapper getInstance() {
+ return sInstance;
+ }
+
+ /**
+ * @return the stable insets for the primary display.
+ */
+ public void getStableInsets(Rect outStableInsets) {
+ try {
+ WindowManagerGlobal.getWindowManagerService().getStableInsets(DEFAULT_DISPLAY,
+ outStableInsets);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 623fe53..41b007a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -78,6 +78,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.google.android.collect.Lists;
@@ -1187,7 +1188,7 @@
mFpm.addLockoutResetCallback(mLockoutResetCallback);
}
- SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener);
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
mUserManager = context.getSystemService(UserManager.class);
}
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index 2e4a5a4..22922e7 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -22,11 +22,8 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
-import android.graphics.Bitmap;
import android.graphics.Rect;
-import android.net.Uri;
import android.os.Binder;
-import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -36,12 +33,14 @@
import android.util.Log;
import android.view.SurfaceControl;
+import com.android.systemui.OverviewProxyService.OverviewProxyListener;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
-import com.android.systemui.OverviewProxyService.OverviewProxyListener;
+import com.android.systemui.shared.system.GraphicBufferCompat;
import com.android.systemui.statusbar.policy.CallbackController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -67,12 +66,12 @@
private int mConnectionBackoffAttempts;
private ISystemUiProxy mSysUiProxy = new ISystemUiProxy.Stub() {
- public Bitmap screenshot(Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
- boolean useIdentityTransform, int rotation) {
+ public GraphicBufferCompat screenshot(Rect sourceCrop, int width, int height, int minLayer,
+ int maxLayer, boolean useIdentityTransform, int rotation) {
long token = Binder.clearCallingIdentity();
try {
- return SurfaceControl.screenshot(sourceCrop, width, height, minLayer, maxLayer,
- useIdentityTransform, rotation);
+ return new GraphicBufferCompat(SurfaceControl.screenshotToBuffer(sourceCrop, width,
+ height, minLayer, maxLayer, useIdentityTransform, rotation));
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
index 4119ec0..b9e9e0a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
@@ -31,6 +31,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
public class WorkLockActivityController {
private static final String TAG = WorkLockActivityController.class.getSimpleName();
@@ -39,15 +40,15 @@
private final IActivityManager mIam;
public WorkLockActivityController(Context context) {
- this(context, SystemServicesProxy.getInstance(context), ActivityManager.getService());
+ this(context, ActivityManagerWrapper.getInstance(), ActivityManager.getService());
}
@VisibleForTesting
- WorkLockActivityController(Context context, SystemServicesProxy ssp, IActivityManager am) {
+ WorkLockActivityController(Context context, ActivityManagerWrapper am, IActivityManager iAm) {
mContext = context;
- mIam = am;
+ mIam = iAm;
- ssp.registerTaskStackListener(mLockListener);
+ am.registerTaskStackListener(mLockListener);
}
private void startWorkChallengeInTask(int taskId, int userId) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 7ef0f15..2963506 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -174,7 +174,7 @@
} catch (RemoteException e) {
Log.e(TAG, "Failed to register pinned stack listener", e);
}
- SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener);
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
mInputConsumerController = new InputConsumerController(mWindowManager);
mMediaController = new PipMediaController(context, mActivityManager);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 5a91def..eef43d2 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -47,6 +47,7 @@
import com.android.systemui.pip.BasePipManager;
import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -234,7 +235,7 @@
mActivityManager = ActivityManager.getService();
mWindowManager = WindowManagerGlobal.getWindowManagerService();
- SystemServicesProxy.getInstance(context).registerTaskStackListener(mTaskStackListener);
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_MEDIA_RESOURCE_GRANTED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index c666d57..9aecc68 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -17,7 +17,6 @@
package com.android.systemui.recents;
import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_HOME_KEY;
-import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS;
import android.app.Activity;
import android.app.ActivityOptions;
@@ -96,7 +95,6 @@
import com.android.systemui.recents.views.RecentsView;
import com.android.systemui.recents.views.SystemBarScrimViews;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.statusbar.phone.StatusBar;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -471,7 +469,7 @@
if (launchState.launchedFromApp) {
Task launchTarget = stack.getLaunchTarget();
int launchTaskIndexInStack = launchTarget != null
- ? stack.indexOfStackTask(launchTarget)
+ ? stack.indexOfTask(launchTarget)
: 0;
MetricsLogger.count(this, "overview_source_app", 1);
// If from an app, track the stack index of the app in the stack (for affiliated tasks)
@@ -517,7 +515,7 @@
// Notify of the config change
Configuration newDeviceConfiguration = Utilities.getAppConfiguration(this);
- int numStackTasks = mRecentsView.getStack().getStackTaskCount();
+ int numStackTasks = mRecentsView.getStack().getTaskCount();
EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */,
mLastConfig.orientation != newDeviceConfiguration.orientation,
mLastConfig.densityDpi != newDeviceConfiguration.densityDpi, numStackTasks > 0));
@@ -826,7 +824,7 @@
loader.loadTasks(loadPlan, loadOpts);
TaskStack stack = loadPlan.getTaskStack();
- int numStackTasks = stack.getStackTaskCount();
+ int numStackTasks = stack.getTaskCount();
boolean showDeferredAnimation = numStackTasks > 0;
if (sendConfigChangedEvent) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
index d2326ce..14fda95 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
@@ -50,24 +50,4 @@
launchedViaDragGesture = false;
launchedViaDockGesture = false;
}
-
- /**
- * Returns the task to focus given the current launch state.
- */
- public int getInitialFocusTaskIndex(int numTasks, boolean useGridLayout) {
- RecentsDebugFlags debugFlags = Recents.getDebugFlags();
- RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- if (launchedFromApp) {
- if (useGridLayout) {
- // If coming from another app to the grid layout, focus the front most task
- return numTasks - 1;
- }
-
- // If coming from another app, focus the next task
- return Math.max(0, numTasks - 2);
- } else {
- // If coming from home, focus the front most task
- return numTasks - 1;
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index d2dfbbf..3b1b2f9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -25,11 +25,11 @@
import android.app.ActivityManager;
import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityOptions;
-import android.app.ActivityOptions.OnAnimationStartedListener;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -40,7 +40,6 @@
import android.util.Log;
import android.util.MutableBoolean;
import android.util.Pair;
-import android.view.AppTransitionAnimationSpec;
import android.view.LayoutInflater;
import android.view.ViewConfiguration;
import android.view.WindowManager;
@@ -85,6 +84,7 @@
import com.android.systemui.recents.views.TaskViewHeader;
import com.android.systemui.recents.views.TaskViewTransform;
import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
+import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
import com.android.systemui.shared.recents.view.RecentsTransition;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -159,7 +159,7 @@
mBackgroundLayoutAlgorithm.update(plan.getTaskStack(), EMPTY_SET, launchState);
VisibilityReport visibilityReport =
mBackgroundLayoutAlgorithm.computeStackVisibilityReport(
- stack.getStackTasks());
+ stack.getTasks());
launchOpts.runningTaskId = runningTaskInfo != null ? runningTaskInfo.id : -1;
launchOpts.numVisibleTasks = visibilityReport.numVisibleTasks;
@@ -200,14 +200,13 @@
}
@Override
- public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) {
+ public void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) {
// Check this is for the right user
if (!checkCurrentUserId(mContext, false /* debug */)) {
return;
}
- EventBus.getDefault().send(new TaskSnapshotChangedEvent(taskId,
- new ThumbnailData(snapshot)));
+ EventBus.getDefault().send(new TaskSnapshotChangedEvent(taskId, snapshot));
}
}
@@ -221,13 +220,12 @@
// recents. In this case, we defer the toggle state until then and apply it immediately after.
private static boolean mToggleFollowingTransitionStart = true;
- private ActivityOptions.OnAnimationStartedListener mResetToggleFlagListener =
- new OnAnimationStartedListener() {
- @Override
- public void onAnimationStarted() {
- setWaitingForTransitionStart(false);
- }
- };
+ private Runnable mResetToggleFlagListener = new Runnable() {
+ @Override
+ public void run() {
+ setWaitingForTransitionStart(false);
+ }
+ };
protected Context mContext;
protected Handler mHandler;
@@ -270,8 +268,7 @@
// Register the task stack listener
mTaskStackListener = new TaskStackListenerImpl();
- SystemServicesProxy ssp = Recents.getSystemServices();
- ssp.registerTaskStackListener(mTaskStackListener);
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
// Initialize the static configuration resources
mDummyStackView = new TaskStackView(mContext);
@@ -535,7 +532,7 @@
boolean isRunningTaskInHomeStack =
runningTask.configuration.windowConfiguration.getActivityType()
== ACTIVITY_TYPE_HOME;
- ArrayList<Task> tasks = focusedStack.getStackTasks();
+ ArrayList<Task> tasks = focusedStack.getTasks();
Task toTask = null;
ActivityOptions launchOpts = null;
int taskCount = tasks.size();
@@ -565,7 +562,7 @@
}
// Launch the task
- ActivityManagerWrapper.getInstance().startActivityFromRecents(toTask.key, launchOpts,
+ ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(toTask.key, launchOpts,
null /* resultCallback */, null /* resultCallbackHandler */);
}
@@ -591,7 +588,7 @@
if (activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS) return;
// Find the task in the recents list
- ArrayList<Task> tasks = focusedStack.getStackTasks();
+ ArrayList<Task> tasks = focusedStack.getTasks();
Task toTask = null;
ActivityOptions launchOpts = null;
int taskCount = tasks.size();
@@ -635,7 +632,7 @@
MetricsLogger.count(mContext, "overview_affiliated_task_launch", 1);
// Launch the task
- ActivityManagerWrapper.getInstance().startActivityFromRecents(toTask.key, launchOpts,
+ ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(toTask.key, launchOpts,
null /* resultListener */, null /* resultCallbackHandler */);
}
@@ -879,12 +876,12 @@
RectF toTaskRect = toTransform.rect;
AppTransitionAnimationSpecsFuture future = new AppTransitionAnimationSpecsFuture(mHandler) {
@Override
- public List<AppTransitionAnimationSpec> composeSpecs() {
+ public List<AppTransitionAnimationSpecCompat> composeSpecs() {
Rect rect = new Rect();
toTaskRect.round(rect);
- GraphicBuffer thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform);
- return Lists.newArrayList(new AppTransitionAnimationSpec(toTask.key.id, thumbnail,
- rect));
+ Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform);
+ return Lists.newArrayList(new AppTransitionAnimationSpecCompat(toTask.key.id,
+ thumbnail, rect));
}
};
@@ -907,7 +904,7 @@
runningTaskOut.copyFrom(launchTask);
} else {
// If no task is specified or we can not find the task just use the front most one
- launchTask = stack.getStackFrontMostTask();
+ launchTask = stack.getFrontMostTask();
runningTaskOut.copyFrom(launchTask);
}
@@ -922,7 +919,7 @@
/**
* Draws the header of a task used for the window animation into a bitmap.
*/
- private GraphicBuffer drawThumbnailTransitionBitmap(Task toTask,
+ private Bitmap drawThumbnailTransitionBitmap(Task toTask,
TaskViewTransform toTransform) {
SystemServicesProxy ssp = Recents.getSystemServices();
int width = (int) toTransform.rect.width();
@@ -932,7 +929,7 @@
boolean disabledInSafeMode = !toTask.isSystemApp && ssp.isInSafeMode();
mHeaderBar.onTaskViewSizeChanged(width, height);
if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
- return RecentsTransition.drawViewIntoGraphicBuffer(width, mTaskBarHeight,
+ return RecentsTransition.drawViewIntoHardwareBitmap(width, mTaskBarHeight,
null, 1f, 0xFFff0000);
} else {
// Workaround for b/27815919, reset the callback so that we do not trigger an
@@ -945,7 +942,7 @@
disabledInSafeMode);
mHeaderBar.onTaskDataLoaded();
mHeaderBar.setDimAlpha(toTransform.dimAlpha);
- return RecentsTransition.drawViewIntoGraphicBuffer(width, mTaskBarHeight,
+ return RecentsTransition.drawViewIntoHardwareBitmap(width, mTaskBarHeight,
mHeaderBar, 1f, 0);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 5eb315e..d89bab7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -114,7 +114,6 @@
UserManager mUm;
Display mDisplay;
String mRecentsPackage;
- private TaskStackChangeListeners mTaskStackChangeListeners;
private int mCurrentUserId;
boolean mIsSafeMode;
@@ -156,7 +155,6 @@
mRecentsPackage = context.getPackageName();
mIsSafeMode = mPm.isSafeMode();
mCurrentUserId = mAm.getCurrentUser();
- mTaskStackChangeListeners = new TaskStackChangeListeners(Looper.getMainLooper());
// Get the dummy thumbnail width/heights
Resources res = context.getResources();
@@ -494,18 +492,6 @@
}
}
- /**
- * Registers a task stack listener with the system.
- * This should be called on the main thread.
- */
- public void registerTaskStackListener(SysUiTaskStackChangeListener listener) {
- if (mIam == null) return;
-
- synchronized (mTaskStackChangeListeners) {
- mTaskStackChangeListeners.addListener(mIam, listener);
- }
- }
-
public void endProlongedAnimations() {
if (mWm == null) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionComposer.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionComposer.java
index 99390ec..1c47430 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionComposer.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionComposer.java
@@ -23,14 +23,15 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import android.content.Context;
+import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
import android.util.Log;
-import android.view.AppTransitionAnimationSpec;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
import com.android.systemui.shared.recents.view.RecentsTransition;
import java.util.ArrayList;
@@ -54,9 +55,9 @@
/**
* Composes a single animation spec for the given {@link TaskView}
*/
- private static AppTransitionAnimationSpec composeAnimationSpec(TaskStackView stackView,
+ private static AppTransitionAnimationSpecCompat composeAnimationSpec(TaskStackView stackView,
TaskView taskView, TaskViewTransform transform, boolean addHeaderBitmap) {
- GraphicBuffer b = null;
+ Bitmap b = null;
if (addHeaderBitmap) {
b = composeHeaderBitmap(taskView, transform);
if (b == null) {
@@ -71,28 +72,28 @@
// force the task thumbnail to full stackView height immediately causing the transition
// jarring.
if (!Recents.getConfiguration().isLowRamDevice && taskView.getTask() !=
- stackView.getStack().getStackFrontMostTask()) {
+ stackView.getStack().getFrontMostTask()) {
taskRect.bottom = taskRect.top + stackView.getMeasuredHeight();
}
- return new AppTransitionAnimationSpec(taskView.getTask().key.id, b, taskRect);
+ return new AppTransitionAnimationSpecCompat(taskView.getTask().key.id, b, taskRect);
}
/**
* Composes the transition spec when docking a task, which includes a full task bitmap.
*/
- public List<AppTransitionAnimationSpec> composeDockAnimationSpec(TaskView taskView,
+ public List<AppTransitionAnimationSpecCompat> composeDockAnimationSpec(TaskView taskView,
Rect bounds) {
mTmpTransform.fillIn(taskView);
Task task = taskView.getTask();
- GraphicBuffer buffer = RecentsTransitionComposer.composeTaskBitmap(taskView, mTmpTransform);
- return Collections.singletonList(new AppTransitionAnimationSpec(task.key.id, buffer,
+ Bitmap buffer = RecentsTransitionComposer.composeTaskBitmap(taskView, mTmpTransform);
+ return Collections.singletonList(new AppTransitionAnimationSpecCompat(task.key.id, buffer,
bounds));
}
/**
* Composes the animation specs for all the tasks in the target stack.
*/
- public List<AppTransitionAnimationSpec> composeAnimationSpecs(final Task task,
+ public List<AppTransitionAnimationSpecCompat> composeAnimationSpecs(final Task task,
final TaskStackView stackView, int windowingMode, int activityType, Rect windowRect) {
// Calculate the offscreen task rect (for tasks that are not backed by views)
TaskView taskView = stackView.getChildViewForTask(task);
@@ -110,13 +111,13 @@
|| windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
|| activityType == ACTIVITY_TYPE_ASSISTANT
|| windowingMode == WINDOWING_MODE_UNDEFINED) {
- List<AppTransitionAnimationSpec> specs = new ArrayList<>();
+ List<AppTransitionAnimationSpecCompat> specs = new ArrayList<>();
if (taskView == null) {
specs.add(composeOffscreenAnimationSpec(task, offscreenTaskRect));
} else {
mTmpTransform.fillIn(taskView);
stackLayout.transformToScreenCoordinates(mTmpTransform, windowRect);
- AppTransitionAnimationSpec spec = composeAnimationSpec(stackView, taskView,
+ AppTransitionAnimationSpecCompat spec = composeAnimationSpec(stackView, taskView,
mTmpTransform, true /* addHeaderBitmap */);
if (spec != null) {
specs.add(spec);
@@ -130,12 +131,12 @@
/**
* Composes a single animation spec for the given {@link Task}
*/
- private static AppTransitionAnimationSpec composeOffscreenAnimationSpec(Task task,
+ private static AppTransitionAnimationSpecCompat composeOffscreenAnimationSpec(Task task,
Rect taskRect) {
- return new AppTransitionAnimationSpec(task.key.id, null, taskRect);
+ return new AppTransitionAnimationSpecCompat(task.key.id, null, taskRect);
}
- public static GraphicBuffer composeTaskBitmap(TaskView taskView, TaskViewTransform transform) {
+ public static Bitmap composeTaskBitmap(TaskView taskView, TaskViewTransform transform) {
float scale = transform.scale;
int fromWidth = (int) (transform.rect.width() * scale);
int fromHeight = (int) (transform.rect.height() * scale);
@@ -143,19 +144,19 @@
Log.e(TAG, "Could not compose thumbnail for task: " + taskView.getTask() +
" at transform: " + transform);
- return RecentsTransition.drawViewIntoGraphicBuffer(1, 1, null, 1f, 0x00ffffff);
+ return RecentsTransition.drawViewIntoHardwareBitmap(1, 1, null, 1f, 0x00ffffff);
} else {
if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
- return RecentsTransition.drawViewIntoGraphicBuffer(fromWidth, fromHeight, null, 1f,
+ return RecentsTransition.drawViewIntoHardwareBitmap(fromWidth, fromHeight, null, 1f,
0xFFff0000);
} else {
- return RecentsTransition.drawViewIntoGraphicBuffer(fromWidth, fromHeight, taskView,
+ return RecentsTransition.drawViewIntoHardwareBitmap(fromWidth, fromHeight, taskView,
scale, 0);
}
}
}
- private static GraphicBuffer composeHeaderBitmap(TaskView taskView,
+ private static Bitmap composeHeaderBitmap(TaskView taskView,
TaskViewTransform transform) {
float scale = transform.scale;
int headerWidth = (int) (transform.rect.width());
@@ -165,10 +166,10 @@
}
if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
- return RecentsTransition.drawViewIntoGraphicBuffer(headerWidth, headerHeight, null, 1f,
+ return RecentsTransition.drawViewIntoHardwareBitmap(headerWidth, headerHeight, null, 1f,
0xFFff0000);
} else {
- return RecentsTransition.drawViewIntoGraphicBuffer(headerWidth, headerHeight,
+ return RecentsTransition.drawViewIntoHardwareBitmap(headerWidth, headerHeight,
taskView.mHeaderView, scale, 0);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index b82f15e..1440fc1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -16,7 +16,6 @@
package com.android.systemui.recents.views;
-import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_HOME_KEY;
import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS;
import android.animation.ValueAnimator;
@@ -90,6 +89,7 @@
import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.TaskStack;
+import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
import com.android.systemui.shared.recents.view.RecentsTransition;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -296,7 +296,7 @@
* @return True if it changed.
*/
private boolean updateBusyness() {
- final int taskCount = mTaskStackView.getStack().getStackTaskCount();
+ final int taskCount = mTaskStackView.getStack().getTaskCount();
final float busyness = Math.min(taskCount, BUSY_RECENTS_TASK_COUNT)
/ (float) BUSY_RECENTS_TASK_COUNT;
if (mBusynessFactor == busyness) {
@@ -611,27 +611,23 @@
// Dock the task and launch it
SystemServicesProxy ssp = Recents.getSystemServices();
if (ssp.startTaskInDockedMode(event.task.key.id, dockState.createMode)) {
- final OnAnimationStartedListener startedListener =
- new OnAnimationStartedListener() {
- @Override
- public void onAnimationStarted() {
- EventBus.getDefault().send(new DockedFirstAnimationFrameEvent());
- // Remove the task and don't bother relaying out, as all the tasks will be
- // relaid out when the stack changes on the multiwindow change event
- getStack().removeTask(event.task, null, true /* fromDockGesture */);
- }
+ final Runnable animStartedListener = () -> {
+ EventBus.getDefault().send(new DockedFirstAnimationFrameEvent());
+ // Remove the task and don't bother relaying out, as all the tasks will be
+ // relaid out when the stack changes on the multiwindow change event
+ getStack().removeTask(event.task, null, true /* fromDockGesture */);
};
final Rect taskRect = getTaskRect(event.taskView);
AppTransitionAnimationSpecsFuture future = new AppTransitionAnimationSpecsFuture(
getHandler()) {
@Override
- public List<AppTransitionAnimationSpec> composeSpecs() {
+ public List<AppTransitionAnimationSpecCompat> composeSpecs() {
return mTransitionHelper.composeDockAnimationSpec(event.taskView, taskRect);
}
};
ssp.overridePendingAppTransitionMultiThumbFuture(future.getFuture(),
- RecentsTransition.wrapStartedListener(getHandler(), startedListener),
+ RecentsTransition.wrapStartedListener(getHandler(), animStartedListener),
true /* scaleUp */);
MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_DRAG_DROP,
@@ -928,7 +924,7 @@
final TaskStackView stackView, final TaskView taskView,
final boolean screenPinningRequested, final int windowingMode, final int activityType) {
- final ActivityOptions.OnAnimationStartedListener animStartedListener;
+ final Runnable animStartedListener;
final AppTransitionAnimationSpecsFuture transitionFuture;
if (taskView != null) {
@@ -937,16 +933,16 @@
final Rect windowRect = Recents.getSystemServices().getWindowRect();
transitionFuture = new AppTransitionAnimationSpecsFuture(stackView.getHandler()) {
@Override
- public List<AppTransitionAnimationSpec> composeSpecs() {
+ public List<AppTransitionAnimationSpecCompat> composeSpecs() {
return mTransitionHelper.composeAnimationSpecs(task, stackView, windowingMode,
activityType, windowRect);
}
};
- animStartedListener = new OnAnimationStartedListener() {
+ animStartedListener = new Runnable() {
private boolean mHandled;
@Override
- public void onAnimationStarted() {
+ public void run() {
if (mHandled) {
return;
}
@@ -975,11 +971,11 @@
} else {
// This is only the case if the task is not on screen (scrolled offscreen for example)
transitionFuture = null;
- animStartedListener = new OnAnimationStartedListener() {
+ animStartedListener = new Runnable() {
private boolean mHandled;
@Override
- public void onAnimationStarted() {
+ public void run() {
if (mHandled) {
return;
}
@@ -1027,12 +1023,12 @@
private void startTaskActivity(TaskStack stack, Task task, @Nullable TaskView taskView,
ActivityOptions opts, AppTransitionAnimationSpecsFuture transitionFuture,
int windowingMode, int activityType) {
- ActivityManagerWrapper.getInstance().startActivityFromRecents(task.key, opts, windowingMode,
- activityType, succeeded -> {
+ ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(task.key, opts,
+ windowingMode, activityType, succeeded -> {
if (succeeded) {
// Keep track of the index of the task launch
int taskIndexFromFront = 0;
- int taskIndex = stack.indexOfStackTask(task);
+ int taskIndex = stack.indexOfTask(task);
if (taskIndex > -1) {
taskIndexFromFront = stack.getTaskCount() - taskIndex - 1;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
index 0cfdbde..5c69ae3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -40,7 +40,6 @@
import com.android.systemui.recents.events.ui.dragndrop.DragStartInitializeDropTargetsEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.TaskStack;
import java.util.ArrayList;
@@ -106,7 +105,7 @@
/** Handles touch events once we have intercepted them */
public boolean onTouchEvent(MotionEvent ev) {
handleTouchEvent(ev);
- if (ev.getAction() == MotionEvent.ACTION_UP && mRv.getStack().getStackTaskCount() == 0) {
+ if (ev.getAction() == MotionEvent.ACTION_UP && mRv.getStack().getTaskCount() == 0) {
EventBus.getDefault().send(new HideRecentsEvent(false, true));
}
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
index 7827c59..170e39d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -154,7 +154,7 @@
public final void onBusEvent(MultiWindowStateChangedEvent event) {
mHasDockedTasks = event.inMultiWindow;
- animateScrimToCurrentNavBarState(event.stack.getStackTaskCount() > 0);
+ animateScrimToCurrentNavBarState(event.stack.getTaskCount() > 0);
}
public final void onBusEvent(final DragEndEvent event) {
@@ -166,7 +166,7 @@
public final void onBusEvent(final DragEndCancelledEvent event) {
// Restore the scrims to the normal state
- animateScrimToCurrentNavBarState(event.stack.getStackTaskCount() > 0);
+ animateScrimToCurrentNavBarState(event.stack.getTaskCount() > 0);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index 26db26f..67d0978 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -449,7 +449,7 @@
// Get the current set of task transforms
int taskViewCount = mStackView.getTaskViews().size();
- ArrayList<Task> stackTasks = stack.getStackTasks();
+ ArrayList<Task> stackTasks = stack.getTasks();
mStackView.getCurrentTaskTransforms(stackTasks, mTmpCurrentTaskTransforms);
// Pick up the newly visible views after the scroll
@@ -541,7 +541,7 @@
TaskStackViewScroller stackScroller = mStackView.getScroller();
// Get the current set of task transforms
- ArrayList<Task> stackTasks = newStack.getStackTasks();
+ ArrayList<Task> stackTasks = newStack.getTasks();
mStackView.getCurrentTaskTransforms(stackTasks, mTmpCurrentTaskTransforms);
// Update the stack
@@ -563,7 +563,7 @@
false /* ignoreTaskOverrides */, mTmpFinalTaskTransforms);
// Hide the front most task view until the scroll is complete
- Task frontMostTask = newStack.getStackFrontMostTask();
+ Task frontMostTask = newStack.getFrontMostTask();
final TaskView frontMostTaskView = mStackView.getChildViewForTask(frontMostTask);
final TaskViewTransform frontMostTransform = mTmpFinalTaskTransforms.get(
stackTasks.indexOf(frontMostTask));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index acb058c..600da04 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -438,7 +438,7 @@
mTaskIndexMap.clear();
// Return early if we have no tasks
- ArrayList<Task> tasks = stack.getStackTasks();
+ ArrayList<Task> tasks = stack.getTasks();
if (tasks.isEmpty()) {
mFrontMostTaskP = 0;
mMinScrollP = mMaxScrollP = mInitialScrollP = 0;
@@ -468,7 +468,7 @@
// Calculate the min/max/initial scroll
Task launchTask = stack.getLaunchTarget();
int launchTaskIndex = launchTask != null
- ? stack.indexOfStackTask(launchTask)
+ ? stack.indexOfTask(launchTask)
: mNumStackTasks - 1;
if (getInitialFocusState() == STATE_FOCUSED) {
int maxBottomOffset = mStackBottomOffset + mTaskRect.height();
@@ -557,7 +557,7 @@
}
mUnfocusedRange.offset(0f);
- List<Task> tasks = stack.getStackTasks();
+ List<Task> tasks = stack.getTasks();
int taskCount = tasks.size();
for (int i = taskCount - 1; i >= 0; i--) {
int indexFromFront = taskCount - i - 1;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 428113a..1197501 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -535,7 +535,7 @@
*/
void bindVisibleTaskViews(float targetStackScroll, boolean ignoreTaskOverrides) {
// Get all the task transforms
- ArrayList<Task> tasks = mStack.getStackTasks();
+ ArrayList<Task> tasks = mStack.getTasks();
int[] visibleTaskRange = computeVisibleTaskTransforms(mCurrentTaskTransforms, tasks,
mStackScroller.getStackScroll(), targetStackScroll, mIgnoreTasks,
ignoreTaskOverrides);
@@ -557,7 +557,7 @@
// It is possible for the set of lingering TaskViews to differ from the stack if the
// stack was updated before the relayout. If the task view is no longer in the stack,
// then just return it back to the view pool.
- int taskIndex = mStack.indexOfStackTask(task);
+ int taskIndex = mStack.indexOfTask(task);
TaskViewTransform transform = null;
if (taskIndex != -1) {
transform = mCurrentTaskTransforms.get(taskIndex);
@@ -601,7 +601,7 @@
}
} else {
// Reattach it in the right z order
- final int taskIndex = mStack.indexOfStackTask(task);
+ final int taskIndex = mStack.indexOfTask(task);
final int insertIndex = findTaskViewInsertIndex(task, taskIndex);
if (insertIndex != getTaskViews().indexOf(tv)){
detachViewFromParent(tv);
@@ -663,7 +663,7 @@
continue;
}
- int taskIndex = mStack.indexOfStackTask(task);
+ int taskIndex = mStack.indexOfTask(task);
TaskViewTransform transform = mCurrentTaskTransforms.get(taskIndex);
if (animationOverrides != null && animationOverrides.containsKey(task)) {
animation = animationOverrides.get(task);
@@ -866,7 +866,7 @@
int newFocusedTaskIndex = mStack.getTaskCount() > 0 ?
Utilities.clamp(focusTaskIndex, 0, mStack.getTaskCount() - 1) : -1;
final Task newFocusedTask = (newFocusedTaskIndex != -1) ?
- mStack.getStackTasks().get(newFocusedTaskIndex) : null;
+ mStack.getTasks().get(newFocusedTaskIndex) : null;
// Reset the last focused task state if changed
if (mFocusedTask != null) {
@@ -953,10 +953,10 @@
public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated,
boolean cancelWindowAnimations, int timerIndicatorDuration) {
Task focusedTask = getFocusedTask();
- int newIndex = mStack.indexOfStackTask(focusedTask);
+ int newIndex = mStack.indexOfTask(focusedTask);
if (focusedTask != null) {
if (stackTasksOnly) {
- List<Task> tasks = mStack.getStackTasks();
+ List<Task> tasks = mStack.getTasks();
// Try the next task if it is a stack task
int tmpNewIndex = newIndex + (forward ? -1 : 1);
if (0 <= tmpNewIndex && tmpNewIndex < tasks.size()) {
@@ -971,7 +971,7 @@
} else {
// We don't have a focused task
float stackScroll = mStackScroller.getStackScroll();
- ArrayList<Task> tasks = mStack.getStackTasks();
+ ArrayList<Task> tasks = mStack.getTasks();
int taskCount = tasks.size();
if (useGridLayout()) {
// For the grid layout, we directly set focus to the most recently used task
@@ -1060,8 +1060,8 @@
if (taskViewCount > 0) {
TaskView backMostTask = taskViews.get(0);
TaskView frontMostTask = taskViews.get(taskViewCount - 1);
- event.setFromIndex(mStack.indexOfStackTask(backMostTask.getTask()));
- event.setToIndex(mStack.indexOfStackTask(frontMostTask.getTask()));
+ event.setFromIndex(mStack.indexOfTask(backMostTask.getTask()));
+ event.setToIndex(mStack.indexOfTask(frontMostTask.getTask()));
event.setContentDescription(frontMostTask.getTask().title);
}
event.setItemCount(mStack.getTaskCount());
@@ -1080,7 +1080,7 @@
// Find the accessibility focused task
Task focusedTask = getAccessibilityFocusedTask();
info.setScrollable(true);
- int focusedTaskIndex = mStack.indexOfStackTask(focusedTask);
+ int focusedTaskIndex = mStack.indexOfTask(focusedTask);
if (focusedTaskIndex > 0 || !mStackActionButtonVisible) {
info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
}
@@ -1101,7 +1101,7 @@
return true;
}
Task focusedTask = getAccessibilityFocusedTask();
- int taskIndex = mStack.indexOfStackTask(focusedTask);
+ int taskIndex = mStack.indexOfTask(focusedTask);
if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
switch (action) {
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
@@ -1157,7 +1157,7 @@
* updateLayoutForStack() is called first.
*/
public TaskStackLayoutAlgorithm.VisibilityReport computeStackVisibilityReport() {
- return mLayoutAlgorithm.computeStackVisibilityReport(mStack.getStackTasks());
+ return mLayoutAlgorithm.computeStackVisibilityReport(mStack.getTasks());
}
/**
@@ -1328,10 +1328,9 @@
// We set the initial focused task view iff the following conditions are satisfied:
// 1. Recents is showing task views in stack layout.
// 2. Recents is launched with ALT + TAB.
- boolean setFocusOnFirstLayout = !useGridLayout() ||
- Recents.getConfiguration().getLaunchState().launchedWithAltTab;
+ boolean setFocusOnFirstLayout = !useGridLayout() || launchState.launchedWithAltTab;
if (setFocusOnFirstLayout) {
- int focusedTaskIndex = launchState.getInitialFocusTaskIndex(mStack.getTaskCount(),
+ int focusedTaskIndex = getInitialFocusTaskIndex(launchState, mStack.getTaskCount(),
useGridLayout());
if (focusedTaskIndex != -1) {
setFocusedTask(focusedTaskIndex, false /* scrollToTask */,
@@ -1502,7 +1501,7 @@
@Override
public void onPickUpViewFromPool(TaskView tv, Task task, boolean isNewView) {
// Find the index where this task should be placed in the stack
- int taskIndex = mStack.indexOfStackTask(task);
+ int taskIndex = mStack.indexOfTask(task);
int insertIndex = findTaskViewInsertIndex(task, taskIndex);
// Add/attach the view to the hierarchy
@@ -1545,7 +1544,7 @@
}
// Restore the action button visibility if it is the front most task view
- if (mScreenPinningEnabled && tv.getTask() == mStack.getStackFrontMostTask()) {
+ if (mScreenPinningEnabled && tv.getTask() == mStack.getFrontMostTask()) {
tv.showActionButton(false /* fadeIn */, 0 /* fadeInDuration */);
}
}
@@ -1669,7 +1668,7 @@
event.packageName, event.userId);
// For other tasks, just remove them directly if they no longer exist
- ArrayList<Task> tasks = mStack.getStackTasks();
+ ArrayList<Task> tasks = mStack.getTasks();
for (int i = tasks.size() - 1; i >= 0; i--) {
final Task t = tasks.get(i);
if (removedComponents.contains(t.key.getComponent())) {
@@ -1692,7 +1691,7 @@
public final void onBusEvent(LaunchMostRecentTaskRequestEvent event) {
if (mStack.getTaskCount() > 0) {
- Task mostRecentTask = mStack.getStackFrontMostTask();
+ Task mostRecentTask = mStack.getFrontMostTask();
launchTask(mostRecentTask);
}
}
@@ -1786,7 +1785,7 @@
public final void onBusEvent(final DismissAllTaskViewsEvent event) {
// Keep track of the tasks which will have their data removed
- ArrayList<Task> tasks = new ArrayList<>(mStack.getStackTasks());
+ ArrayList<Task> tasks = new ArrayList<>(mStack.getTasks());
mAnimationHelper.startDeleteAllTasksAnimation(
getTaskViews(), useGridLayout(), event.getAnimationTrigger());
event.addPostAnimationCallback(new Runnable() {
@@ -1854,7 +1853,7 @@
public final void onBusEvent(NavigateTaskViewEvent event) {
if (useGridLayout()) {
final int taskCount = mStack.getTaskCount();
- final int currentIndex = mStack.indexOfStackTask(getFocusedTask());
+ final int currentIndex = mStack.indexOfTask(getFocusedTask());
final int nextIndex = mLayoutAlgorithm.mTaskGridLayoutAlgorithm.navigateFocus(taskCount,
currentIndex, event.direction);
setFocusedTask(nextIndex, false, true);
@@ -2000,7 +1999,7 @@
if (mFocusedTask != null) {
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
- setFocusedTask(mStack.indexOfStackTask(mFocusedTask),
+ setFocusedTask(mStack.indexOfTask(mFocusedTask),
false /* scrollToTask */, launchState.launchedWithAltTab);
TaskView focusedTaskView = getChildViewForTask(mFocusedTask);
if (mTouchExplorationEnabled && focusedTaskView != null) {
@@ -2131,7 +2130,7 @@
Task tvTask = taskViews.get(i).getTask();
if (tvTask == task) {
foundTaskView = true;
- } else if (taskIndex < mStack.indexOfStackTask(tvTask)) {
+ } else if (taskIndex < mStack.indexOfTask(tvTask)) {
if (foundTaskView) {
return i - 1;
} else {
@@ -2201,6 +2200,25 @@
}
/**
+ * Returns the task to focus given the current launch state.
+ */
+ private int getInitialFocusTaskIndex(RecentsActivityLaunchState launchState, int numTasks,
+ boolean useGridLayout) {
+ if (launchState.launchedFromApp) {
+ if (useGridLayout) {
+ // If coming from another app to the grid layout, focus the front most task
+ return numTasks - 1;
+ }
+
+ // If coming from another app, focus the next task
+ return Math.max(0, numTasks - 2);
+ } else {
+ // If coming from home, focus the front most task
+ return numTasks - 1;
+ }
+ }
+
+ /**
* Updates {@param transforms} to be the same size as {@param tasks}.
*/
private void matchTaskListSize(List<Task> tasks, List<TaskViewTransform> transforms) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index b9ca248..bfaa8cd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -446,7 +446,7 @@
TaskView tv = (TaskView) v;
Task task = tv.getTask();
return !mSwipeHelperAnimations.containsKey(v) &&
- (mSv.getStack().indexOfStackTask(task) != -1);
+ (mSv.getStack().indexOfTask(task) != -1);
}
/**
@@ -476,7 +476,7 @@
mSv.addIgnoreTask(tv.getTask());
// Determine if we are animating the other tasks while dismissing this task
- mCurrentTasks = new ArrayList<Task>(mSv.getStack().getStackTasks());
+ mCurrentTasks = new ArrayList<Task>(mSv.getStack().getTasks());
MutableBoolean isFrontMostTask = new MutableBoolean(false);
Task anchorTask = mSv.findAnchorTask(mCurrentTasks, isFrontMostTask);
TaskStackLayoutAlgorithm layoutAlgorithm = mSv.getStackAlgorithm();
@@ -673,7 +673,7 @@
/** Returns the view at the specified coordinates */
private TaskView findViewAtPoint(int x, int y) {
- List<Task> tasks = mSv.getStack().getStackTasks();
+ List<Task> tasks = mSv.getStack().getTasks();
int taskCount = tasks.size();
for (int i = taskCount - 1; i >= 0; i--) {
TaskView tv = mSv.getChildViewForTask(tasks.get(i));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index b440847..f0278a6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -55,6 +55,7 @@
import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.recents.view.AnimateableViewBounds;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -683,7 +684,7 @@
}
SystemServicesProxy ssp = Recents.getSystemServices();
boolean inBounds = false;
- Rect clipBounds = new Rect(mViewBounds.mClipBounds);
+ Rect clipBounds = new Rect(mViewBounds.getClipBounds());
if (!clipBounds.isEmpty()) {
// If we are clipping the view to the bounds, manually do the hit test.
clipBounds.scale(getScaleX());
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/AnimateableGridViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/AnimateableGridViewBounds.java
index a029478..3bdad31 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/AnimateableGridViewBounds.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/grid/AnimateableGridViewBounds.java
@@ -17,7 +17,7 @@
package com.android.systemui.recents.views.grid;
import android.view.View;
-import com.android.systemui.recents.views.AnimateableViewBounds;
+import com.android.systemui.shared.recents.view.AnimateableViewBounds;
/* An outline provider for grid-based task views. */
class AnimateableGridViewBounds extends AnimateableViewBounds {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java
index 8b4700c..0d51154 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java
@@ -19,7 +19,7 @@
import android.content.Context;
import android.util.AttributeSet;
import com.android.systemui.R;
-import com.android.systemui.recents.views.AnimateableViewBounds;
+import com.android.systemui.shared.recents.view.AnimateableViewBounds;
import com.android.systemui.recents.views.TaskView;
public class GridTaskView extends TaskView {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskViewFocusFrame.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskViewFocusFrame.java
index 95f1d58..fe6bafb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskViewFocusFrame.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskViewFocusFrame.java
@@ -125,7 +125,7 @@
// We're returning from touch mode, set the focus to the previously focused task.
final TaskStack stack = mSv.getStack();
final int taskCount = stack.getTaskCount();
- final int k = stack.indexOfStackTask(mSv.getFocusedTask());
+ final int k = stack.indexOfTask(mSv.getFocusedTask());
final int taskIndexToFocus = k == -1 ? (taskCount - 1) : (k % taskCount);
mSv.setFocusedTask(taskIndexToFocus, false, true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
index b2bbe30..826fa6c 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
@@ -33,6 +33,7 @@
import com.android.systemui.recents.events.component.ShowUserToastEvent;
import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.stackdivider.events.StartedDragingEvent;
import com.android.systemui.stackdivider.events.StoppedDragingEvent;
@@ -75,7 +76,7 @@
public ForcedResizableInfoActivityController(Context context) {
mContext = context;
EventBus.getDefault().register(this);
- SystemServicesProxy.getInstance(context).registerTaskStackListener(
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(
new SysUiTaskStackChangeListener() {
@Override
public void onActivityForcedResizable(String packageName, int taskId,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 41cae6b..5941af2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -85,7 +85,7 @@
public void start() {
super.start();
mTaskStackListener = new TaskStackListenerImpl();
- SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener);
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
registerPackageChangeReceivers();
mStackScroller.setScrollingEnabled(true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index 4180884..bed6d82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -19,6 +19,7 @@
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.RemoteException;
import android.util.Log;
@@ -76,6 +77,8 @@
private final GestureDetector mTaskSwitcherDetector;
private final int mScrollTouchSlop;
private final int mMinFlingVelocity;
+ private final Matrix mTransformGlobalMatrix = new Matrix();
+ private final Matrix mTransformLocalMatrix = new Matrix();
private int mTouchDownX;
private int mTouchDownY;
private boolean mDownOnRecents;
@@ -116,27 +119,30 @@
final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
if (overviewProxy != null) {
mNavigationBarView.requestUnbufferedDispatch(event);
+ event.transform(mTransformGlobalMatrix);
try {
overviewProxy.onMotionEvent(event);
return true;
} catch (RemoteException e) {
Log.e(TAG, "Callback failed", e);
+ } finally {
+ event.transform(mTransformLocalMatrix);
}
}
return false;
}
public boolean onInterceptTouchEvent(MotionEvent event) {
- if (!proxyMotionEvents(event)) {
- // If we move more than a fixed amount, then start capturing for the
- // task switcher detector, disabled when proxying motion events to launcher service
- mTaskSwitcherDetector.onTouchEvent(event);
- }
int action = event.getAction();
+ boolean result = false;
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
mTouchDownX = (int) event.getX();
mTouchDownY = (int) event.getY();
+ mTransformGlobalMatrix.set(Matrix.IDENTITY_MATRIX);
+ mTransformLocalMatrix.set(Matrix.IDENTITY_MATRIX);
+ mNavigationBarView.transformMatrixToGlobal(mTransformGlobalMatrix);
+ mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix);
break;
}
case MotionEvent.ACTION_MOVE: {
@@ -147,7 +153,7 @@
boolean exceededTouchSlop = xDiff > mScrollTouchSlop && xDiff > yDiff
|| yDiff > mScrollTouchSlop && yDiff > xDiff;
if (exceededTouchSlop) {
- return true;
+ result = true;
}
break;
}
@@ -155,7 +161,12 @@
case MotionEvent.ACTION_UP:
break;
}
- return mDockWindowEnabled && interceptDockWindowEvent(event);
+ if (!proxyMotionEvents(event)) {
+ // If we move more than a fixed amount, then start capturing for the
+ // task switcher detector, disabled when proxying motion events to launcher service
+ mTaskSwitcherDetector.onTouchEvent(event);
+ }
+ return result || (mDockWindowEnabled && interceptDockWindowEvent(event));
}
private boolean interceptDockWindowEvent(MotionEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index ba4ff58..09fe579 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -67,6 +67,7 @@
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.policy.BluetoothController;
@@ -249,7 +250,7 @@
mLocationController.addCallback(this);
SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallbacks(this);
- SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskListener);
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskListener);
// Clear out all old notifications on startup (only present in the case where sysui dies)
NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
index 87d11b2..4606aee 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
@@ -235,7 +235,7 @@
intent.putExtra(UsbManager.EXTRA_DEVICE, mDevice);
if (mPermissionGranted) {
service.grantDevicePermission(mDevice, mUid);
- if (mAlwaysUse.isChecked()) {
+ if (mAlwaysUse != null && mAlwaysUse.isChecked()) {
final int userId = UserHandle.getUserId(mUid);
service.setDevicePackage(mDevice, mPackageName, userId);
}
@@ -245,7 +245,7 @@
intent.putExtra(UsbManager.EXTRA_ACCESSORY, mAccessory);
if (mPermissionGranted) {
service.grantAccessoryPermission(mAccessory, mUid);
- if (mAlwaysUse.isChecked()) {
+ if (mAlwaysUse != null && mAlwaysUse.isChecked()) {
final int userId = UserHandle.getUserId(mUid);
service.setAccessoryPackage(mAccessory, mPackageName, userId);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
index d758314..cf32760 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
@@ -41,7 +41,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
-import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
import org.junit.Before;
import org.junit.Test;
@@ -61,7 +61,7 @@
private static final int TASK_ID = 444;
private @Mock Context mContext;
- private @Mock SystemServicesProxy mSystemServicesProxy;
+ private @Mock ActivityManagerWrapper mActivityManager;
private @Mock IActivityManager mIActivityManager;
private WorkLockActivityController mController;
@@ -77,10 +77,9 @@
// Construct controller. Save the TaskStackListener for injecting events.
final ArgumentCaptor<SysUiTaskStackChangeListener> listenerCaptor =
ArgumentCaptor.forClass(SysUiTaskStackChangeListener.class);
- mController =
- new WorkLockActivityController(mContext, mSystemServicesProxy, mIActivityManager);
+ mController = new WorkLockActivityController(mContext, mActivityManager, mIActivityManager);
- verify(mSystemServicesProxy).registerTaskStackListener(listenerCaptor.capture());
+ verify(mActivityManager).registerTaskStackListener(listenerCaptor.capture());
mTaskStackListener = listenerCaptor.getValue();
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 5823ab1..af4668a 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -36,6 +36,7 @@
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.IAssistDataReceiver;
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.AutofillOverlay;
import android.app.assist.AssistStructure.ViewNode;
@@ -76,7 +77,6 @@
import android.view.autofill.IAutofillWindowPresenter;
import com.android.internal.R;
-import com.android.internal.app.IAssistDataReceiver;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 3e40dfd..bccae06 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -5616,7 +5616,8 @@
}
private void logNetworkEvent(NetworkAgentInfo nai, int evtype) {
- mMetricsLog.log(new NetworkEvent(nai.network.netId, evtype));
+ int[] transports = nai.networkCapabilities.getTransportTypes();
+ mMetricsLog.log(nai.network.netId, transports, new NetworkEvent(evtype));
}
private static boolean toBool(int encodedBoolean) {
diff --git a/services/core/java/com/android/server/ForceAppStandbyTracker.java b/services/core/java/com/android/server/ForceAppStandbyTracker.java
new file mode 100644
index 0000000..5dd3ee0
--- /dev/null
+++ b/services/core/java/com/android/server/ForceAppStandbyTracker.java
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.app.AppOpsManager.PackageOps;
+import android.app.IUidObserver;
+import android.content.Context;
+import android.os.Handler;
+import android.os.PowerManager.ServiceType;
+import android.os.PowerManagerInternal;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.ArraySet;
+import android.util.Pair;
+import android.util.Slog;
+import android.util.SparseBooleanArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.app.IAppOpsCallback;
+import com.android.internal.app.IAppOpsService;
+import com.android.internal.util.Preconditions;
+
+import java.util.List;
+
+/**
+ * Class to track OP_RUN_ANY_IN_BACKGROUND, UID foreground state and "force all app standby".
+ *
+ * TODO Clean up cache when a user is deleted.
+ * TODO Add unit tests. b/68769804.
+ */
+public class ForceAppStandbyTracker {
+ private static final String TAG = "ForceAppStandbyTracker";
+
+ @GuardedBy("ForceAppStandbyTracker.class")
+ private static ForceAppStandbyTracker sInstance;
+
+ private final Object mLock = new Object();
+ private final Context mContext;
+
+ AppOpsManager mAppOpsManager;
+ IAppOpsService mAppOpsService;
+ PowerManagerInternal mPowerManagerInternal;
+
+ private final Handler mCallbackHandler;
+
+ /**
+ * Pair of (uid (not user-id), packageName) with OP_RUN_ANY_IN_BACKGROUND *not* allowed.
+ */
+ @GuardedBy("mLock")
+ final ArraySet<Pair<Integer, String>> mForcedAppStandbyUidPackages = new ArraySet<>();
+
+ @GuardedBy("mLock")
+ final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
+
+ @GuardedBy("mLock")
+ final ArraySet<Listener> mListeners = new ArraySet<>();
+
+ @GuardedBy("mLock")
+ boolean mStarted;
+
+ @GuardedBy("mLock")
+ boolean mForceAllAppsStandby;
+
+ public static abstract class Listener {
+ public void onRestrictionChanged(int uid, @Nullable String packageName) {
+ }
+
+ public void onGlobalRestrictionChanged() {
+ }
+ }
+
+ private ForceAppStandbyTracker(Context context) {
+ mContext = context;
+ mCallbackHandler = FgThread.getHandler();
+ }
+
+ /**
+ * Get the singleton instance.
+ */
+ public static synchronized ForceAppStandbyTracker getInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = new ForceAppStandbyTracker(context);
+ }
+ return sInstance;
+ }
+
+ /**
+ * Call it when the system is ready.
+ */
+ public void start() {
+ synchronized (mLock) {
+ if (mStarted) {
+ return;
+ }
+ mStarted = true;
+
+ mAppOpsManager = Preconditions.checkNotNull(
+ mContext.getSystemService(AppOpsManager.class));
+ mAppOpsService = Preconditions.checkNotNull(
+ IAppOpsService.Stub.asInterface(
+ ServiceManager.getService(Context.APP_OPS_SERVICE)));
+ mPowerManagerInternal = Preconditions.checkNotNull(
+ LocalServices.getService(PowerManagerInternal.class));
+
+ try {
+ ActivityManager.getService().registerUidObserver(new UidObserver(),
+ ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
+ | ActivityManager.UID_OBSERVER_ACTIVE,
+ ActivityManager.PROCESS_STATE_UNKNOWN, null);
+ mAppOpsService.startWatchingMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, null,
+ new AppOpsWatcher());
+ } catch (RemoteException e) {
+ // shouldn't happen.
+ }
+
+ mPowerManagerInternal.registerLowPowerModeObserver(
+ ServiceType.FORCE_ALL_APPS_STANDBY,
+ state -> updateForceAllAppsStandby(state.batterySaverEnabled));
+
+ updateForceAllAppsStandby(
+ mPowerManagerInternal.getLowPowerState(ServiceType.FORCE_ALL_APPS_STANDBY)
+ .batterySaverEnabled);
+
+ refreshForcedAppStandbyUidPackagesLocked();
+ }
+ }
+
+ /**
+ * Update {@link #mForcedAppStandbyUidPackages} with the current app ops state.
+ */
+ private void refreshForcedAppStandbyUidPackagesLocked() {
+ final int op = AppOpsManager.OP_RUN_ANY_IN_BACKGROUND;
+
+ mForcedAppStandbyUidPackages.clear();
+ final List<PackageOps> ops = mAppOpsManager.getPackagesForOps(new int[] {op});
+
+ if (ops == null) {
+ return;
+ }
+ final int size = ops.size();
+ for (int i = 0; i < size; i++) {
+ final AppOpsManager.PackageOps pkg = ops.get(i);
+ final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps();
+
+ for (int j = 0; j < entries.size(); j++) {
+ AppOpsManager.OpEntry ent = entries.get(j);
+ if (ent.getOp() != op) {
+ continue;
+ }
+ if (ent.getMode() != AppOpsManager.MODE_ALLOWED) {
+ mForcedAppStandbyUidPackages.add(Pair.create(
+ pkg.getUid(), pkg.getPackageName()));
+ }
+ }
+ }
+ }
+
+ boolean isRunAnyInBackgroundAppOpRestricted(int uid, @NonNull String packageName) {
+ try {
+ return mAppOpsService.checkOperation(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
+ uid, packageName) != AppOpsManager.MODE_ALLOWED;
+ } catch (RemoteException e) {
+ return false; // shouldn't happen.
+ }
+ }
+
+ private int findForcedAppStandbyUidPackageIndexLocked(int uid, @NonNull String packageName) {
+ // TODO Maybe we should switch to indexOf(Pair.create()) if the array size is too big.
+ final int size = mForcedAppStandbyUidPackages.size();
+ for (int i = 0; i < size; i++) {
+ final Pair<Integer, String> pair = mForcedAppStandbyUidPackages.valueAt(i);
+
+ if ((pair.first == uid) && packageName.equals(pair.second)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * @return whether a uid package-name pair is in mForcedAppStandbyUidPackages.
+ */
+ boolean isUidPackageRestrictedLocked(int uid, @NonNull String packageName) {
+ return findForcedAppStandbyUidPackageIndexLocked(uid, packageName) >= 0;
+ }
+
+ boolean updateRestrictedUidPackageLocked(int uid, @NonNull String packageName,
+ boolean restricted) {
+ final int index = findForcedAppStandbyUidPackageIndexLocked(uid, packageName);
+ final boolean wasRestricted = index >= 0;
+ if (wasRestricted == restricted) {
+ return false;
+ }
+ if (restricted) {
+ mForcedAppStandbyUidPackages.add(Pair.create(uid, packageName));
+ } else {
+ mForcedAppStandbyUidPackages.removeAt(index);
+ }
+ return true;
+ }
+
+ void uidToForeground(int uid) {
+ synchronized (mLock) {
+ if (!UserHandle.isApp(uid)) {
+ return;
+ }
+ // TODO This can be optimized by calling indexOfKey and sharing the index for get and
+ // put.
+ if (mForegroundUids.get(uid)) {
+ return;
+ }
+ mForegroundUids.put(uid, true);
+ notifyForUidPackage(uid, null);
+ }
+ }
+
+ void uidToBackground(int uid, boolean remove) {
+ synchronized (mLock) {
+ if (!UserHandle.isApp(uid)) {
+ return;
+ }
+ // TODO This can be optimized by calling indexOfKey and sharing the index for get and
+ // put.
+ if (!mForegroundUids.get(uid)) {
+ return;
+ }
+ if (remove) {
+ mForegroundUids.delete(uid);
+ } else {
+ mForegroundUids.put(uid, false);
+ }
+ notifyForUidPackage(uid, null);
+ }
+ }
+
+ // Event handlers
+
+ final class UidObserver extends IUidObserver.Stub {
+ @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
+ }
+
+ @Override public void onUidGone(int uid, boolean disabled) {
+ uidToBackground(uid, /*remove=*/ true);
+ }
+
+ @Override public void onUidActive(int uid) {
+ uidToForeground(uid);
+ }
+
+ @Override public void onUidIdle(int uid, boolean disabled) {
+ // Just to avoid excessive memcpy, don't remove from the array in this case.
+ uidToBackground(uid, /*remove=*/ false);
+ }
+
+ @Override public void onUidCachedChanged(int uid, boolean cached) {
+ }
+ };
+
+ private final class AppOpsWatcher extends IAppOpsCallback.Stub {
+ @Override
+ public void opChanged(int op, int uid, String packageName) throws RemoteException {
+ synchronized (mLock) {
+ final boolean restricted = isRunAnyInBackgroundAppOpRestricted(uid, packageName);
+
+ if (updateRestrictedUidPackageLocked(uid, packageName, restricted)) {
+ notifyForUidPackage(uid, packageName);
+ }
+ }
+ }
+ }
+
+ private Listener[] cloneListeners() {
+ synchronized (mLock) {
+ return mListeners.toArray(new Listener[mListeners.size()]);
+ }
+ }
+
+ void notifyForUidPackage(int uid, String packageName) {
+ mCallbackHandler.post(() -> {
+ for (Listener l : cloneListeners()) {
+ l.onRestrictionChanged(uid, packageName);
+ }
+ });
+ }
+
+ void notifyGlobal() {
+ mCallbackHandler.post(() -> {
+ for (Listener l : cloneListeners()) {
+ l.onGlobalRestrictionChanged();
+ }
+ });
+ }
+
+ void updateForceAllAppsStandby(boolean forceAllAppsStandby) {
+ synchronized (mLock) {
+ if (mForceAllAppsStandby == forceAllAppsStandby) {
+ return;
+ }
+ mForceAllAppsStandby = forceAllAppsStandby;
+ Slog.i(TAG, "Force all app standby: " + mForceAllAppsStandby);
+ notifyGlobal();
+ }
+ }
+
+ // Public interface.
+
+ /**
+ * Register a new listener.
+ */
+ public void addListener(@NonNull Listener listener) {
+ synchronized (mLock) {
+ mListeners.add(listener);
+ }
+ }
+
+ /**
+ * Whether force-app-standby is effective for a UID package-name.
+ */
+ public boolean isRestricted(int uid, @NonNull String packageName) {
+ if (isInForeground(uid)) {
+ return false;
+ }
+ synchronized (mLock) {
+ if (mForceAllAppsStandby) {
+ return true;
+ }
+ return isUidPackageRestrictedLocked(uid, packageName);
+ }
+ }
+
+ /** For dumpsys -- otherwise the callers don't need to know it. */
+ public boolean isInForeground(int uid) {
+ if (!UserHandle.isApp(uid)) {
+ return true;
+ }
+ synchronized (mLock) {
+ return mForegroundUids.get(uid);
+ }
+ }
+
+ /** For dumpsys -- otherwise the callers don't need to know it. */
+ public boolean isForceAllAppsStandbyEnabled() {
+ synchronized (mLock) {
+ return mForceAllAppsStandby;
+ }
+ }
+
+ /** For dumpsys -- otherwise the callers don't need to know it. */
+ public boolean isRunAnyInBackgroundAppOpsAllowed(int uid, @NonNull String packageName) {
+ synchronized (mLock) {
+ return !isUidPackageRestrictedLocked(uid, packageName);
+ }
+ }
+
+ /** For dumpsys -- otherwise the callers don't need to know it. */
+ public SparseBooleanArray getForegroudUids() {
+ synchronized (mLock) {
+ return mForegroundUids.clone();
+ }
+ }
+
+ /** For dumpsys -- otherwise the callers don't need to know it. */
+ public ArraySet<Pair<Integer, String>> getRestrictedUidPackages() {
+ synchronized (mLock) {
+ return new ArraySet(mForcedAppStandbyUidPackages);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 2131731..701c574 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1043,8 +1043,8 @@
try {
if (AppGlobals.getPackageManager().checkPermission(
android.Manifest.permission.INSTANT_APP_FOREGROUND_SERVICE,
- r.appInfo.packageName,
- r.appInfo.uid) != PackageManager.PERMISSION_GRANTED) {
+ r.appInfo.packageName, UserHandle.getUserId(r.appInfo.uid))
+ != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Instant app " + r.appInfo.packageName
+ " does not have permission to create foreground"
+ "services");
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ea2d1f3..fe5c789 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -222,6 +222,7 @@
import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.IApplicationThread;
+import android.app.IAssistDataReceiver;
import android.app.IInstrumentationWatcher;
import android.app.INotificationManager;
import android.app.IProcessObserver;
@@ -373,7 +374,6 @@
import com.android.internal.app.DumpHeapActivity;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
-import com.android.internal.app.IAssistDataReceiver;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.ProcessMap;
import com.android.internal.app.SystemUserHomeActivity;
@@ -4712,8 +4712,8 @@
}
@Override
- public int startRecentsActivity(IAssistDataReceiver assistDataReceiver, Bundle bOptions,
- int userId) {
+ public int startRecentsActivity(IAssistDataReceiver assistDataReceiver, Bundle options,
+ Bundle activityOptions, int userId) {
if (!mRecentTasks.isCallerRecents(Binder.getCallingUid())) {
String msg = "Permission Denial: startRecentsActivity() from pid="
+ Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
@@ -4747,8 +4747,9 @@
final Intent intent = new Intent();
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
intent.setComponent(recentsComponent);
+ intent.putExtras(options);
return mActivityStarter.startActivityMayWait(null, recentsUid, recentsPackage,
- intent, null, null, null, null, null, 0, 0, null, null, null, bOptions,
+ intent, null, null, null, null, null, 0, 0, null, null, null, activityOptions,
false, userId, null, "startRecentsActivity");
}
} finally {
@@ -14921,6 +14922,23 @@
synchronized (this) {
writeBroadcastsToProtoLocked(proto);
}
+ } else if ("provider".equals(cmd)) {
+ String[] newArgs;
+ String name;
+ if (opti >= args.length) {
+ name = null;
+ newArgs = EMPTY_STRING_ARRAY;
+ } else {
+ name = args[opti];
+ opti++;
+ newArgs = new String[args.length - opti];
+ if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
+ args.length - opti);
+ }
+ if (!dumpProviderProto(fd, pw, name, newArgs)) {
+ pw.println("No providers match: " + name);
+ pw.println("Use -h for help.");
+ }
} else {
// default option, dump everything, output is ActivityManagerServiceProto
synchronized (this) {
@@ -16062,6 +16080,15 @@
return mProviderMap.dumpProvider(fd, pw, name, args, opti, dumpAll);
}
+ /**
+ * Similar to the dumpProvider, but only dumps the first matching provider.
+ * The provider is responsible for dumping as proto.
+ */
+ protected boolean dumpProviderProto(FileDescriptor fd, PrintWriter pw, String name,
+ String[] args) {
+ return mProviderMap.dumpProviderProto(fd, pw, name, args);
+ }
+
static class ItemMatcher {
ArrayList<ComponentName> components;
ArrayList<String> strings;
diff --git a/services/core/java/com/android/server/am/AssistDataReceiverProxy.java b/services/core/java/com/android/server/am/AssistDataReceiverProxy.java
index f22fe37..9991ce1 100644
--- a/services/core/java/com/android/server/am/AssistDataReceiverProxy.java
+++ b/services/core/java/com/android/server/am/AssistDataReceiverProxy.java
@@ -19,13 +19,13 @@
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import android.app.IAssistDataReceiver;
import android.graphics.Bitmap;
import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
-import com.android.internal.app.IAssistDataReceiver;
import com.android.server.am.AssistDataRequester.AssistDataRequesterCallbacks;
/**
diff --git a/services/core/java/com/android/server/am/AssistDataRequester.java b/services/core/java/com/android/server/am/AssistDataRequester.java
index a8f829f..9f7621f 100644
--- a/services/core/java/com/android/server/am/AssistDataRequester.java
+++ b/services/core/java/com/android/server/am/AssistDataRequester.java
@@ -23,6 +23,7 @@
import android.app.AppOpsManager;
import android.app.IActivityManager;
+import android.app.IAssistDataReceiver;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
@@ -31,7 +32,6 @@
import android.view.IWindowManager;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.app.IAssistDataReceiver;
import com.android.internal.logging.MetricsLogger;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/am/ProviderMap.java b/services/core/java/com/android/server/am/ProviderMap.java
index 32d03da..8a905f8 100644
--- a/services/core/java/com/android/server/am/ProviderMap.java
+++ b/services/core/java/com/android/server/am/ProviderMap.java
@@ -28,6 +28,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -322,8 +323,7 @@
return needSep;
}
- protected boolean dumpProvider(FileDescriptor fd, PrintWriter pw, String name, String[] args,
- int opti, boolean dumpAll) {
+ private ArrayList<ContentProviderRecord> getProvidersForName(String name) {
ArrayList<ContentProviderRecord> allProviders = new ArrayList<ContentProviderRecord>();
ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
@@ -365,6 +365,12 @@
}
}
}
+ return providers;
+ }
+
+ protected boolean dumpProvider(FileDescriptor fd, PrintWriter pw, String name, String[] args,
+ int opti, boolean dumpAll) {
+ ArrayList<ContentProviderRecord> providers = getProvidersForName(name);
if (providers.size() <= 0) {
return false;
@@ -417,6 +423,33 @@
}
/**
+ * Similar to the dumpProvider, but only dumps the first matching provider.
+ * The provider is responsible for dumping as proto.
+ */
+ protected boolean dumpProviderProto(FileDescriptor fd, PrintWriter pw, String name,
+ String[] args) {
+ //add back the --proto arg, which was stripped out by PriorityDump
+ String[] newArgs = Arrays.copyOf(args, args.length + 1);
+ newArgs[args.length] = "--proto";
+
+ ArrayList<ContentProviderRecord> providers = getProvidersForName(name);
+
+ if (providers.size() <= 0) {
+ return false;
+ }
+
+ // Only dump the first provider, since we are dumping in proto format
+ for (int i = 0; i < providers.size(); i++) {
+ final ContentProviderRecord r = providers.get(i);
+ if (r.proc != null && r.proc.thread != null) {
+ dumpToTransferPipe(null, fd, pw, r, newArgs);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Invokes IApplicationThread.dumpProvider() on the thread of the specified provider without
* any meta string (e.g., provider info, indentation) written to the file descriptor.
*/
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 2df5dc9..4e3d8d2 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -89,6 +89,7 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
+import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemServiceManager;
import com.android.server.pm.UserManagerService;
@@ -355,27 +356,35 @@
// Only keep marching forward if user is actually unlocked
if (!StorageManager.isUserKeyUnlocked(userId)) return;
synchronized (mLock) {
- // Bail if we ended up with a stale user
- if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return;
-
- // Do not proceed if unexpected state
- if (!uss.setState(STATE_RUNNING_LOCKED, STATE_RUNNING_UNLOCKING)) {
+ // Do not proceed if unexpected state or a stale user
+ if (mStartedUsers.get(userId) != uss || uss.state != STATE_RUNNING_LOCKED) {
return;
}
}
- mInjector.getUserManagerInternal().setUserState(userId, uss.state);
uss.mUnlockProgress.start();
// Prepare app storage before we go any further
uss.mUnlockProgress.setProgress(5,
mInjector.getContext().getString(R.string.android_start_title));
- mInjector.getUserManager().onBeforeUnlockUser(userId);
- uss.mUnlockProgress.setProgress(20);
- // Dispatch unlocked to system services; when fully dispatched,
- // that calls through to the next "unlocked" phase
- mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0, uss)
- .sendToTarget();
+ // Call onBeforeUnlockUser on a worker thread that allows disk I/O
+ FgThread.getHandler().post(() -> {
+ mInjector.getUserManager().onBeforeUnlockUser(userId);
+ synchronized (mLock) {
+ // Do not proceed if unexpected state
+ if (!uss.setState(STATE_RUNNING_LOCKED, STATE_RUNNING_UNLOCKING)) {
+ return;
+ }
+ }
+ mInjector.getUserManagerInternal().setUserState(userId, uss.state);
+
+ uss.mUnlockProgress.setProgress(20);
+
+ // Dispatch unlocked to system services; when fully dispatched,
+ // that calls through to the next "unlocked" phase
+ mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0, uss)
+ .sendToTarget();
+ });
}
/**
@@ -1819,7 +1828,10 @@
case SYSTEM_USER_UNLOCK_MSG:
final int userId = msg.arg1;
mInjector.getSystemServiceManager().unlockUser(userId);
- mInjector.loadUserRecents(userId);
+ // Loads recents on a worker thread that allows disk I/O
+ FgThread.getHandler().post(() -> {
+ mInjector.loadUserRecents(userId);
+ });
if (userId == UserHandle.USER_SYSTEM) {
mInjector.startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index b549768..b9777ec 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -622,24 +622,15 @@
if (disabled) {
cancelJobsForUid(uid, "uid gone");
}
- synchronized (mLock) {
- mBackgroundJobsController.setUidActiveLocked(uid, false);
- }
}
@Override public void onUidActive(int uid) throws RemoteException {
- synchronized (mLock) {
- mBackgroundJobsController.setUidActiveLocked(uid, true);
- }
}
@Override public void onUidIdle(int uid, boolean disabled) {
if (disabled) {
cancelJobsForUid(uid, "app uid idle");
}
- synchronized (mLock) {
- mBackgroundJobsController.setUidActiveLocked(uid, false);
- }
}
@Override public void onUidCachedChanged(int uid, boolean cached) {
diff --git a/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java b/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
index 78b4160..f67bd04 100644
--- a/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -16,7 +16,6 @@
package com.android.server.job.controllers;
-import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -25,19 +24,20 @@
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.os.UserHandle;
-import android.util.ArraySet;
+import android.util.Pair;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.SparseBooleanArray;
-import com.android.internal.app.IAppOpsCallback;
-import com.android.internal.app.IAppOpsService;
import com.android.internal.util.ArrayUtils;
+import com.android.server.ForceAppStandbyTracker;
+import com.android.server.ForceAppStandbyTracker.Listener;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.JobStore;
import java.io.PrintWriter;
+import java.util.function.Predicate;
public final class BackgroundJobsController extends StateController {
@@ -49,18 +49,13 @@
private static volatile BackgroundJobsController sController;
private final JobSchedulerService mJobSchedulerService;
- private final IAppOpsService mAppOpsService;
private final IDeviceIdleController mDeviceIdleController;
- private final SparseBooleanArray mForegroundUids;
private int[] mPowerWhitelistedUserAppIds;
private int[] mTempWhitelistedAppIds;
- /**
- * Only tracks jobs for which source package app op RUN_ANY_IN_BACKGROUND is not ALLOWED.
- * Maps jobs to the sourceUid unlike the global {@link JobSchedulerService#mJobs JobStore}
- * which uses callingUid.
- */
- private SparseArray<ArraySet<JobStatus>> mTrackedJobs;
+
+ private final ForceAppStandbyTracker mForceAppStandbyTracker;
+
public static BackgroundJobsController get(JobSchedulerService service) {
synchronized (sCreationLock) {
@@ -89,9 +84,7 @@
} catch (RemoteException rexc) {
Slog.e(LOG_TAG, "Device idle controller not reachable");
}
- if (checkAllTrackedJobsLocked()) {
- mStateChangedListener.onControllerStateChanged();
- }
+ updateAllJobRestrictionsLocked();
}
}
};
@@ -99,16 +92,12 @@
private BackgroundJobsController(JobSchedulerService service, Context context, Object lock) {
super(service, context, lock);
mJobSchedulerService = service;
- mAppOpsService = IAppOpsService.Stub.asInterface(
- ServiceManager.getService(Context.APP_OPS_SERVICE));
mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
- mForegroundUids = new SparseBooleanArray();
- mTrackedJobs = new SparseArray<>();
+ mForceAppStandbyTracker = ForceAppStandbyTracker.getInstance(context);
+
try {
- mAppOpsService.startWatchingMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, null,
- new AppOpsWatcher());
mPowerWhitelistedUserAppIds = mDeviceIdleController.getAppIdUserWhitelist();
mTempWhitelistedAppIds = mDeviceIdleController.getAppIdTempWhitelist();
} catch (RemoteException rexc) {
@@ -120,184 +109,165 @@
powerWhitelistFilter.addAction(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
context.registerReceiverAsUser(mDozeWhitelistReceiver, UserHandle.ALL, powerWhitelistFilter,
null, null);
+
+ mForceAppStandbyTracker.addListener(mForceAppStandbyListener);
+ mForceAppStandbyTracker.start();
}
@Override
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
- final int uid = jobStatus.getSourceUid();
- final String packageName = jobStatus.getSourcePackageName();
- try {
- final int mode = mAppOpsService.checkOperation(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
- uid, packageName);
- if (mode == AppOpsManager.MODE_ALLOWED) {
- jobStatus.setBackgroundNotRestrictedConstraintSatisfied(true);
- return;
- }
- } catch (RemoteException rexc) {
- Slog.e(LOG_TAG, "Cannot reach app ops service", rexc);
- }
- jobStatus.setBackgroundNotRestrictedConstraintSatisfied(canRunJobLocked(uid));
- startTrackingJobLocked(jobStatus);
+ updateSingleJobRestrictionLocked(jobStatus);
}
@Override
public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
boolean forUpdate) {
- stopTrackingJobLocked(jobStatus);
- }
-
- /* Called by JobSchedulerService to report uid state changes between active and idle */
- public void setUidActiveLocked(int uid, boolean active) {
- final boolean changed = (active != mForegroundUids.get(uid));
- if (!changed) {
- return;
- }
- if (DEBUG) {
- Slog.d(LOG_TAG, "uid " + uid + " going to " + (active ? "fg" : "bg"));
- }
- if (active) {
- mForegroundUids.put(uid, true);
- } else {
- mForegroundUids.delete(uid);
- }
- if (checkTrackedJobsForUidLocked(uid)) {
- mStateChangedListener.onControllerStateChanged();
- }
}
@Override
public void dumpControllerStateLocked(final PrintWriter pw, final int filterUid) {
pw.println("BackgroundJobsController");
+
+ pw.print("Force all apps standby: ");
+ pw.println(mForceAppStandbyTracker.isForceAllAppsStandbyEnabled());
+
pw.print("Foreground uids: [");
- for (int i = 0; i < mForegroundUids.size(); i++) {
- if (mForegroundUids.valueAt(i)) pw.print(mForegroundUids.keyAt(i) + " ");
+ final SparseBooleanArray foregroundUids = mForceAppStandbyTracker.getForegroudUids();
+
+ String sep = "";
+ for (int i = 0; i < foregroundUids.size(); i++) {
+ if (foregroundUids.valueAt(i)) {
+ pw.print(sep);
+ pw.print(UserHandle.formatUid(foregroundUids.keyAt(i)));
+ sep = " ";
+ }
}
pw.println("]");
- mJobSchedulerService.getJobStore().forEachJob(new JobStore.JobStatusFunctor() {
- @Override
- public void process(JobStatus jobStatus) {
- if (!jobStatus.shouldDump(filterUid)) {
- return;
- }
- final int uid = jobStatus.getSourceUid();
- pw.print(" #");
- jobStatus.printUniqueId(pw);
- pw.print(" from ");
- UserHandle.formatUid(pw, uid);
- pw.print(mForegroundUids.get(uid) ? " foreground" : " background");
- if (isWhitelistedLocked(uid)) {
- pw.print(", whitelisted");
- }
- pw.print(": ");
- pw.print(jobStatus.getSourcePackageName());
- pw.print(" [background restrictions");
- final ArraySet<JobStatus> jobsForUid = mTrackedJobs.get(uid);
- pw.print(jobsForUid != null && jobsForUid.contains(jobStatus) ? " on]" : " off]");
- if ((jobStatus.satisfiedConstraints
- & JobStatus.CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0) {
- pw.println(" RUNNABLE");
- } else {
- pw.println(" WAITING");
- }
+
+ pw.println("Restricted packages:");
+ for (Pair<Integer, String> uidAndPackage
+ : mForceAppStandbyTracker.getRestrictedUidPackages()) {
+ pw.print(" ");
+ pw.print(UserHandle.formatUid(uidAndPackage.first));
+ pw.print(" ");
+ pw.print(uidAndPackage.second);
+ pw.println();
+ }
+
+ pw.println("Job state:");
+ mJobSchedulerService.getJobStore().forEachJob((jobStatus) -> {
+ if (!jobStatus.shouldDump(filterUid)) {
+ return;
+ }
+ final int uid = jobStatus.getSourceUid();
+ pw.print(" #");
+ jobStatus.printUniqueId(pw);
+ pw.print(" from ");
+ UserHandle.formatUid(pw, uid);
+ pw.print(mForceAppStandbyTracker.isInForeground(uid) ? " foreground" : " background");
+ if (isWhitelistedLocked(uid)) {
+ pw.print(", whitelisted");
+ }
+ pw.print(": ");
+ pw.print(jobStatus.getSourcePackageName());
+
+ pw.print(" [background restrictions ");
+ pw.print(mForceAppStandbyTracker.isRunAnyInBackgroundAppOpsAllowed(
+ jobStatus.getSourceUid(), jobStatus.getSourcePackageName()) ? "off]" : "on]");
+
+ if ((jobStatus.satisfiedConstraints
+ & JobStatus.CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0) {
+ pw.println(" RUNNABLE");
+ } else {
+ pw.println(" WAITING");
}
});
}
- void startTrackingJobLocked(JobStatus jobStatus) {
+ private void updateAllJobRestrictionsLocked() {
+ updateJobRestrictionsLocked(/*filterUid=*/ -1);
+ }
+
+ private void updateJobRestrictionsForUidLocked(int uid) {
+
+ // TODO Use forEachJobForSourceUid() once we have it.
+
+ updateJobRestrictionsLocked(/*filterUid=*/ uid);
+ }
+
+ private void updateJobRestrictionsLocked(int filterUid) {
+ final UpdateJobFunctor updateTrackedJobs =
+ new UpdateJobFunctor(filterUid);
+
+ final long start = DEBUG ? SystemClock.elapsedRealtimeNanos() : 0;
+
+ mJobSchedulerService.getJobStore().forEachJob(updateTrackedJobs);
+
+ final long time = DEBUG ? (SystemClock.elapsedRealtimeNanos() - start) : 0;
+ if (DEBUG) {
+ Slog.d(LOG_TAG, String.format(
+ "Job status updated: %d/%d checked/total jobs, %d us",
+ updateTrackedJobs.mCheckedCount,
+ updateTrackedJobs.mTotalCount,
+ (time / 1000)
+ ));
+ }
+
+ if (updateTrackedJobs.mChanged) {
+ mStateChangedListener.onControllerStateChanged();
+ }
+ }
+
+ private boolean isWhitelistedLocked(int uid) {
+ final int appId = UserHandle.getAppId(uid);
+ return ArrayUtils.contains(mTempWhitelistedAppIds, appId)
+ || ArrayUtils.contains(mPowerWhitelistedUserAppIds, appId);
+ }
+
+ boolean updateSingleJobRestrictionLocked(JobStatus jobStatus) {
+
final int uid = jobStatus.getSourceUid();
- ArraySet<JobStatus> jobsForUid = mTrackedJobs.get(uid);
- if (jobsForUid == null) {
- jobsForUid = new ArraySet<>();
- mTrackedJobs.put(uid, jobsForUid);
- }
- jobsForUid.add(jobStatus);
+ final String packageName = jobStatus.getSourcePackageName();
+
+ final boolean canRun = isWhitelistedLocked(uid)
+ || !mForceAppStandbyTracker.isRestricted(uid, packageName);
+
+ return jobStatus.setBackgroundNotRestrictedConstraintSatisfied(canRun);
}
- void stopTrackingJobLocked(JobStatus jobStatus) {
- final int uid = jobStatus.getSourceUid();
- ArraySet<JobStatus> jobsForUid = mTrackedJobs.get(uid);
- if (jobsForUid != null) {
- jobsForUid.remove(jobStatus);
- }
- }
+ private final class UpdateJobFunctor implements JobStore.JobStatusFunctor {
+ private final int mFilterUid;
- boolean checkAllTrackedJobsLocked() {
- boolean changed = false;
- for (int i = 0; i < mTrackedJobs.size(); i++) {
- changed |= checkTrackedJobsForUidLocked(mTrackedJobs.keyAt(i));
- }
- return changed;
- }
+ boolean mChanged = false;
+ int mTotalCount = 0;
+ int mCheckedCount = 0;
- private boolean checkTrackedJobsForUidLocked(int uid) {
- final ArraySet<JobStatus> jobsForUid = mTrackedJobs.get(uid);
- boolean changed = false;
- if (jobsForUid != null) {
- for (int i = 0; i < jobsForUid.size(); i++) {
- JobStatus jobStatus = jobsForUid.valueAt(i);
- changed |= jobStatus.setBackgroundNotRestrictedConstraintSatisfied(
- canRunJobLocked(uid));
- }
- }
- return changed;
- }
-
- boolean isWhitelistedLocked(int uid) {
- return ArrayUtils.contains(mTempWhitelistedAppIds, UserHandle.getAppId(uid))
- || ArrayUtils.contains(mPowerWhitelistedUserAppIds, UserHandle.getAppId(uid));
- }
-
- boolean canRunJobLocked(int uid) {
- return mForegroundUids.get(uid) || isWhitelistedLocked(uid);
- }
-
- private final class AppOpsWatcher extends IAppOpsCallback.Stub {
- @Override
- public void opChanged(int op, int uid, String packageName) throws RemoteException {
- synchronized (mLock) {
- final int mode = mAppOpsService.checkOperation(op, uid, packageName);
- if (DEBUG) {
- Slog.d(LOG_TAG,
- "Appop changed for " + uid + ", " + packageName + " to " + mode);
- }
- final boolean shouldTrack = (mode != AppOpsManager.MODE_ALLOWED);
- UpdateTrackedJobsFunc updateTrackedJobs = new UpdateTrackedJobsFunc(uid,
- packageName, shouldTrack);
- mJobSchedulerService.getJobStore().forEachJob(updateTrackedJobs);
- if (updateTrackedJobs.mChanged) {
- mStateChangedListener.onControllerStateChanged();
- }
- }
- }
- }
-
- private final class UpdateTrackedJobsFunc implements JobStore.JobStatusFunctor {
- private final String mPackageName;
- private final int mUid;
- private final boolean mShouldTrack;
- private boolean mChanged = false;
-
- UpdateTrackedJobsFunc(int uid, String packageName, boolean shouldTrack) {
- mUid = uid;
- mPackageName = packageName;
- mShouldTrack = shouldTrack;
+ UpdateJobFunctor(int filterUid) {
+ mFilterUid = filterUid;
}
@Override
public void process(JobStatus jobStatus) {
- final String packageName = jobStatus.getSourcePackageName();
- final int uid = jobStatus.getSourceUid();
- if (mUid != uid || !mPackageName.equals(packageName)) {
+ mTotalCount++;
+ if ((mFilterUid > 0) && (mFilterUid != jobStatus.getSourceUid())) {
return;
}
- if (mShouldTrack) {
- mChanged |= jobStatus.setBackgroundNotRestrictedConstraintSatisfied(
- canRunJobLocked(uid));
- startTrackingJobLocked(jobStatus);
- } else {
- mChanged |= jobStatus.setBackgroundNotRestrictedConstraintSatisfied(true);
- stopTrackingJobLocked(jobStatus);
+ mCheckedCount++;
+ if (updateSingleJobRestrictionLocked(jobStatus)) {
+ mChanged = true;
}
}
}
+
+ private final Listener mForceAppStandbyListener = new Listener() {
+ @Override
+ public void onRestrictionChanged(int uid, String packageName) {
+ updateJobRestrictionsForUidLocked(uid);
+ }
+
+ @Override
+ public void onGlobalRestrictionChanged() {
+ updateAllJobRestrictionsLocked();
+ }
+ };
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 557ba42..eb94414 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -736,6 +736,11 @@
for (NotificationVisibility nv : newlyVisibleKeys) {
NotificationRecord r = mNotificationsByKey.get(nv.key);
if (r == null) continue;
+ if (!r.isSeen()) {
+ // Report to usage stats that notification was made visible
+ if (DBG) Slog.d(TAG, "Marking notification as visible " + nv.key);
+ reportSeen(r);
+ }
r.setVisibility(true, nv.rank);
nv.recycle();
}
@@ -1643,6 +1648,14 @@
return INotificationManager.Stub.asInterface(mService);
}
+ protected void reportSeen(NotificationRecord r) {
+ final int userId = r.sbn.getUserId();
+ mAppUsageStats.reportEvent(r.sbn.getPackageName(),
+ userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM
+ : userId,
+ UsageEvents.Event.NOTIFICATION_SEEN);
+ }
+
@VisibleForTesting
NotificationManagerInternal getInternalService() {
return mInternalService;
@@ -2269,10 +2282,7 @@
}
if (!r.isSeen()) {
if (DBG) Slog.d(TAG, "Marking notification as seen " + keys[i]);
- mAppUsageStats.reportEvent(r.sbn.getPackageName(),
- userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM
- : userId,
- UsageEvents.Event.USER_INTERACTION);
+ reportSeen(r);
r.setSeen();
}
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 29f48ee..00cfa31 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -154,7 +154,13 @@
targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
final List<String> paths = pkg.getAllCodePaths();
- final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
+
+ int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
+ if (sharedGid == -1) {
+ Slog.wtf(TAG, "Well this is awkward; package " + pkg.applicationInfo.name + " had UID "
+ + pkg.applicationInfo.uid, new Throwable());
+ sharedGid = android.os.Process.NOBODY_UID;
+ }
// Get the class loader context dependencies.
// For each code path in the package, this array contains the class loader context that
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 1152310..dbf413f 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -717,6 +717,19 @@
}
}
+ @Override
+ public int getProfileParentId(int userHandle) {
+ checkManageUsersPermission("get the profile parent");
+ synchronized (mUsersLock) {
+ UserInfo profileParent = getProfileParentLU(userHandle);
+ if (profileParent == null) {
+ return userHandle;
+ }
+
+ return profileParent.id;
+ }
+ }
+
private UserInfo getProfileParentLU(int userHandle) {
UserInfo profile = getUserInfoLU(userHandle);
if (profile == null) {
diff --git a/services/core/java/com/android/server/power/BatterySaverPolicy.java b/services/core/java/com/android/server/power/BatterySaverPolicy.java
index 15121b8..3992f8a 100644
--- a/services/core/java/com/android/server/power/BatterySaverPolicy.java
+++ b/services/core/java/com/android/server/power/BatterySaverPolicy.java
@@ -29,16 +29,21 @@
import android.util.KeyValueListParser;
import android.util.Slog;
+import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.R;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.List;
/**
* Class to decide whether to turn on battery saver mode for specific service
*
+ * TODO: We should probably make {@link #mFilesForInteractive} and {@link #mFilesForNoninteractive}
+ * less flexible and just take a list of "CPU number - frequency" pairs. Being able to write
+ * anything under /sys/ and /proc/ is too loose.
+ *
* Test: atest BatterySaverPolicyTest
*/
public class BatterySaverPolicy extends ContentObserver {
@@ -62,12 +67,11 @@
private static final String KEY_ADJUST_BRIGHTNESS_FACTOR = "adjust_brightness_factor";
private static final String KEY_FULLBACKUP_DEFERRED = "fullbackup_deferred";
private static final String KEY_KEYVALUE_DEFERRED = "keyvaluebackup_deferred";
- private static final String KEY_FORCE_ALL_APPS_STANDBY_JOBS = "force_all_apps_standby_jobs";
- private static final String KEY_FORCE_ALL_APPS_STANDBY_ALARMS = "force_all_apps_standby_alarms";
+ private static final String KEY_FORCE_ALL_APPS_STANDBY = "force_all_apps_standby";
private static final String KEY_OPTIONAL_SENSORS_DISABLED = "optional_sensors_disabled";
- private static final String KEY_SCREEN_ON_FILE_PREFIX = "file-on:";
- private static final String KEY_SCREEN_OFF_FILE_PREFIX = "file-off:";
+ private static final String KEY_FILE_FOR_INTERACTIVE_PREFIX = "file-on:";
+ private static final String KEY_FILE_FOR_NONINTERACTIVE_PREFIX = "file-off:";
private static String mSettings;
private static String mDeviceSpecificSettings;
@@ -156,14 +160,9 @@
private float mAdjustBrightnessFactor;
/**
- * Whether to put all apps in the stand-by mode or not for job scheduler.
+ * Whether to put all apps in the stand-by mode.
*/
- private boolean mForceAllAppsStandbyJobs;
-
- /**
- * Whether to put all apps in the stand-by mode or not for alarms.
- */
- private boolean mForceAllAppsStandbyAlarms;
+ private boolean mForceAllAppsStandby;
/**
* Weather to show non-essential sensors (e.g. edge sensors) or not.
@@ -179,25 +178,25 @@
private ContentResolver mContentResolver;
@GuardedBy("mLock")
- private final ArrayList<BatterySaverPolicyListener> mListeners = new ArrayList<>();
+ private final List<BatterySaverPolicyListener> mListeners = new ArrayList<>();
/**
* List of [Filename -> content] that should be written when battery saver is activated
- * and the screen is on.
+ * and the device is interactive.
*
* We use this to change the max CPU frequencies.
*/
@GuardedBy("mLock")
- private ArrayMap<String, String> mScreenOnFiles;
+ private ArrayMap<String, String> mFilesForInteractive;
/**
* List of [Filename -> content] that should be written when battery saver is activated
- * and the screen is off.
+ * and the device is non-interactive.
*
* We use this to change the max CPU frequencies.
*/
@GuardedBy("mLock")
- private ArrayMap<String, String> mScreenOffFiles;
+ private ArrayMap<String, String> mFilesForNoninteractive;
public interface BatterySaverPolicyListener {
void onBatterySaverPolicyChanged(BatterySaverPolicy policy);
@@ -236,11 +235,6 @@
return R.string.config_batterySaverDeviceSpecificConfig;
}
- @VisibleForTesting
- void onChangeForTest() {
- onChange(true, null);
- }
-
@Override
public void onChange(boolean selfChange, Uri uri) {
final BatterySaverPolicyListener[] listeners;
@@ -297,9 +291,7 @@
mAdjustBrightnessDisabled = parser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED, false);
mAdjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR, 0.5f);
mDataSaverDisabled = parser.getBoolean(KEY_DATASAVER_DISABLED, true);
- mForceAllAppsStandbyJobs = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY_JOBS, true);
- mForceAllAppsStandbyAlarms =
- parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY_ALARMS, true);
+ mForceAllAppsStandby = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY, true);
mOptionalSensorsDisabled = parser.getBoolean(KEY_OPTIONAL_SENSORS_DISABLED, true);
// Get default value from Settings.Secure
@@ -315,8 +307,8 @@
+ deviceSpecificSetting);
}
- mScreenOnFiles = collectParams(parser, KEY_SCREEN_ON_FILE_PREFIX);
- mScreenOffFiles = collectParams(parser, KEY_SCREEN_OFF_FILE_PREFIX);
+ mFilesForInteractive = collectParams(parser, KEY_FILE_FOR_INTERACTIVE_PREFIX);
+ mFilesForNoninteractive = collectParams(parser, KEY_FILE_FOR_NONINTERACTIVE_PREFIX);
}
private static ArrayMap<String, String> collectParams(
@@ -330,7 +322,7 @@
}
final String path = key.substring(prefix.length());
- if (!(path.startsWith("/sys/") || path.startsWith("/proc"))) {
+ if (!(path.startsWith("/sys/") || path.startsWith("/proc/"))) {
Slog.wtf(TAG, "Invalid path: " + path);
continue;
}
@@ -387,12 +379,6 @@
case ServiceType.VIBRATION:
return builder.setBatterySaverEnabled(mVibrationDisabled)
.build();
- case ServiceType.FORCE_ALL_APPS_STANDBY_JOBS:
- return builder.setBatterySaverEnabled(mForceAllAppsStandbyJobs)
- .build();
- case ServiceType.FORCE_ALL_APPS_STANDBY_ALARMS:
- return builder.setBatterySaverEnabled(mForceAllAppsStandbyAlarms)
- .build();
case ServiceType.OPTIONAL_SENSORS:
return builder.setBatterySaverEnabled(mOptionalSensorsDisabled)
.build();
@@ -403,9 +389,9 @@
}
}
- public ArrayMap<String, String> getFileValues(boolean screenOn) {
+ public ArrayMap<String, String> getFileValues(boolean interactive) {
synchronized (mLock) {
- return screenOn ? mScreenOnFiles : mScreenOffFiles;
+ return interactive ? mFilesForInteractive : mFilesForNoninteractive;
}
}
@@ -428,17 +414,16 @@
pw.println(" " + KEY_ADJUST_BRIGHTNESS_DISABLED + "=" + mAdjustBrightnessDisabled);
pw.println(" " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + mAdjustBrightnessFactor);
pw.println(" " + KEY_GPS_MODE + "=" + mGpsMode);
- pw.println(" " + KEY_FORCE_ALL_APPS_STANDBY_JOBS + "=" + mForceAllAppsStandbyJobs);
- pw.println(" " + KEY_FORCE_ALL_APPS_STANDBY_ALARMS + "=" + mForceAllAppsStandbyAlarms);
+ pw.println(" " + KEY_FORCE_ALL_APPS_STANDBY + "=" + mForceAllAppsStandby);
pw.println(" " + KEY_OPTIONAL_SENSORS_DISABLED + "=" + mOptionalSensorsDisabled);
pw.println();
- pw.print(" Screen On Files:\n");
- dumpMap(pw, " ", mScreenOnFiles);
+ pw.print(" Interactive File values:\n");
+ dumpMap(pw, " ", mFilesForInteractive);
pw.println();
- pw.print(" Screen Off Files:\n");
- dumpMap(pw, " ", mScreenOffFiles);
+ pw.print(" Noninteractive File values:\n");
+ dumpMap(pw, " ", mFilesForNoninteractive);
pw.println();
}
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index a47b809..584761c 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -3105,7 +3105,7 @@
mIsVrModeEnabled = enabled;
}
- public static void powerHintInternal(int hintId, int data) {
+ private static void powerHintInternal(int hintId, int data) {
nativeSendPowerHint(hintId, data);
}
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 755c5f0..6bf725e 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -68,7 +68,8 @@
public final class ShutdownThread extends Thread {
// constants
private static final String TAG = "ShutdownThread";
- private static final int PHONE_STATE_POLL_SLEEP_MSEC = 500;
+ private static final int ACTION_DONE_POLL_WAIT_MS = 500;
+ private static final int RADIOS_STATE_POLL_SLEEP_MS = 100;
// maximum time we wait for the shutdown broadcast before going on.
private static final int MAX_BROADCAST_TIME = 10*1000;
private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000;
@@ -471,7 +472,7 @@
sInstance.setRebootProgress(status, null);
}
try {
- mActionDoneSync.wait(Math.min(delay, PHONE_STATE_POLL_SLEEP_MSEC));
+ mActionDoneSync.wait(Math.min(delay, ACTION_DONE_POLL_WAIT_MS));
} catch (InterruptedException e) {
}
}
@@ -565,7 +566,7 @@
sInstance.setRebootProgress(status, null);
}
try {
- mActionDoneSync.wait(Math.min(delay, PHONE_STATE_POLL_SLEEP_MSEC));
+ mActionDoneSync.wait(Math.min(delay, ACTION_DONE_POLL_WAIT_MS));
} catch (InterruptedException e) {
}
}
@@ -710,8 +711,7 @@
done[0] = true;
break;
}
- SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);
-
+ SystemClock.sleep(RADIOS_STATE_POLL_SLEEP_MS);
delay = endTime - SystemClock.elapsedRealtime();
}
}
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
index b3e8538..3db6a25 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
@@ -25,6 +25,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
+import android.os.PowerManagerInternal;
import android.os.PowerManagerInternal.LowPowerModeListener;
import android.os.PowerSaveState;
import android.os.UserHandle;
@@ -33,7 +34,9 @@
import android.widget.Toast;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
+import com.android.server.LocalServices;
import com.android.server.power.BatterySaverPolicy;
import com.android.server.power.BatterySaverPolicy.BatterySaverPolicyListener;
import com.android.server.power.PowerManagerService;
@@ -63,20 +66,17 @@
@GuardedBy("mLock")
private boolean mEnabled;
- /**
- * Keep track of the previous enabled state, which we use to decide when to send broadcasts,
- * which we don't want to send only when the screen state changes.
- */
- @GuardedBy("mLock")
- private boolean mWasEnabled;
-
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case Intent.ACTION_SCREEN_ON:
case Intent.ACTION_SCREEN_OFF:
- mHandler.postStateChanged();
+ if (!isEnabled()) {
+ return; // No need to send it if not enabled.
+ }
+ // Don't send the broadcast, because we never did so in this case.
+ mHandler.postStateChanged(/*sendBroadcast=*/ false);
break;
}
}
@@ -121,25 +121,32 @@
@Override
public void onBatterySaverPolicyChanged(BatterySaverPolicy policy) {
- mHandler.postStateChanged();
+ if (!isEnabled()) {
+ return; // No need to send it if not enabled.
+ }
+ mHandler.postStateChanged(/*sendBroadcast=*/ true);
}
private class MyHandler extends Handler {
- private final int MSG_STATE_CHANGED = 1;
+ private static final int MSG_STATE_CHANGED = 1;
+
+ private static final int ARG_DONT_SEND_BROADCAST = 0;
+ private static final int ARG_SEND_BROADCAST = 1;
public MyHandler(Looper looper) {
super(looper);
}
- public void postStateChanged() {
- obtainMessage(MSG_STATE_CHANGED).sendToTarget();
+ public void postStateChanged(boolean sendBroadcast) {
+ obtainMessage(MSG_STATE_CHANGED, sendBroadcast ?
+ ARG_SEND_BROADCAST : ARG_DONT_SEND_BROADCAST, 0).sendToTarget();
}
@Override
public void dispatchMessage(Message msg) {
switch (msg.what) {
case MSG_STATE_CHANGED:
- handleBatterySaverStateChanged();
+ handleBatterySaverStateChanged(msg.arg1 == ARG_SEND_BROADCAST);
break;
}
}
@@ -155,38 +162,53 @@
}
mEnabled = enable;
- mHandler.postStateChanged();
+ mHandler.postStateChanged(/*sendBroadcast=*/ true);
+ }
+ }
+
+ /** @return whether battery saver is enabled or not. */
+ boolean isEnabled() {
+ synchronized (mLock) {
+ return mEnabled;
}
}
/**
* Dispatch power save events to the listeners.
*
- * This is always called on the handler thread.
+ * This method is always called on the handler thread.
+ *
+ * This method is called only in the following cases:
+ * - When battery saver becomes activated.
+ * - When battery saver becomes deactivated.
+ * - When battery saver is on the interactive state changes.
+ * - When battery saver is on the battery saver policy changes.
*/
- void handleBatterySaverStateChanged() {
+ void handleBatterySaverStateChanged(boolean sendBroadcast) {
final LowPowerModeListener[] listeners;
- final boolean wasEnabled;
final boolean enabled;
- final boolean isScreenOn = getPowerManager().isInteractive();
+ final boolean isInteractive = getPowerManager().isInteractive();
final ArrayMap<String, String> fileValues;
synchronized (mLock) {
- Slog.i(TAG, "Battery saver enabled: screen on=" + isScreenOn);
+ Slog.i(TAG, "Battery saver " + (mEnabled ? "enabled" : "disabled")
+ + ": isInteractive=" + isInteractive);
listeners = mListeners.toArray(new LowPowerModeListener[mListeners.size()]);
- wasEnabled = mWasEnabled;
enabled = mEnabled;
if (enabled) {
- fileValues = mBatterySaverPolicy.getFileValues(isScreenOn);
+ fileValues = mBatterySaverPolicy.getFileValues(isInteractive);
} else {
fileValues = null;
}
}
- PowerManagerService.powerHintInternal(PowerHint.LOW_POWER, enabled ? 1 : 0);
+ final PowerManagerInternal pmi = LocalServices.getService(PowerManagerInternal.class);
+ if (pmi != null) {
+ pmi.powerHint(PowerHint.LOW_POWER, enabled ? 1 : 0);
+ }
if (enabled) {
// STOPSHIP Remove the toast.
@@ -195,13 +217,13 @@
Toast.LENGTH_LONG).show();
}
- if (fileValues == null || fileValues.size() == 0) {
+ if (ArrayUtils.isEmpty(fileValues)) {
mFileUpdater.restoreDefault();
} else {
mFileUpdater.writeFiles(fileValues);
}
- if (enabled != wasEnabled) {
+ if (sendBroadcast) {
if (DEBUG) {
Slog.i(TAG, "Sending broadcasts for mode: " + enabled);
}
@@ -231,9 +253,5 @@
listener.onLowPowerModeChanged(result);
}
}
-
- synchronized (mLock) {
- mWasEnabled = enabled;
- }
}
}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index e1edf11..dafab77 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -182,7 +182,7 @@
Slog.i(TAG, "StatsCompanionService noticed an app was updated.");
synchronized (sStatsdLock) {
if (sStatsd == null) {
- Slog.w(TAG, "Could not access statsd to inform it of anomaly alarm firing");
+ Slog.w(TAG, "Could not access statsd to inform it of an app update");
return;
}
try {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 723b888..ce34306 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -124,6 +124,7 @@
import android.app.ActivityThread;
import android.app.AppOpsManager;
import android.app.IActivityManager;
+import android.app.IAssistDataReceiver;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ContentResolver;
@@ -226,7 +227,6 @@
import android.view.inputmethod.InputMethodManagerInternal;
import com.android.internal.R;
-import com.android.internal.app.IAssistDataReceiver;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.internal.os.IResultReceiver;
import com.android.internal.policy.IKeyguardDismissCallback;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 74a7bd4a..33f4e34 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -35,6 +35,7 @@
import android.os.IIncidentManager;
import android.os.Looper;
import android.os.Message;
+import android.os.Parcel;
import android.os.PowerManager;
import android.os.Process;
import android.os.ServiceManager;
@@ -360,6 +361,9 @@
// to avoid throwing BadParcelableException.
BaseBundle.setShouldDefuse(true);
+ // Within the system server, when parceling exceptions, include the stack trace
+ Parcel.setStackTraceParceling(true);
+
// Ensure binder calls into the system always run at foreground priority.
BinderInternal.disableBackgroundScheduling(true);
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index f63d1e7..114929c 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -48,7 +48,7 @@
# TODO(b/69254249): Migrate to Robolectric 3.4.2
LOCAL_JAVA_LIBRARIES := \
junit \
- platform-robolectric-prebuilt
+ platform-robolectric-3.1.1-prebuilt
LOCAL_INSTRUMENTATION_FOR := FrameworksServicesLib
LOCAL_MODULE := FrameworksServicesRoboTests
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index 70e8a16..66f5770 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -144,7 +144,9 @@
// Use a Testable subclass so we can simulate calls from the system without failing.
private static class TestableNotificationManagerService extends NotificationManagerService {
- public TestableNotificationManagerService(Context context) { super(context); }
+ public TestableNotificationManagerService(Context context) {
+ super(context);
+ }
@Override
protected boolean isCallingUidSystem() {
@@ -160,6 +162,11 @@
protected ICompanionDeviceManager getCompanionManager() {
return null;
}
+
+ @Override
+ protected void reportSeen(NotificationRecord r) {
+ return;
+ }
}
@Before
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index fbb5fd2..afece5d 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -428,7 +428,8 @@
assertSecurityException(expectCallable, () -> mService.getTaskDescription(0));
assertSecurityException(expectCallable, () -> mService.cancelTaskWindowTransition(0));
assertSecurityException(expectCallable, () -> mService.cancelTaskThumbnailTransition(0));
- assertSecurityException(expectCallable, () -> mService.startRecentsActivity(null, null, 0));
+ assertSecurityException(expectCallable, () -> mService.startRecentsActivity(null, null,
+ null, 0));
}
private void testGetTasksApis(boolean expectCallable) {
diff --git a/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java b/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java
index f22dfdc..c7fd551 100644
--- a/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java
+++ b/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java
@@ -11,7 +11,6 @@
import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
-import android.content.pm.IPackageInstallObserver;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.InstantAppInfo;
import android.content.pm.InstrumentationInfo;
@@ -623,12 +622,6 @@
}
@Override
- public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
- String installerPackageName) {
-
- }
-
- @Override
public void installPackage(Uri packageURI, PackageInstallObserver observer, int flags,
String installerPackageName) {
diff --git a/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java b/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
index afe432b..467b47a 100644
--- a/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
@@ -37,7 +37,6 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
-import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;
@@ -57,10 +56,10 @@
* To run this test from root of checkout:
* <pre>
* mmm -j32 frameworks/base/services/tests/servicestests/
- * adb install out/target/product/marlin/data/app/JobTestApp/JobTestApp.apk
- * adb install out/target/product/marlin/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
+ * adb install -r $OUT/data/app/JobTestApp/JobTestApp.apk
+ * adb install -r $OUT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
* adb shell am instrument -e class 'com.android.server.job.BackgroundRestrictionsTest' -w \
- * 'com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner'
+ com.android.frameworks.servicestests
* </pre>
*/
@RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java b/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java
index 5b6225e..0db19e4 100644
--- a/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java
@@ -18,13 +18,13 @@
import android.os.PowerManager.ServiceType;
import android.os.PowerSaveState;
import android.os.Handler;
-import android.provider.Settings;
import android.provider.Settings.Global;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArrayMap;
import com.android.frameworks.servicestests.R;
+import com.android.internal.annotations.VisibleForTesting;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -68,6 +68,12 @@
int getDeviceSpecificConfigResId() {
return mDeviceSpecificConfigResId;
}
+
+
+ @VisibleForTesting
+ void onChange() {
+ onChange(true, null);
+ }
}
@Mock
@@ -221,14 +227,14 @@
mMockGlobalSettings.put(Global.BATTERY_SAVER_CONSTANTS, "");
mMockGlobalSettings.put(Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS, "");
- mBatterySaverPolicy.onChangeForTest();
+ mBatterySaverPolicy.onChange();
assertThat(mBatterySaverPolicy.getFileValues(true).toString()).isEqualTo("{}");
assertThat(mBatterySaverPolicy.getFileValues(false).toString()).isEqualTo("{}");
mDeviceSpecificConfigResId = R.string.config_batterySaverDeviceSpecificConfig_2;
- mBatterySaverPolicy.onChangeForTest();
+ mBatterySaverPolicy.onChange();
assertThat(mBatterySaverPolicy.getFileValues(true).toString()).isEqualTo("{}");
assertThat(mBatterySaverPolicy.getFileValues(false).toString())
.isEqualTo("{/sys/a=1, /sys/b=2}");
@@ -236,7 +242,7 @@
mDeviceSpecificConfigResId = R.string.config_batterySaverDeviceSpecificConfig_3;
- mBatterySaverPolicy.onChangeForTest();
+ mBatterySaverPolicy.onChange();
assertThat(mBatterySaverPolicy.getFileValues(true).toString()).isEqualTo("{/proc/c=4}");
assertThat(mBatterySaverPolicy.getFileValues(false).toString()).isEqualTo("{/sys/a=3}");
@@ -244,7 +250,7 @@
mMockGlobalSettings.put(Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS,
"file-on:/proc/z=4");
- mBatterySaverPolicy.onChangeForTest();
+ mBatterySaverPolicy.onChange();
assertThat(mBatterySaverPolicy.getFileValues(true).toString()).isEqualTo("{/proc/z=4}");
assertThat(mBatterySaverPolicy.getFileValues(false).toString()).isEqualTo("{}");
}
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 8531baf..baa3e05 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -17,6 +17,9 @@
package com.android.server.usage;
import static android.app.usage.AppStandby.*;
+import static android.app.usage.UsageEvents.Event.NOTIFICATION_SEEN;
+import static android.app.usage.UsageEvents.Event.USER_INTERACTION;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -247,21 +250,27 @@
false));
}
- private void reportEvent(AppStandbyController controller, long elapsedTime) {
+ private void reportEvent(AppStandbyController controller, int eventType,
+ long elapsedTime) {
// Back to ACTIVE on event
UsageEvents.Event ev = new UsageEvents.Event();
ev.mPackage = PACKAGE_1;
- ev.mEventType = UsageEvents.Event.USER_INTERACTION;
+ ev.mEventType = eventType;
controller.reportEvent(ev, elapsedTime, USER_ID);
}
+ private int getStandbyBucket(AppStandbyController controller) {
+ return controller.getAppStandbyBucket(PACKAGE_1, USER_ID, mInjector.mElapsedRealtime,
+ true);
+ }
+
@Test
public void testBuckets() throws Exception {
AppStandbyController controller = setupController();
assertTimeout(controller, 0, STANDBY_BUCKET_NEVER);
- reportEvent(controller, 0);
+ reportEvent(controller, USER_INTERACTION, 0);
// ACTIVE bucket
assertTimeout(controller, 11 * HOUR_MS, STANDBY_BUCKET_ACTIVE);
@@ -278,7 +287,7 @@
// RARE bucket
assertTimeout(controller, 9 * DAY_MS, STANDBY_BUCKET_RARE);
- reportEvent(controller, 9 * DAY_MS);
+ reportEvent(controller, USER_INTERACTION, 9 * DAY_MS);
assertTimeout(controller, 9 * DAY_MS, STANDBY_BUCKET_ACTIVE);
@@ -293,7 +302,7 @@
assertTimeout(controller, 0, STANDBY_BUCKET_NEVER);
- reportEvent(controller, 0);
+ reportEvent(controller, USER_INTERACTION, 0);
// ACTIVE bucket
assertTimeout(controller, 11 * HOUR_MS, STANDBY_BUCKET_ACTIVE);
@@ -304,9 +313,7 @@
// RARE bucket, should fail because the screen wasn't ON.
mInjector.mElapsedRealtime = 9 * DAY_MS;
controller.checkIdleStates(USER_ID);
- assertNotEquals(STANDBY_BUCKET_RARE,
- controller.getAppStandbyBucket(PACKAGE_1, USER_ID, mInjector.mElapsedRealtime,
- false));
+ assertNotEquals(STANDBY_BUCKET_RARE, getStandbyBucket(controller));
mInjector.setDisplayOn(true);
assertTimeout(controller, 18 * DAY_MS, STANDBY_BUCKET_RARE);
@@ -318,8 +325,7 @@
setChargingState(controller, false);
controller.forceIdleState(PACKAGE_1, USER_ID, true);
- assertEquals(STANDBY_BUCKET_RARE, controller.getAppStandbyBucket(PACKAGE_1, USER_ID, 0,
- true));
+ assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(controller));
assertTrue(controller.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
controller.forceIdleState(PACKAGE_1, USER_ID, false);
@@ -327,4 +333,20 @@
true));
assertFalse(controller.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
}
+
+ @Test
+ public void testNotificationEvent() throws Exception {
+ AppStandbyController controller = setupController();
+ setChargingState(controller, false);
+
+ reportEvent(controller, USER_INTERACTION, 0);
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(controller));
+ mInjector.mElapsedRealtime = 1;
+ reportEvent(controller, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(controller));
+
+ controller.forceIdleState(PACKAGE_1, USER_ID, true);
+ reportEvent(controller, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
+ assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(controller));
+ }
}
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index c5ca330..1e5eb05 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -186,7 +186,7 @@
writeScreenOnTime();
}
- public void reportUsage(String packageName, int userId, long elapsedRealtime) {
+ public int reportUsage(String packageName, int userId, long elapsedRealtime) {
ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
elapsedRealtime, true);
@@ -197,12 +197,33 @@
+ (elapsedRealtime - mElapsedSnapshot);
appUsageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
appUsageHistory.recent[HISTORY_SIZE - 1] = FLAG_LAST_STATE | FLAG_PARTIAL_ACTIVE;
- appUsageHistory.currentBucket = AppStandby.STANDBY_BUCKET_ACTIVE;
- appUsageHistory.bucketingReason = AppStandby.REASON_USAGE;
- if (DEBUG) {
- Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket
- + ", reason=" + appUsageHistory.bucketingReason);
+ if (appUsageHistory.currentBucket > STANDBY_BUCKET_ACTIVE) {
+ appUsageHistory.currentBucket = STANDBY_BUCKET_ACTIVE;
+ if (DEBUG) {
+ Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket
+ + ", reason=" + appUsageHistory.bucketingReason);
+ }
}
+ appUsageHistory.bucketingReason = AppStandby.REASON_USAGE;
+
+ return appUsageHistory.currentBucket;
+ }
+
+ public int reportMildUsage(String packageName, int userId, long elapsedRealtime) {
+ ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
+ AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
+ elapsedRealtime, true);
+ if (appUsageHistory.currentBucket > STANDBY_BUCKET_WORKING_SET) {
+ appUsageHistory.currentBucket = STANDBY_BUCKET_WORKING_SET;
+ if (DEBUG) {
+ Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket
+ + ", reason=" + appUsageHistory.bucketingReason);
+ }
+ }
+ // TODO: Should this be a different reason for partial usage?
+ appUsageHistory.bucketingReason = AppStandby.REASON_USAGE;
+
+ return appUsageHistory.currentBucket;
}
public void setIdle(String packageName, int userId, long elapsedRealtime) {
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 5623a68..97f7de2 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -229,6 +229,7 @@
// Get sync adapters for the authority
String[] packages = ContentResolver.getSyncAdapterPackagesForAuthorityAsUser(
authority, userId);
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
for (String packageName: packages) {
// Only force the sync adapters to active if the provider is not in the same package and
// the sync adapter is a system package.
@@ -239,7 +240,12 @@
continue;
}
if (!packageName.equals(providerPkgName)) {
- setAppIdleAsync(packageName, false, userId);
+ synchronized (mAppIdleLock) {
+ int newBucket = mAppIdleHistory.reportMildUsage(packageName, userId,
+ elapsedRealtime);
+ maybeInformListeners(packageName, userId, elapsedRealtime,
+ newBucket);
+ }
}
} catch (PackageManager.NameNotFoundException e) {
// Shouldn't happen
@@ -493,11 +499,21 @@
if ((event.mEventType == UsageEvents.Event.MOVE_TO_FOREGROUND
|| event.mEventType == UsageEvents.Event.MOVE_TO_BACKGROUND
|| event.mEventType == UsageEvents.Event.SYSTEM_INTERACTION
- || event.mEventType == UsageEvents.Event.USER_INTERACTION)) {
- mAppIdleHistory.reportUsage(event.mPackage, userId, elapsedRealtime);
+ || event.mEventType == UsageEvents.Event.USER_INTERACTION
+ || event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN)) {
+
+ final int newBucket;
+ if (event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN) {
+ newBucket = mAppIdleHistory.reportMildUsage(event.mPackage, userId,
+ elapsedRealtime);
+ } else {
+ newBucket = mAppIdleHistory.reportUsage(event.mPackage, userId,
+ elapsedRealtime);
+ }
+
+ maybeInformListeners(event.mPackage, userId, elapsedRealtime,
+ newBucket);
if (previouslyIdle) {
- maybeInformListeners(event.mPackage, userId, elapsedRealtime,
- AppStandby.STANDBY_BUCKET_ACTIVE);
notifyBatteryStats(event.mPackage, userId, false);
}
}
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 0b10590..f02221c 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -643,6 +643,8 @@
return "SHORTCUT_INVOCATION";
case UsageEvents.Event.CHOOSER_ACTION:
return "CHOOSER_ACTION";
+ case UsageEvents.Event.NOTIFICATION_SEEN:
+ return "NOTIFICATION_SEEN";
default:
return "UNKNOWN";
}
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index e13bd61..a07f2bb 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -855,6 +855,39 @@
*/
public static abstract class Callback {
/**
+ * @hide
+ */
+ @IntDef({HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_DEST_NOT_SUPPORTED,
+ HANDOVER_FAILURE_DEST_INVALID_PERM, HANDOVER_FAILURE_DEST_USER_REJECTED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface HandoverFailureErrors {}
+
+ /**
+ * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
+ * to handover the call rejects handover.
+ */
+ public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
+
+ /**
+ * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there is
+ * an error associated with unsupported handover.
+ */
+ public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2;
+
+ /**
+ * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
+ * are some permission errors associated with APIs doing handover.
+ */
+ public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3;
+
+ /**
+ * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when user
+ * rejects handover.
+ */
+ public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4;
+
+
+ /**
* Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
*
* @param call The {@code Call} invoking this method.
@@ -989,6 +1022,21 @@
* {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
*/
public void onRttInitiationFailure(Call call, int reason) {}
+
+ /**
+ * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
+ * has completed successfully.
+ * @param call The call which had initiated handover.
+ */
+ public void onHandoverComplete(Call call) {}
+
+ /**
+ * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
+ * has failed.
+ * @param call The call which had initiated handover.
+ * @param failureReason Error reason for failure
+ */
+ public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
}
/**
@@ -1367,6 +1415,24 @@
}
/**
+ * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
+ * by {@code toHandle}. The videoState specified indicates the desired video state after the
+ * handover.
+ * <p>
+ * A handover request is initiated by the user from one app to indicate a desire
+ * to handover a call to another.
+ *
+ * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
+ * this call to.
+ * @param videoState Indicates the video state desired after the handover.
+ * @param extras Bundle containing extra information to be passed to the
+ * {@link ConnectionService}
+ */
+ public void handoverTo(PhoneAccountHandle toHandle, int videoState, Bundle extras) {
+ mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
+ }
+
+ /**
* Terminate the RTT session on this call. The resulting state change will be notified via
* the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
*/
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index ffb5e93..2bb1c4e 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -1684,6 +1684,8 @@
// The internal telecom call ID associated with this connection.
private String mTelecomCallId;
+ // The PhoneAccountHandle associated with this connection.
+ private PhoneAccountHandle mPhoneAccountHandle;
private int mState = STATE_NEW;
private CallAudioState mCallAudioState;
private Uri mAddress;
@@ -3099,6 +3101,27 @@
}
/**
+ * Sets the {@link PhoneAccountHandle} associated with this connection.
+ *
+ * @hide
+ */
+ public void setPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) {
+ if (mPhoneAccountHandle != phoneAccountHandle) {
+ mPhoneAccountHandle = phoneAccountHandle;
+ notifyPhoneAccountChanged(phoneAccountHandle);
+ }
+ }
+
+ /**
+ * Returns the {@link PhoneAccountHandle} associated with this connection.
+ *
+ * @hide
+ */
+ public PhoneAccountHandle getPhoneAccountHandle() {
+ return mPhoneAccountHandle;
+ }
+
+ /**
* Sends an event associated with this {@code Connection} with associated event extras to the
* {@link InCallService}.
* <p>
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 35804f6..7e83306 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -1382,7 +1382,7 @@
connection.setTelecomCallId(callId);
if (connection.getState() != Connection.STATE_DISCONNECTED) {
- addConnection(callId, connection);
+ addConnection(request.getAccountHandle(), callId, connection);
}
Uri address = connection.getAddress();
@@ -1846,6 +1846,7 @@
mAdapter.setIsConferenced(connectionId, id);
}
}
+ onConferenceAdded(conference);
}
}
@@ -2033,6 +2034,43 @@
}
/**
+ * Called by Telecom on the initiating side of the handover to create an instance of a
+ * handover connection.
+ * @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
+ * ConnectionService which needs to handover the call.
+ * @param request Details about the call which needs to be handover.
+ * @return Connection object corresponding to the handover call.
+ */
+ public Connection onCreateOutgoingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
+ ConnectionRequest request) {
+ return null;
+ }
+
+ /**
+ * Called by Telecom on the receiving side of the handover to request the
+ * {@link ConnectionService} to create an instance of a handover connection.
+ * @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
+ * ConnectionService which needs to handover the call.
+ * @param request Details about the call which needs to be handover.
+ * @return {@link Connection} object corresponding to the handover call.
+ */
+ public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
+ ConnectionRequest request) {
+ return null;
+ }
+
+ /**
+ * Called by Telecom in response to a {@code TelecomManager#acceptHandover()}
+ * invocation which failed.
+ * @param request Details about the call which needs to be handover.
+ * @param error Reason for handover failure as defined in
+ * {@link android.telecom.Call.Callback#HANDOVER_FAILURE_DEST_INVALID_PERM}
+ */
+ public void onHandoverFailed(ConnectionRequest request, int error) {
+ return;
+ }
+
+ /**
* Create a {@code Connection} for a new unknown call. An unknown call is a call originating
* from the ConnectionService that was neither a user-initiated outgoing call, nor an incoming
* call created using
@@ -2056,6 +2094,30 @@
public void onConference(Connection connection1, Connection connection2) {}
/**
+ * Called when a connection is added.
+ * @hide
+ */
+ public void onConnectionAdded(Connection connection) {}
+
+ /**
+ * Called when a connection is removed.
+ * @hide
+ */
+ public void onConnectionRemoved(Connection connection) {}
+
+ /**
+ * Called when a conference is added.
+ * @hide
+ */
+ public void onConferenceAdded(Conference conference) {}
+
+ /**
+ * Called when a conference is removed.
+ * @hide
+ */
+ public void onConferenceRemoved(Conference conference) {}
+
+ /**
* Indicates that a remote conference has been created for existing {@link RemoteConnection}s.
* When this method is invoked, this {@link ConnectionService} should create its own
* representation of the conference call and send it to telecom using {@link #addConference}.
@@ -2122,16 +2184,18 @@
// prefix for a unique incremental call ID.
id = handle.getComponentName().getClassName() + "@" + getNextCallId();
}
- addConnection(id, connection);
+ addConnection(handle, id, connection);
return id;
}
- private void addConnection(String callId, Connection connection) {
+ private void addConnection(PhoneAccountHandle handle, String callId, Connection connection) {
connection.setTelecomCallId(callId);
mConnectionById.put(callId, connection);
mIdByConnection.put(connection, callId);
connection.addConnectionListener(mConnectionListener);
connection.setConnectionService(this);
+ connection.setPhoneAccountHandle(handle);
+ onConnectionAdded(connection);
}
/** {@hide} */
@@ -2143,6 +2207,7 @@
mConnectionById.remove(id);
mIdByConnection.remove(connection);
mAdapter.removeCall(id);
+ onConnectionRemoved(connection);
}
}
@@ -2179,6 +2244,8 @@
mConferenceById.remove(id);
mIdByConference.remove(conference);
mAdapter.removeCall(id);
+
+ onConferenceRemoved(conference);
}
}
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 9bf0467..4bc2a9b 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -435,4 +435,21 @@
} catch (RemoteException ignored) {
}
}
+
+
+ /**
+ * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
+ * by destAcct.
+ * @param callId The callId of the Call which calls this function.
+ * @param destAcct ConnectionService to which the call should be handed over.
+ * @param videoState The video state desired after the handover.
+ * @param extras Extra information to be passed to ConnectionService
+ */
+ public void handoverTo(String callId, PhoneAccountHandle destAcct, int videoState,
+ Bundle extras) {
+ try {
+ mAdapter.handoverTo(callId, destAcct, videoState, extras);
+ } catch (RemoteException ignored) {
+ }
+ }
}
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 691e7cf..74b9465 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -86,13 +86,11 @@
/**
* Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which
* indicates whether this {@link PhoneAccount} is capable of supporting a request to handover a
- * connection (see {@link android.telecom.Call#EVENT_REQUEST_HANDOVER}) to this
- * {@link PhoneAccount} from a {@link PhoneAccount} specifying
- * {@link #EXTRA_SUPPORTS_HANDOVER_FROM}.
+ * connection (see {@code android.telecom.Call#handoverTo()}) to this {@link PhoneAccount} from
+ * a {@link PhoneAccount} specifying {@link #EXTRA_SUPPORTS_HANDOVER_FROM}.
* <p>
* A handover request is initiated by the user from the default dialer app to indicate a desire
* to handover a call from one {@link PhoneAccount}/{@link ConnectionService} to another.
- * @hide
*/
public static final String EXTRA_SUPPORTS_HANDOVER_TO =
"android.telecom.extra.SUPPORTS_HANDOVER_TO";
@@ -113,12 +111,11 @@
* Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which
* indicates whether this {@link PhoneAccount} is capable of supporting a request to handover a
* connection from this {@link PhoneAccount} to another {@link PhoneAccount}.
- * (see {@link android.telecom.Call#EVENT_REQUEST_HANDOVER}) which specifies
+ * (see {@code android.telecom.Call#handoverTo()}) which specifies
* {@link #EXTRA_SUPPORTS_HANDOVER_TO}.
* <p>
* A handover request is initiated by the user from the default dialer app to indicate a desire
* to handover a call from one {@link PhoneAccount}/{@link ConnectionService} to another.
- * @hide
*/
public static final String EXTRA_SUPPORTS_HANDOVER_FROM =
"android.telecom.extra.SUPPORTS_HANDOVER_FROM";
@@ -132,7 +129,6 @@
* <p>
* By default, Self-Managed {@link PhoneAccount}s do not log their calls to the call log.
* Setting this extra to {@code true} provides a means for them to log their calls.
- * @hide
*/
public static final String EXTRA_LOG_SELF_MANAGED_CALLS =
"android.telecom.extra.LOG_SELF_MANAGED_CALLS";
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index f30d7bd..05480dc 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -1065,7 +1065,7 @@
*
* @param state The audio state of this {@code RemoteConnection}.
* @hide
- * @deprecated Use {@link #setCallAudioState(CallAudioState) instead.
+ * @deprecated Use {@link #setCallAudioState(CallAudioState)} instead.
*/
@SystemApi
@Deprecated
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 9e52c71..da32e0b 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1750,6 +1750,41 @@
return false;
}
+ /**
+ * Called from the recipient side of a handover to indicate a desire to accept the handover
+ * of an ongoing call to another {@link ConnectionService} identified by
+ * {@link PhoneAccountHandle} destAcct. For managed {@link ConnectionService}s, the specified
+ * {@link PhoneAccountHandle} must have been registered with {@link #registerPhoneAccount} and
+ * the user must have enabled the corresponding {@link PhoneAccount}. This can be checked using
+ * {@link #getPhoneAccount}. Self-managed {@link ConnectionService}s must have
+ * {@link android.Manifest.permission#MANAGE_OWN_CALLS} to handover a call to it.
+ * <p>
+ * Once invoked, this method will cause the system to bind to the {@link ConnectionService}
+ * associated with the {@link PhoneAccountHandle} destAcct and call
+ * (See {@link ConnectionService#onCreateIncomingHandoverConnection}).
+ * <p>
+ * For a managed {@link ConnectionService}, a {@link SecurityException} will be thrown if either
+ * the {@link PhoneAccountHandle} destAcct does not correspond to a registered
+ * {@link PhoneAccount} or the associated {@link PhoneAccount} is not currently enabled by the
+ * user.
+ * <p>
+ * For a self-managed {@link ConnectionService}, a {@link SecurityException} will be thrown if
+ * the calling app does not have {@link android.Manifest.permission#MANAGE_OWN_CALLS}.
+ *
+ * @param srcAddr The {@link android.net.Uri} of the ongoing call to handover to the caller’s
+ * {@link ConnectionService}.
+ * @param videoState Video state after the handover.
+ * @param destAcct The {@link PhoneAccountHandle} registered to the calling package.
+ */
+ public void acceptHandover(Uri srcAddr, int videoState, PhoneAccountHandle destAcct) {
+ try {
+ if (isServiceConnected()) {
+ getTelecomService().acceptHandover(srcAddr, videoState, destAcct);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException acceptHandover: " + e);
+ }
+ }
private ITelecomService getTelecomService() {
if (mTelecomServiceOverride != null) {
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index bce3392..23ac940 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -77,4 +77,7 @@
void stopRtt(String callId);
void setRttMode(String callId, int mode);
+
+ void handoverTo(String callId, in PhoneAccountHandle destAcct, int videoState,
+ in Bundle extras);
}
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 8ebac2c..3460754 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -274,4 +274,9 @@
* @see TelecomServiceImpl#waitOnHandler
*/
void waitOnHandlers();
+
+ /**
+ * @see TelecomServiceImpl#acceptHandover
+ */
+ void acceptHandover(in Uri srcAddr, int videoState, in PhoneAccountHandle destAcct);
}
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 4d7c71f..dc897a2 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -122,7 +122,10 @@
// If the mccStr is empty or unknown, set it as null.
mMccStr = null;
} else {
- throw new IllegalArgumentException("invalid MCC format");
+ // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
+ // after the bug got fixed.
+ mMccStr = null;
+ log("invalid MCC format: " + mccStr);
}
if (mncStr == null || mncStr.matches("^[0-9]{2,3}$")) {
@@ -131,7 +134,10 @@
// If the mncStr is empty or unknown, set it as null.
mMncStr = null;
} else {
- throw new IllegalArgumentException("invalid MNC format");
+ // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
+ // after the bug got fixed.
+ mMncStr = null;
+ log("invalid MNC format: " + mncStr);
}
mAlphaLong = alphal;
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index fd837fc..f234b0a 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -121,7 +121,10 @@
// If the mccStr is empty or unknown, set it as null.
mMccStr = null;
} else {
- throw new IllegalArgumentException("invalid MCC format");
+ // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
+ // after the bug got fixed.
+ mMccStr = null;
+ log("invalid MCC format: " + mccStr);
}
if (mncStr == null || mncStr.matches("^[0-9]{2,3}$")) {
@@ -130,7 +133,10 @@
// If the mncStr is empty or unknown, set it as null.
mMncStr = null;
} else {
- throw new IllegalArgumentException("invalid MNC format");
+ // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
+ // after the bug got fixed.
+ mMncStr = null;
+ log("invalid MNC format: " + mncStr);
}
mAlphaLong = alphal;
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 1597245..1a461f2 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -121,7 +121,10 @@
// If the mccStr is empty or unknown, set it as null.
mMccStr = null;
} else {
- throw new IllegalArgumentException("invalid MCC format");
+ // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
+ // after the bug got fixed.
+ mMccStr = null;
+ log("invalid MCC format: " + mccStr);
}
if (mncStr == null || mncStr.matches("^[0-9]{2,3}$")) {
@@ -130,13 +133,16 @@
// If the mncStr is empty or unknown, set it as null.
mMncStr = null;
} else {
- throw new IllegalArgumentException("invalid MNC format");
+ // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
+ // after the bug got fixed.
+ mMncStr = null;
+ log("invalid MNC format: " + mncStr);
}
mAlphaLong = alphal;
mAlphaShort = alphas;
}
-
+
private CellIdentityWcdma(CellIdentityWcdma cid) {
this(cid.mLac, cid.mCid, cid.mPsc, cid.mUarfcn, cid.mMccStr,
cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 2f39ddb..64cc7c1 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -28,6 +28,7 @@
import android.net.INetworkPolicyManager;
import android.net.Uri;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -446,7 +447,15 @@
* for #onSubscriptionsChanged to be invoked.
*/
public static class OnSubscriptionsChangedListener {
- private final Handler mHandler = new Handler() {
+ private class OnSubscriptionsChangedListenerHandler extends Handler {
+ OnSubscriptionsChangedListenerHandler() {
+ super();
+ }
+
+ OnSubscriptionsChangedListenerHandler(Looper looper) {
+ super(looper);
+ }
+
@Override
public void handleMessage(Message msg) {
if (DBG) {
@@ -454,7 +463,22 @@
}
OnSubscriptionsChangedListener.this.onSubscriptionsChanged();
}
- };
+ }
+
+ private final Handler mHandler;
+
+ public OnSubscriptionsChangedListener() {
+ mHandler = new OnSubscriptionsChangedListenerHandler();
+ }
+
+ /**
+ * Allow a listener to be created with a custom looper
+ * @param looper the looper that the underlining handler should run on
+ * @hide
+ */
+ public OnSubscriptionsChangedListener(Looper looper) {
+ mHandler = new OnSubscriptionsChangedListenerHandler(looper);
+ }
/**
* Callback invoked when there is any change to any SubscriptionInfo. Typically
diff --git a/test-mock/Android.mk b/test-mock/Android.mk
new file mode 100644
index 0000000..18da8b8
--- /dev/null
+++ b/test-mock/Android.mk
@@ -0,0 +1,144 @@
+#
+# Copyright (C) 2008 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+android_test_mock_source_files := $(call all-java-files-under, src/android/test/mock)
+
+# Build the repackaged.android.test.mock library
+# ==============================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := core-oj core-libart framework legacy-test
+
+LOCAL_JARJAR_RULES := $(LOCAL_PATH)/../legacy-test/jarjar-rules.txt
+
+LOCAL_MODULE:= repackaged.android.test.mock
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Build the android.test.mock library
+# ===================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
+
+LOCAL_MODULE:= android.test.mock
+
+include $(BUILD_JAVA_LIBRARY)
+
+# For unbundled build we'll use the prebuilt jar from prebuilts/sdk.
+ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
+
+# Generate the stub source files for android.test.mock.stubs
+# ==========================================================
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(android_test_mock_source_files)
+
+LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/src/android/test/mock
+
+ANDROID_TEST_MOCK_OUTPUT_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android.test.mock.stubs_intermediates/api.txt
+ANDROID_TEST_MOCK_OUTPUT_REMOVED_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android.test.mock.stubs_intermediates/removed.txt
+
+ANDROID_TEST_MOCK_API_FILE := $(LOCAL_PATH)/api/android-test-mock-current.txt
+ANDROID_TEST_MOCK_REMOVED_API_FILE := $(LOCAL_PATH)/api/android-test-mock-removed.txt
+
+LOCAL_DROIDDOC_OPTIONS:= \
+ -stubpackages android.test.mock \
+ -stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android.test.mock.stubs_intermediates/src \
+ -nodocs \
+ -api $(ANDROID_TEST_MOCK_OUTPUT_API_FILE) \
+ -removedApi $(ANDROID_TEST_MOCK_OUTPUT_REMOVED_API_FILE) \
+
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_MODULE := android-test-mock-api-stubs-gen
+
+include $(BUILD_DROIDDOC)
+
+# Remember the target that will trigger the code generation.
+android_test_mock_gen_stamp := $(full_target)
+
+# Add some additional dependencies
+$(ANDROID_TEST_MOCK_OUTPUT_API_FILE): $(full_target)
+$(ANDROID_TEST_MOCK_OUTPUT_REMOVED_API_FILE): $(full_target)
+
+# Build the android.test.mock.stubs library
+# =========================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := android.test.mock.stubs
+
+LOCAL_SOURCE_FILES_ALL_GENERATED := true
+
+# Make sure to run droiddoc first to generate the stub source files.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(android_test_mock_gen_stamp)
+android_test_mock_gen_stamp :=
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Archive a copy of the classes.jar in SDK build.
+$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.mock.stubs.jar)
+
+# Check that the android.test.mock.stubs library has not changed
+# ==============================================================
+
+# Check that the API we're building hasn't changed from the not-yet-released
+# SDK version.
+$(eval $(call check-api, \
+ check-android-test-mock-api-current, \
+ $(ANDROID_TEST_MOCK_API_FILE), \
+ $(ANDROID_TEST_MOCK_OUTPUT_API_FILE), \
+ $(ANDROID_TEST_MOCK_REMOVED_API_FILE), \
+ $(ANDROID_TEST_MOCK_OUTPUT_REMOVED_API_FILE), \
+ -error 2 -error 3 -error 4 -error 5 -error 6 \
+ -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \
+ -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \
+ -error 25 -error 26 -error 27, \
+ cat $(LOCAL_PATH)/api/apicheck_msg_android_test_mock.txt, \
+ check-android-test-mock-api, \
+ $(call doc-timestamp-for,android-test-mock-api-stubs-gen) \
+ ))
+
+.PHONY: check-android-test-mock-api
+checkapi: check-android-test-mock-api
+
+.PHONY: update-android-test-mock-api
+update-api: update-android-test-mock-api
+
+update-android-test-mock-api: $(ANDROID_TEST_MOCK_OUTPUT_API_FILE) | $(ACP)
+ @echo Copying current.txt
+ $(hide) $(ACP) $(ANDROID_TEST_MOCK_OUTPUT_API_FILE) $(ANDROID_TEST_MOCK_API_FILE)
+ @echo Copying removed.txt
+ $(hide) $(ACP) $(ANDROID_TEST_MOCK_OUTPUT_REMOVED_API_FILE) $(ANDROID_TEST_MOCK_REMOVED_API_FILE)
+
+# Build the android.test.mock.sdk library
+# =======================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := android.test.mock.sdk
+LOCAL_SDK_VERSION := current
+
+LOCAL_STATIC_JAVA_LIBRARIES := android.test.mock.stubs
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+endif # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true
diff --git a/test-runner/api/android-test-mock-current.txt b/test-mock/api/android-test-mock-current.txt
similarity index 99%
rename from test-runner/api/android-test-mock-current.txt
rename to test-mock/api/android-test-mock-current.txt
index 93bbf6c..07fcee2 100644
--- a/test-runner/api/android-test-mock-current.txt
+++ b/test-mock/api/android-test-mock-current.txt
@@ -344,7 +344,6 @@
method public int installExistingPackage(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
method public int installExistingPackage(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public int installExistingPackageAsUser(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
- method public void installPackage(android.net.Uri, android.content.pm.IPackageInstallObserver, int, java.lang.String);
method public void installPackage(android.net.Uri, android.app.PackageInstallObserver, int, java.lang.String);
method public boolean isInstantApp();
method public boolean isInstantApp(java.lang.String);
diff --git a/test-runner/api/android-test-mock-removed.txt b/test-mock/api/android-test-mock-removed.txt
similarity index 100%
rename from test-runner/api/android-test-mock-removed.txt
rename to test-mock/api/android-test-mock-removed.txt
diff --git a/test-runner/api/apicheck_msg_android_test_mock.txt b/test-mock/api/apicheck_msg_android_test_mock.txt
similarity index 100%
rename from test-runner/api/apicheck_msg_android_test_mock.txt
rename to test-mock/api/apicheck_msg_android_test_mock.txt
diff --git a/test-runner/src/android/test/mock/MockApplication.java b/test-mock/src/android/test/mock/MockApplication.java
similarity index 100%
rename from test-runner/src/android/test/mock/MockApplication.java
rename to test-mock/src/android/test/mock/MockApplication.java
diff --git a/test-runner/src/android/test/mock/MockContentProvider.java b/test-mock/src/android/test/mock/MockContentProvider.java
similarity index 100%
rename from test-runner/src/android/test/mock/MockContentProvider.java
rename to test-mock/src/android/test/mock/MockContentProvider.java
diff --git a/test-runner/src/android/test/mock/MockContentResolver.java b/test-mock/src/android/test/mock/MockContentResolver.java
similarity index 100%
rename from test-runner/src/android/test/mock/MockContentResolver.java
rename to test-mock/src/android/test/mock/MockContentResolver.java
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
similarity index 100%
rename from test-runner/src/android/test/mock/MockContext.java
rename to test-mock/src/android/test/mock/MockContext.java
diff --git a/test-runner/src/android/test/mock/MockCursor.java b/test-mock/src/android/test/mock/MockCursor.java
similarity index 100%
rename from test-runner/src/android/test/mock/MockCursor.java
rename to test-mock/src/android/test/mock/MockCursor.java
diff --git a/test-runner/src/android/test/mock/MockDialogInterface.java b/test-mock/src/android/test/mock/MockDialogInterface.java
similarity index 100%
rename from test-runner/src/android/test/mock/MockDialogInterface.java
rename to test-mock/src/android/test/mock/MockDialogInterface.java
diff --git a/test-runner/src/android/test/mock/MockIContentProvider.java b/test-mock/src/android/test/mock/MockIContentProvider.java
similarity index 100%
rename from test-runner/src/android/test/mock/MockIContentProvider.java
rename to test-mock/src/android/test/mock/MockIContentProvider.java
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-mock/src/android/test/mock/MockPackageManager.java
similarity index 98%
rename from test-runner/src/android/test/mock/MockPackageManager.java
rename to test-mock/src/android/test/mock/MockPackageManager.java
index 7e08f51..0c562e6 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-mock/src/android/test/mock/MockPackageManager.java
@@ -26,12 +26,11 @@
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ChangedPackages;
-import android.content.pm.InstantAppInfo;
import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
-import android.content.pm.IPackageInstallObserver;
import android.content.pm.IPackageStatsObserver;
+import android.content.pm.InstantAppInfo;
import android.content.pm.InstrumentationInfo;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.KeySet;
@@ -653,15 +652,6 @@
throw new UnsupportedOperationException();
}
- /**
- * @hide - to match hiding in superclass
- */
- @Override
- public void installPackage(Uri packageURI, IPackageInstallObserver observer,
- int flags, String installerPackageName) {
- throw new UnsupportedOperationException();
- }
-
@Override
public void setInstallerPackageName(String targetPackage,
String installerPackageName) {
diff --git a/test-runner/src/android/test/mock/MockResources.java b/test-mock/src/android/test/mock/MockResources.java
similarity index 100%
rename from test-runner/src/android/test/mock/MockResources.java
rename to test-mock/src/android/test/mock/MockResources.java
diff --git a/test-runner/src/android/test/mock/package.html b/test-mock/src/android/test/mock/package.html
similarity index 100%
rename from test-runner/src/android/test/mock/package.html
rename to test-mock/src/android/test/mock/package.html
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index 3367aba..d0f5b32 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -16,14 +16,11 @@
LOCAL_PATH:= $(call my-dir)
-android_test_mock_source_files := $(call all-java-files-under, src/android/test/mock)
-
# Build the android.test.runner library
# =====================================
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := \
- $(filter-out $(android_test_mock_source_files), $(call all-java-files-under, src))
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_JAVA_LIBRARIES := \
core-oj \
@@ -42,7 +39,12 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework legacy-test
+LOCAL_JAVA_LIBRARIES := \
+ core-oj \
+ core-libart \
+ framework \
+ legacy-test \
+ android.test.mock \
LOCAL_JARJAR_RULES := $(LOCAL_PATH)/../legacy-test/jarjar-rules.txt
@@ -57,10 +59,7 @@
# ============================================================
include $(CLEAR_VARS)
-# Exclude android.test.mock classes as stubs for them are created in the
-# android.test.mock.stubs target
-LOCAL_SRC_FILES := \
- $(filter-out $(android_test_mock_source_files), $(call all-java-files-under, src))
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_JAVA_LIBRARIES := \
core-oj \
@@ -153,117 +152,3 @@
$(hide) $(ACP) $(ANDROID_TEST_RUNNER_OUTPUT_REMOVED_API_FILE) $(ANDROID_TEST_RUNNER_REMOVED_API_FILE)
endif # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true
-
-# Build the android.test.mock library
-# ===================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(android_test_mock_source_files)
-
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
-
-LOCAL_MODULE:= android.test.mock
-
-include $(BUILD_JAVA_LIBRARY)
-
-# For unbundled build we'll use the prebuilt jar from prebuilts/sdk.
-ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
-
-# Generate the stub source files for android.test.mock.stubs
-# ==========================================================
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(android_test_mock_source_files)
-
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/src/android/test/mock
-
-ANDROID_TEST_MOCK_OUTPUT_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android.test.mock.stubs_intermediates/api.txt
-ANDROID_TEST_MOCK_OUTPUT_REMOVED_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android.test.mock.stubs_intermediates/removed.txt
-
-ANDROID_TEST_MOCK_API_FILE := $(LOCAL_PATH)/api/android-test-mock-current.txt
-ANDROID_TEST_MOCK_REMOVED_API_FILE := $(LOCAL_PATH)/api/android-test-mock-removed.txt
-
-LOCAL_DROIDDOC_OPTIONS:= \
- -stubpackages android.test.mock \
- -stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android.test.mock.stubs_intermediates/src \
- -nodocs \
- -api $(ANDROID_TEST_MOCK_OUTPUT_API_FILE) \
- -removedApi $(ANDROID_TEST_MOCK_OUTPUT_REMOVED_API_FILE) \
-
-LOCAL_UNINSTALLABLE_MODULE := true
-LOCAL_MODULE := android-test-mock-api-stubs-gen
-
-include $(BUILD_DROIDDOC)
-
-# Remember the target that will trigger the code generation.
-android_test_mock_gen_stamp := $(full_target)
-
-# Add some additional dependencies
-$(ANDROID_TEST_MOCK_OUTPUT_API_FILE): $(full_target)
-$(ANDROID_TEST_MOCK_OUTPUT_REMOVED_API_FILE): $(full_target)
-
-# Build the android.test.mock.stubs library
-# =========================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := android.test.mock.stubs
-
-LOCAL_SOURCE_FILES_ALL_GENERATED := true
-
-# Make sure to run droiddoc first to generate the stub source files.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(android_test_mock_gen_stamp)
-android_test_mock_gen_stamp :=
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# Archive a copy of the classes.jar in SDK build.
-$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.mock.stubs.jar)
-
-# Check that the android.test.mock.stubs library has not changed
-# ==============================================================
-
-# Check that the API we're building hasn't changed from the not-yet-released
-# SDK version.
-$(eval $(call check-api, \
- check-android-test-mock-api-current, \
- $(ANDROID_TEST_MOCK_API_FILE), \
- $(ANDROID_TEST_MOCK_OUTPUT_API_FILE), \
- $(ANDROID_TEST_MOCK_REMOVED_API_FILE), \
- $(ANDROID_TEST_MOCK_OUTPUT_REMOVED_API_FILE), \
- -error 2 -error 3 -error 4 -error 5 -error 6 \
- -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \
- -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \
- -error 25 -error 26 -error 27, \
- cat $(LOCAL_PATH)/api/apicheck_msg_android_test_mock.txt, \
- check-android-test-mock-api, \
- $(call doc-timestamp-for,android-test-mock-api-stubs-gen) \
- ))
-
-.PHONY: check-android-test-mock-api
-checkapi: check-android-test-mock-api
-
-.PHONY: update-android-test-mock-api
-update-api: update-android-test-mock-api
-
-update-android-test-mock-api: $(ANDROID_TEST_MOCK_OUTPUT_API_FILE) | $(ACP)
- @echo Copying current.txt
- $(hide) $(ACP) $(ANDROID_TEST_MOCK_OUTPUT_API_FILE) $(ANDROID_TEST_MOCK_API_FILE)
- @echo Copying removed.txt
- $(hide) $(ACP) $(ANDROID_TEST_MOCK_OUTPUT_REMOVED_API_FILE) $(ANDROID_TEST_MOCK_REMOVED_API_FILE)
-
-# Build the android.test.mock.sdk library
-# =======================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := android.test.mock.sdk
-LOCAL_SDK_VERSION := current
-
-LOCAL_STATIC_JAVA_LIBRARIES := android.test.mock.stubs
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# additionally, build unit tests in a separate .apk
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
-endif # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index 08efc27..0f6fb50 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -218,6 +218,7 @@
if (attr.id) {
printer_->Print(attr.id.value().to_string());
}
+ printer_->Println();
}
}
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 96a0203..6fcf0f6 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -268,6 +268,11 @@
return out << res_id.to_string();
}
+// For generic code to call 'using std::to_string; to_string(T);'.
+inline std::string to_string(const ResourceId& id) {
+ return id.to_string();
+}
+
//
// ResourceType implementation.
//
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 66b5a7a..e94c0b4 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -16,7 +16,6 @@
#include <sys/stat.h>
-#include <fstream>
#include <queue>
#include <unordered_map>
#include <vector>
@@ -212,6 +211,8 @@
// This delegate will attempt to masquerade any '@id/' references with ID 0xPPTTEEEE,
// where PP > 7f, as 0x7fPPEEEE. Any potential overlapping is verified and an error occurs if such
// an overlap exists.
+//
+// See b/37498913.
class FeatureSplitSymbolTableDelegate : public DefaultSymbolTableDelegate {
public:
FeatureSplitSymbolTableDelegate(IAaptContext* context) : context_(context) {
@@ -652,24 +653,26 @@
static bool WriteStableIdMapToPath(IDiagnostics* diag,
const std::unordered_map<ResourceName, ResourceId>& id_map,
const std::string& id_map_path) {
- std::ofstream fout(id_map_path, std::ofstream::binary);
- if (!fout) {
- diag->Error(DiagMessage(id_map_path) << strerror(errno));
+ io::FileOutputStream fout(id_map_path);
+ if (fout.HadError()) {
+ diag->Error(DiagMessage(id_map_path) << "failed to open: " << fout.GetError());
return false;
}
+ text::Printer printer(&fout);
for (const auto& entry : id_map) {
const ResourceName& name = entry.first;
const ResourceId& id = entry.second;
- fout << name << " = " << id << "\n";
+ printer.Print(name.to_string());
+ printer.Print(" = ");
+ printer.Println(id.to_string());
}
+ fout.Flush();
- if (!fout) {
- diag->Error(DiagMessage(id_map_path) << "failed writing to file: "
- << android::base::SystemErrorCodeToString(errno));
+ if (fout.HadError()) {
+ diag->Error(DiagMessage(id_map_path) << "failed writing to file: " << fout.GetError());
return false;
}
-
return true;
}
@@ -985,36 +988,35 @@
file::AppendPath(&out_path, "R.java");
- std::ofstream fout(out_path, std::ofstream::binary);
- if (!fout) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed writing to '" << out_path
- << "': " << android::base::SystemErrorCodeToString(errno));
+ io::FileOutputStream fout(out_path);
+ if (fout.HadError()) {
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path
+ << "': " << fout.GetError());
return false;
}
- std::unique_ptr<std::ofstream> fout_text;
+ std::unique_ptr<io::FileOutputStream> fout_text;
if (out_text_symbols_path) {
- fout_text =
- util::make_unique<std::ofstream>(out_text_symbols_path.value(), std::ofstream::binary);
- if (!*fout_text) {
- context_->GetDiagnostics()->Error(
- DiagMessage() << "failed writing to '" << out_text_symbols_path.value()
- << "': " << android::base::SystemErrorCodeToString(errno));
+ fout_text = util::make_unique<io::FileOutputStream>(out_text_symbols_path.value());
+ if (fout_text->HadError()) {
+ context_->GetDiagnostics()->Error(DiagMessage()
+ << "failed writing to '" << out_text_symbols_path.value()
+ << "': " << fout_text->GetError());
return false;
}
}
JavaClassGenerator generator(context_, table, java_options);
if (!generator.Generate(package_name_to_generate, out_package, &fout, fout_text.get())) {
- context_->GetDiagnostics()->Error(DiagMessage(out_path) << generator.getError());
+ context_->GetDiagnostics()->Error(DiagMessage(out_path) << generator.GetError());
return false;
}
- if (!fout) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed writing to '" << out_path
- << "': " << android::base::SystemErrorCodeToString(errno));
+ fout.Flush();
+
+ if (fout.HadError()) {
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path
+ << "': " << fout.GetError());
return false;
}
return true;
@@ -1142,18 +1144,19 @@
file::AppendPath(&out_path, "Manifest.java");
- std::ofstream fout(out_path, std::ofstream::binary);
- if (!fout) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed writing to '" << out_path
- << "': " << android::base::SystemErrorCodeToString(errno));
+ io::FileOutputStream fout(out_path);
+ if (fout.HadError()) {
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed to open '" << out_path
+ << "': " << fout.GetError());
return false;
}
- if (!ClassDefinition::WriteJavaFile(manifest_class.get(), package_utf8, true, &fout)) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed writing to '" << out_path
- << "': " << android::base::SystemErrorCodeToString(errno));
+ ClassDefinition::WriteJavaFile(manifest_class.get(), package_utf8, true, &fout);
+ fout.Flush();
+
+ if (fout.HadError()) {
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path
+ << "': " << fout.GetError());
return false;
}
return true;
@@ -1165,19 +1168,19 @@
}
const std::string& out_path = out.value();
- std::ofstream fout(out_path, std::ofstream::binary);
- if (!fout) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed to open '" << out_path
- << "': " << android::base::SystemErrorCodeToString(errno));
+ io::FileOutputStream fout(out_path);
+ if (fout.HadError()) {
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed to open '" << out_path
+ << "': " << fout.GetError());
return false;
}
- proguard::WriteKeepSet(&fout, keep_set);
- if (!fout) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed writing to '" << out_path
- << "': " << android::base::SystemErrorCodeToString(errno));
+ proguard::WriteKeepSet(keep_set, &fout);
+ fout.Flush();
+
+ if (fout.HadError()) {
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path
+ << "': " << fout.GetError());
return false;
}
return true;
diff --git a/tools/aapt2/io/FileStream.cpp b/tools/aapt2/io/FileStream.cpp
index 4ff6d78..27529bc 100644
--- a/tools/aapt2/io/FileStream.cpp
+++ b/tools/aapt2/io/FileStream.cpp
@@ -25,6 +25,12 @@
#include "android-base/macros.h"
#include "android-base/utf8.h"
+#if defined(_WIN32)
+// This is only needed for O_CLOEXEC.
+#include <windows.h>
+#define O_CLOEXEC O_NOINHERIT
+#endif
+
using ::android::base::SystemErrorCodeToString;
using ::android::base::unique_fd;
@@ -32,18 +38,20 @@
namespace io {
FileInputStream::FileInputStream(const std::string& path, size_t buffer_capacity)
- : FileInputStream(::android::base::utf8::open(path.c_str(), O_RDONLY | O_BINARY),
- buffer_capacity) {
+ : buffer_capacity_(buffer_capacity) {
+ int mode = O_RDONLY | O_CLOEXEC | O_BINARY;
+ fd_.reset(TEMP_FAILURE_RETRY(::android::base::utf8::open(path.c_str(), mode)));
+ if (fd_ == -1) {
+ error_ = SystemErrorCodeToString(errno);
+ } else {
+ buffer_.reset(new uint8_t[buffer_capacity_]);
+ }
}
FileInputStream::FileInputStream(int fd, size_t buffer_capacity)
- : fd_(fd),
- buffer_capacity_(buffer_capacity),
- buffer_offset_(0u),
- buffer_size_(0u),
- total_byte_count_(0u) {
- if (fd_ == -1) {
- error_ = SystemErrorCodeToString(errno);
+ : fd_(fd), buffer_capacity_(buffer_capacity) {
+ if (fd_ < 0) {
+ error_ = "Bad File Descriptor";
} else {
buffer_.reset(new uint8_t[buffer_capacity_]);
}
@@ -100,9 +108,16 @@
return error_;
}
-FileOutputStream::FileOutputStream(const std::string& path, int mode, size_t buffer_capacity)
- : FileOutputStream(unique_fd(::android::base::utf8::open(path.c_str(), mode)),
- buffer_capacity) {
+FileOutputStream::FileOutputStream(const std::string& path, size_t buffer_capacity)
+ : buffer_capacity_(buffer_capacity) {
+ int mode = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY;
+ owned_fd_.reset(TEMP_FAILURE_RETRY(::android::base::utf8::open(path.c_str(), mode, 0666)));
+ fd_ = owned_fd_.get();
+ if (fd_ < 0) {
+ error_ = SystemErrorCodeToString(errno);
+ } else {
+ buffer_.reset(new uint8_t[buffer_capacity_]);
+ }
}
FileOutputStream::FileOutputStream(unique_fd fd, size_t buffer_capacity)
@@ -111,9 +126,9 @@
}
FileOutputStream::FileOutputStream(int fd, size_t buffer_capacity)
- : fd_(fd), buffer_capacity_(buffer_capacity), buffer_offset_(0u), total_byte_count_(0u) {
- if (fd_ == -1) {
- error_ = SystemErrorCodeToString(errno);
+ : fd_(fd), buffer_capacity_(buffer_capacity) {
+ if (fd_ < 0) {
+ error_ = "Bad File Descriptor";
} else {
buffer_.reset(new uint8_t[buffer_capacity_]);
}
diff --git a/tools/aapt2/io/FileStream.h b/tools/aapt2/io/FileStream.h
index 4ed1ad5..62d910f 100644
--- a/tools/aapt2/io/FileStream.h
+++ b/tools/aapt2/io/FileStream.h
@@ -22,7 +22,6 @@
#include <memory>
#include <string>
-#include "android-base/file.h" // for O_BINARY
#include "android-base/macros.h"
#include "android-base/unique_fd.h"
@@ -55,15 +54,15 @@
android::base::unique_fd fd_;
std::string error_;
std::unique_ptr<uint8_t[]> buffer_;
- size_t buffer_capacity_;
- size_t buffer_offset_;
- size_t buffer_size_;
- size_t total_byte_count_;
+ size_t buffer_capacity_ = 0u;
+ size_t buffer_offset_ = 0u;
+ size_t buffer_size_ = 0u;
+ size_t total_byte_count_ = 0u;
};
class FileOutputStream : public OutputStream {
public:
- explicit FileOutputStream(const std::string& path, int mode = O_RDWR | O_CREAT | O_BINARY,
+ explicit FileOutputStream(const std::string& path,
size_t buffer_capacity = kDefaultBufferCapacity);
// Does not take ownership of `fd`.
@@ -97,9 +96,9 @@
int fd_;
std::string error_;
std::unique_ptr<uint8_t[]> buffer_;
- size_t buffer_capacity_;
- size_t buffer_offset_;
- size_t total_byte_count_;
+ size_t buffer_capacity_ = 0u;
+ size_t buffer_offset_ = 0u;
+ size_t total_byte_count_ = 0u;
};
} // namespace io
diff --git a/tools/aapt2/io/FileStream_test.cpp b/tools/aapt2/io/FileStream_test.cpp
index a6d58ca..c0eaa8e 100644
--- a/tools/aapt2/io/FileStream_test.cpp
+++ b/tools/aapt2/io/FileStream_test.cpp
@@ -16,6 +16,7 @@
#include "io/FileStream.h"
+#include "android-base/file.h"
#include "android-base/macros.h"
#include "android-base/test_utils.h"
diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp
index c93461a..8d91b00 100644
--- a/tools/aapt2/java/AnnotationProcessor.cpp
+++ b/tools/aapt2/java/AnnotationProcessor.cpp
@@ -23,6 +23,7 @@
#include "text/Utf8Iterator.h"
#include "util/Util.h"
+using ::aapt::text::Printer;
using ::aapt::text::Utf8Iterator;
using ::android::StringPiece;
@@ -109,23 +110,22 @@
}
}
-void AnnotationProcessor::WriteToStream(const StringPiece& prefix, std::ostream* out) const {
+void AnnotationProcessor::Print(Printer* printer) const {
if (has_comments_) {
std::string result = comment_.str();
for (StringPiece line : util::Tokenize(result, '\n')) {
- *out << prefix << line << "\n";
+ printer->Println(line);
}
- *out << prefix << " */"
- << "\n";
+ printer->Println(" */");
}
if (annotation_bit_mask_ & AnnotationRule::kDeprecated) {
- *out << prefix << "@Deprecated\n";
+ printer->Println("@Deprecated");
}
for (const AnnotationRule& rule : sAnnotationRules) {
if (annotation_bit_mask_ & rule.bit_mask) {
- *out << prefix << rule.annotation << "\n";
+ printer->Println(rule.annotation);
}
}
}
diff --git a/tools/aapt2/java/AnnotationProcessor.h b/tools/aapt2/java/AnnotationProcessor.h
index a7bf73f..ae7bdb0 100644
--- a/tools/aapt2/java/AnnotationProcessor.h
+++ b/tools/aapt2/java/AnnotationProcessor.h
@@ -22,6 +22,8 @@
#include "androidfw/StringPiece.h"
+#include "text/Printer.h"
+
namespace aapt {
// Builds a JavaDoc comment from a set of XML comments.
@@ -61,8 +63,8 @@
void AppendNewLine();
- // Writes the comments and annotations to the stream, with the given prefix before each line.
- void WriteToStream(const android::StringPiece& prefix, std::ostream* out) const;
+ // Writes the comments and annotations to the Printer.
+ void Print(text::Printer* printer) const;
private:
std::stringstream comment_;
diff --git a/tools/aapt2/java/AnnotationProcessor_test.cpp b/tools/aapt2/java/AnnotationProcessor_test.cpp
index 856f4cc..69f49c8 100644
--- a/tools/aapt2/java/AnnotationProcessor_test.cpp
+++ b/tools/aapt2/java/AnnotationProcessor_test.cpp
@@ -16,8 +16,12 @@
#include "java/AnnotationProcessor.h"
+#include "io/StringStream.h"
#include "test/Test.h"
+#include "text/Printer.h"
+using ::aapt::io::StringOutputStream;
+using ::aapt::text::Printer;
using ::testing::Eq;
using ::testing::HasSubstr;
using ::testing::Not;
@@ -33,9 +37,11 @@
AnnotationProcessor processor;
processor.AppendComment(comment);
- std::stringstream result;
- processor.WriteToStream("", &result);
- std::string annotations = result.str();
+ std::string annotations;
+ StringOutputStream out(&annotations);
+ Printer printer(&out);
+ processor.Print(&printer);
+ out.Flush();
EXPECT_THAT(annotations, HasSubstr("@Deprecated"));
}
@@ -44,9 +50,11 @@
AnnotationProcessor processor;
processor.AppendComment("@SystemApi This is a system API");
- std::stringstream result;
- processor.WriteToStream("", &result);
- std::string annotations = result.str();
+ std::string annotations;
+ StringOutputStream out(&annotations);
+ Printer printer(&out);
+ processor.Print(&printer);
+ out.Flush();
EXPECT_THAT(annotations, HasSubstr("@android.annotation.SystemApi"));
EXPECT_THAT(annotations, Not(HasSubstr("@SystemApi")));
@@ -57,9 +65,11 @@
AnnotationProcessor processor;
processor.AppendComment("@TestApi This is a test API");
- std::stringstream result;
- processor.WriteToStream("", &result);
- std::string annotations = result.str();
+ std::string annotations;
+ StringOutputStream out(&annotations);
+ Printer printer(&out);
+ processor.Print(&printer);
+ out.Flush();
EXPECT_THAT(annotations, HasSubstr("@android.annotation.TestApi"));
EXPECT_THAT(annotations, Not(HasSubstr("@TestApi")));
diff --git a/tools/aapt2/java/ClassDefinition.cpp b/tools/aapt2/java/ClassDefinition.cpp
index 0c57e7e..b692ccf 100644
--- a/tools/aapt2/java/ClassDefinition.cpp
+++ b/tools/aapt2/java/ClassDefinition.cpp
@@ -18,25 +18,27 @@
#include "androidfw/StringPiece.h"
+using ::aapt::text::Printer;
using ::android::StringPiece;
namespace aapt {
-void ClassMember::WriteToStream(const StringPiece& prefix, bool final, std::ostream* out) const {
- processor_.WriteToStream(prefix, out);
+void ClassMember::Print(bool /*final*/, Printer* printer) const {
+ processor_.Print(printer);
}
void MethodDefinition::AppendStatement(const StringPiece& statement) {
statements_.push_back(statement.to_string());
}
-void MethodDefinition::WriteToStream(const StringPiece& prefix, bool final,
- std::ostream* out) const {
- *out << prefix << signature_ << " {\n";
+void MethodDefinition::Print(bool final, Printer* printer) const {
+ printer->Print(signature_).Println(" {");
+ printer->Indent();
for (const auto& statement : statements_) {
- *out << prefix << " " << statement << "\n";
+ printer->Println(statement);
}
- *out << prefix << "}";
+ printer->Undent();
+ printer->Print("}");
}
ClassDefinition::Result ClassDefinition::AddMember(std::unique_ptr<ClassMember> member) {
@@ -62,34 +64,32 @@
return true;
}
-void ClassDefinition::WriteToStream(const StringPiece& prefix, bool final,
- std::ostream* out) const {
+void ClassDefinition::Print(bool final, Printer* printer) const {
if (empty() && !create_if_empty_) {
return;
}
- ClassMember::WriteToStream(prefix, final, out);
+ ClassMember::Print(final, printer);
- *out << prefix << "public ";
+ printer->Print("public ");
if (qualifier_ == ClassQualifier::kStatic) {
- *out << "static ";
+ printer->Print("static ");
}
- *out << "final class " << name_ << " {\n";
-
- std::string new_prefix = prefix.to_string();
- new_prefix.append(kIndent);
+ printer->Print("final class ").Print(name_).Println(" {");
+ printer->Indent();
for (const std::unique_ptr<ClassMember>& member : ordered_members_) {
// There can be nullptr members when a member is added to the ClassDefinition
// and takes precedence over a previous member with the same name. The overridden member is
// set to nullptr.
if (member != nullptr) {
- member->WriteToStream(new_prefix, final, out);
- *out << "\n";
+ member->Print(final, printer);
+ printer->Println();
}
}
- *out << prefix << "}";
+ printer->Undent();
+ printer->Print("}");
}
constexpr static const char* sWarningHeader =
@@ -100,11 +100,12 @@
" * should not be modified by hand.\n"
" */\n\n";
-bool ClassDefinition::WriteJavaFile(const ClassDefinition* def, const StringPiece& package,
- bool final, std::ostream* out) {
- *out << sWarningHeader << "package " << package << ";\n\n";
- def->WriteToStream("", final, out);
- return bool(*out);
+void ClassDefinition::WriteJavaFile(const ClassDefinition* def, const StringPiece& package,
+ bool final, io::OutputStream* out) {
+ Printer printer(out);
+ printer.Print(sWarningHeader).Print("package ").Print(package).Println(";");
+ printer.Println();
+ def->Print(final, &printer);
}
} // namespace aapt
diff --git a/tools/aapt2/java/ClassDefinition.h b/tools/aapt2/java/ClassDefinition.h
index 28a3489..fb11266 100644
--- a/tools/aapt2/java/ClassDefinition.h
+++ b/tools/aapt2/java/ClassDefinition.h
@@ -17,7 +17,6 @@
#ifndef AAPT_JAVA_CLASSDEFINITION_H
#define AAPT_JAVA_CLASSDEFINITION_H
-#include <ostream>
#include <string>
#include <unordered_map>
#include <vector>
@@ -27,6 +26,7 @@
#include "Resource.h"
#include "java/AnnotationProcessor.h"
+#include "text/Printer.h"
#include "util/Util.h"
namespace aapt {
@@ -47,11 +47,10 @@
virtual const std::string& GetName() const = 0;
- // Writes the class member to the out stream. Subclasses should derive this method
+ // Writes the class member to the Printer. Subclasses should derive this method
// to write their own data. Call this base method from the subclass to write out
// this member's comments/annotations.
- virtual void WriteToStream(const android::StringPiece& prefix, bool final,
- std::ostream* out) const;
+ virtual void Print(bool final, text::Printer* printer) const;
private:
AnnotationProcessor processor_;
@@ -71,11 +70,16 @@
return name_;
}
- void WriteToStream(const android::StringPiece& prefix, bool final,
- std::ostream* out) const override {
- ClassMember::WriteToStream(prefix, final, out);
- *out << prefix << "public static " << (final ? "final " : "") << "int " << name_ << "=" << val_
- << ";";
+ void Print(bool final, text::Printer* printer) const override {
+ using std::to_string;
+
+ ClassMember::Print(final, printer);
+
+ printer->Print("public static ");
+ if (final) {
+ printer->Print("final ");
+ }
+ printer->Print("int ").Print(name_).Print("=").Print(to_string(val_)).Print(";");
}
private:
@@ -100,12 +104,14 @@
return name_;
}
- void WriteToStream(const android::StringPiece& prefix, bool final,
- std::ostream* out) const override {
- ClassMember::WriteToStream(prefix, final, out);
+ void Print(bool final, text::Printer* printer) const override {
+ ClassMember::Print(final, printer);
- *out << prefix << "public static " << (final ? "final " : "") << "String "
- << name_ << "=\"" << val_ << "\";";
+ printer->Print("public static ");
+ if (final) {
+ printer->Print("final ");
+ }
+ printer->Print("String ").Print(name_).Print("=\"").Print(val_).Print("\";");
}
private:
@@ -136,25 +142,27 @@
return name_;
}
- void WriteToStream(const android::StringPiece& prefix, bool final,
- std::ostream* out) const override {
- ClassMember::WriteToStream(prefix, final, out);
+ void Print(bool final, text::Printer* printer) const override {
+ ClassMember::Print(final, printer);
- *out << prefix << "public static final int[] " << name_ << "={";
+ printer->Print("public static final int[] ").Print(name_).Print("={");
+ printer->Indent();
const auto begin = elements_.begin();
const auto end = elements_.end();
for (auto current = begin; current != end; ++current) {
if (std::distance(begin, current) % kAttribsPerLine == 0) {
- *out << "\n" << prefix << kIndent << kIndent;
+ printer->Println();
}
- *out << *current;
+ printer->Print(to_string(*current));
if (std::distance(current, end) > 1) {
- *out << ", ";
+ printer->Print(", ");
}
}
- *out << "\n" << prefix << kIndent << "};";
+ printer->Println();
+ printer->Undent();
+ printer->Print("};");
}
private:
@@ -187,8 +195,7 @@
return false;
}
- void WriteToStream(const android::StringPiece& prefix, bool final,
- std::ostream* out) const override;
+ void Print(bool final, text::Printer* printer) const override;
private:
DISALLOW_COPY_AND_ASSIGN(MethodDefinition);
@@ -201,8 +208,8 @@
class ClassDefinition : public ClassMember {
public:
- static bool WriteJavaFile(const ClassDefinition* def, const android::StringPiece& package,
- bool final, std::ostream* out);
+ static void WriteJavaFile(const ClassDefinition* def, const android::StringPiece& package,
+ bool final, io::OutputStream* out);
ClassDefinition(const android::StringPiece& name, ClassQualifier qualifier, bool createIfEmpty)
: name_(name.to_string()), qualifier_(qualifier), create_if_empty_(createIfEmpty) {}
@@ -220,8 +227,7 @@
return name_;
}
- void WriteToStream(const android::StringPiece& prefix, bool final,
- std::ostream* out) const override;
+ void Print(bool final, text::Printer* printer) const override;
private:
DISALLOW_COPY_AND_ASSIGN(ClassDefinition);
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 91cef64..9861770 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -37,8 +37,10 @@
#include "java/ClassDefinition.h"
#include "process/SymbolTable.h"
-using android::StringPiece;
-using android::base::StringPrintf;
+using ::aapt::io::OutputStream;
+using ::aapt::text::Printer;
+using ::android::StringPiece;
+using ::android::base::StringPrintf;
namespace aapt {
@@ -230,7 +232,7 @@
const StringPiece& package_name_to_generate,
ClassDefinition* out_class_def,
MethodDefinition* out_rewrite_method,
- std::ostream* out_r_txt) {
+ Printer* r_txt_printer) {
const std::string array_field_name = TransformToFieldName(name.entry);
std::unique_ptr<ResourceArrayMember> array_def =
util::make_unique<ResourceArrayMember>(array_field_name);
@@ -323,8 +325,8 @@
array_def->GetCommentBuilder()->AppendComment(styleable_comment.str());
}
- if (out_r_txt != nullptr) {
- *out_r_txt << "int[] styleable " << array_field_name << " {";
+ if (r_txt_printer != nullptr) {
+ r_txt_printer->Print("int[] styleable ").Print(array_field_name).Print(" {");
}
// Add the ResourceIds to the array member.
@@ -332,16 +334,16 @@
const ResourceId id = sorted_attributes[i].attr_ref->id.value_or_default(ResourceId(0));
array_def->AddElement(id);
- if (out_r_txt != nullptr) {
+ if (r_txt_printer != nullptr) {
if (i != 0) {
- *out_r_txt << ",";
+ r_txt_printer->Print(",");
}
- *out_r_txt << " " << id;
+ r_txt_printer->Print(" ").Print(id.to_string());
}
}
- if (out_r_txt != nullptr) {
- *out_r_txt << " }\n";
+ if (r_txt_printer != nullptr) {
+ r_txt_printer->Println(" }");
}
// Add the Styleable array to the Styleable class.
@@ -396,9 +398,9 @@
attr_processor->AppendComment(
StringPrintf("@attr name %s:%s", package_name.data(), attr_name.entry.data()));
- if (out_r_txt != nullptr) {
- *out_r_txt << StringPrintf("int styleable %s %d\n", sorted_attributes[i].field_name.data(),
- (int)i);
+ if (r_txt_printer != nullptr) {
+ r_txt_printer->Println(
+ StringPrintf("int styleable %s %zd", sorted_attributes[i].field_name.c_str(), i));
}
out_class_def->AddMember(std::move(index_member));
@@ -422,10 +424,12 @@
void JavaClassGenerator::ProcessResource(const ResourceNameRef& name, const ResourceId& id,
const ResourceEntry& entry, ClassDefinition* out_class_def,
MethodDefinition* out_rewrite_method,
- std::ostream* out_r_txt) {
+ text::Printer* r_txt_printer) {
ResourceId real_id = id;
if (context_->GetMinSdkVersion() < SDK_O && name.type == ResourceType::kId &&
id.package_id() > kAppPackageId) {
+ // Workaround for feature splits using package IDs > 0x7F.
+ // See b/37498913.
real_id = ResourceId(kAppPackageId, id.package_id(), id.entry_id());
}
@@ -456,8 +460,13 @@
out_class_def->AddMember(std::move(resource_member));
- if (out_r_txt != nullptr) {
- *out_r_txt << "int " << name.type << " " << field_name << " " << real_id << "\n";
+ if (r_txt_printer != nullptr) {
+ r_txt_printer->Print("int ")
+ .Print(to_string(name.type))
+ .Print(" ")
+ .Print(field_name)
+ .Print(" ")
+ .Println(real_id.to_string());
}
if (out_rewrite_method != nullptr) {
@@ -497,7 +506,7 @@
const ResourceTableType& type,
ClassDefinition* out_type_class_def,
MethodDefinition* out_rewrite_method_def,
- std::ostream* out_r_txt) {
+ Printer* r_txt_printer) {
for (const auto& entry : type.entries) {
const Maybe<std::string> unmangled_name =
UnmangleResource(package.name, package_name_to_generate, *entry);
@@ -532,18 +541,18 @@
static_cast<const Styleable*>(entry->values.front()->value.get());
ProcessStyleable(resource_name, id, *styleable, package_name_to_generate, out_type_class_def,
- out_rewrite_method_def, out_r_txt);
+ out_rewrite_method_def, r_txt_printer);
} else {
ProcessResource(resource_name, id, *entry, out_type_class_def, out_rewrite_method_def,
- out_r_txt);
+ r_txt_printer);
}
}
return true;
}
-bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, std::ostream* out,
- std::ostream* out_r_txt) {
- return Generate(package_name_to_generate, package_name_to_generate, out);
+bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, OutputStream* out,
+ OutputStream* out_r_txt) {
+ return Generate(package_name_to_generate, package_name_to_generate, out, out_r_txt);
}
static void AppendJavaDocAnnotations(const std::vector<std::string>& annotations,
@@ -556,11 +565,16 @@
}
bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate,
- const StringPiece& out_package_name, std::ostream* out,
- std::ostream* out_r_txt) {
+ const StringPiece& out_package_name, OutputStream* out,
+ OutputStream* out_r_txt) {
ClassDefinition r_class("R", ClassQualifier::kNone, true);
std::unique_ptr<MethodDefinition> rewrite_method;
+ std::unique_ptr<Printer> r_txt_printer;
+ if (out_r_txt != nullptr) {
+ r_txt_printer = util::make_unique<Printer>(out_r_txt);
+ }
+
// Generate an onResourcesLoaded() callback if requested.
if (options_.rewrite_callback_options) {
rewrite_method =
@@ -586,7 +600,7 @@
std::unique_ptr<ClassDefinition> class_def = util::make_unique<ClassDefinition>(
to_string(type->type), ClassQualifier::kStatic, force_creation_if_empty);
if (!ProcessType(package_name_to_generate, *package, *type, class_def.get(),
- rewrite_method.get(), out_r_txt)) {
+ rewrite_method.get(), r_txt_printer.get())) {
return false;
}
@@ -595,7 +609,7 @@
const ResourceTableType* priv_type = package->FindType(ResourceType::kAttrPrivate);
if (priv_type) {
if (!ProcessType(package_name_to_generate, *package, *priv_type, class_def.get(),
- rewrite_method.get(), out_r_txt)) {
+ rewrite_method.get(), r_txt_printer.get())) {
return false;
}
}
@@ -619,22 +633,7 @@
}
AppendJavaDocAnnotations(options_.javadoc_annotations, r_class.GetCommentBuilder());
-
- if (!ClassDefinition::WriteJavaFile(&r_class, out_package_name, options_.use_final, out)) {
- return false;
- }
-
- out->flush();
-
- if (out_r_txt != nullptr) {
- out_r_txt->flush();
-
- if (!*out_r_txt) {
- error_ = android::base::SystemErrorCodeToString(errno);
- return false;
- }
- }
-
+ ClassDefinition::WriteJavaFile(&r_class, out_package_name, options_.use_final, out);
return true;
}
diff --git a/tools/aapt2/java/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h
index 2541749..4992f07 100644
--- a/tools/aapt2/java/JavaClassGenerator.h
+++ b/tools/aapt2/java/JavaClassGenerator.h
@@ -17,16 +17,16 @@
#ifndef AAPT_JAVA_CLASS_GENERATOR_H
#define AAPT_JAVA_CLASS_GENERATOR_H
-#include <ostream>
#include <string>
#include "androidfw/StringPiece.h"
#include "ResourceTable.h"
#include "ResourceValues.h"
-#include "androidfw/StringPiece.h"
+#include "io/Io.h"
#include "process/IResourceTableConsumer.h"
#include "process/SymbolTable.h"
+#include "text/Printer.h"
namespace aapt {
@@ -70,14 +70,14 @@
// All symbols technically belong to a single package, but linked libraries will
// have their names mangled, denoting that they came from a different package.
// We need to generate these symbols in a separate file. Returns true on success.
- bool Generate(const android::StringPiece& package_name_to_generate, std::ostream* out,
- std::ostream* out_r_txt = nullptr);
+ bool Generate(const android::StringPiece& package_name_to_generate, io::OutputStream* out,
+ io::OutputStream* out_r_txt = nullptr);
bool Generate(const android::StringPiece& package_name_to_generate,
- const android::StringPiece& output_package_name, std::ostream* out,
- std::ostream* out_r_txt = nullptr);
+ const android::StringPiece& output_package_name, io::OutputStream* out,
+ io::OutputStream* out_r_txt = nullptr);
- const std::string& getError() const;
+ const std::string& GetError() const;
static std::string TransformToFieldName(const android::StringPiece& symbol);
@@ -94,13 +94,13 @@
bool ProcessType(const android::StringPiece& package_name_to_generate,
const ResourceTablePackage& package, const ResourceTableType& type,
ClassDefinition* out_type_class_def, MethodDefinition* out_rewrite_method_def,
- std::ostream* out_r_txt);
+ text::Printer* r_txt_printer);
// Writes a resource to the R.java file, optionally writing out a rewrite rule for its package
// ID if `out_rewrite_method` is not nullptr.
void ProcessResource(const ResourceNameRef& name, const ResourceId& id,
const ResourceEntry& entry, ClassDefinition* out_class_def,
- MethodDefinition* out_rewrite_method, std::ostream* out_r_txt);
+ MethodDefinition* out_rewrite_method, text::Printer* r_txt_printer);
// Writes a styleable resource to the R.java file, optionally writing out a rewrite rule for
// its package ID if `out_rewrite_method` is not nullptr.
@@ -109,7 +109,7 @@
const Styleable& styleable,
const android::StringPiece& package_name_to_generate,
ClassDefinition* out_class_def, MethodDefinition* out_rewrite_method,
- std::ostream* out_r_txt);
+ text::Printer* r_txt_printer);
IAaptContext* context_;
ResourceTable* table_;
@@ -117,7 +117,7 @@
std::string error_;
};
-inline const std::string& JavaClassGenerator::getError() const {
+inline const std::string& JavaClassGenerator::GetError() const {
return error_;
}
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index 668e434..02f4cb1 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -16,12 +16,13 @@
#include "java/JavaClassGenerator.h"
-#include <sstream>
#include <string>
+#include "io/StringStream.h"
#include "test/Test.h"
#include "util/Util.h"
+using ::aapt::io::StringOutputStream;
using ::android::StringPiece;
using ::testing::HasSubstr;
using ::testing::Lt;
@@ -45,7 +46,8 @@
.Build();
JavaClassGenerator generator(context.get(), table.get(), {});
- std::stringstream out;
+ std::string result;
+ StringOutputStream out(&result);
EXPECT_FALSE(generator.Generate("android", &out));
}
@@ -69,10 +71,10 @@
.Build();
JavaClassGenerator generator(context.get(), table.get(), {});
- std::stringstream out;
+ std::string output;
+ StringOutputStream out(&output);
EXPECT_TRUE(generator.Generate("android", &out));
-
- std::string output = out.str();
+ out.Flush();
EXPECT_THAT(output, HasSubstr("public static final int hey_man=0x01020000;"));
EXPECT_THAT(output, HasSubstr("public static final int[] hey_dude={"));
@@ -93,10 +95,12 @@
.SetNameManglerPolicy(NameManglerPolicy{"android"})
.Build();
JavaClassGenerator generator(context.get(), table.get(), {});
- std::stringstream out;
- ASSERT_TRUE(generator.Generate("android", "com.android.internal", &out));
- std::string output = out.str();
+ std::string output;
+ StringOutputStream out(&output);
+ ASSERT_TRUE(generator.Generate("android", "com.android.internal", &out));
+ out.Flush();
+
EXPECT_THAT(output, HasSubstr("package com.android.internal;"));
EXPECT_THAT(output, HasSubstr("public static final int one=0x01020000;"));
EXPECT_THAT(output, Not(HasSubstr("two")));
@@ -117,10 +121,12 @@
.SetNameManglerPolicy(NameManglerPolicy{"android"})
.Build();
JavaClassGenerator generator(context.get(), table.get(), {});
- std::stringstream out;
- ASSERT_TRUE(generator.Generate("android", &out));
- std::string output = out.str();
+ std::string output;
+ StringOutputStream out(&output);
+ ASSERT_TRUE(generator.Generate("android", &out));
+ out.Flush();
+
EXPECT_THAT(output, HasSubstr("public static final class attr"));
EXPECT_THAT(output, Not(HasSubstr("public static final class ^attr-private")));
}
@@ -147,9 +153,11 @@
options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
{
JavaClassGenerator generator(context.get(), table.get(), options);
- std::stringstream out;
+ std::string output;
+ StringOutputStream out(&output);
ASSERT_TRUE(generator.Generate("android", &out));
- std::string output = out.str();
+ out.Flush();
+
EXPECT_THAT(output, HasSubstr("public static final int one=0x01020000;"));
EXPECT_THAT(output, Not(HasSubstr("two")));
EXPECT_THAT(output, Not(HasSubstr("three")));
@@ -158,9 +166,11 @@
options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
{
JavaClassGenerator generator(context.get(), table.get(), options);
- std::stringstream out;
+ std::string output;
+ StringOutputStream out(&output);
ASSERT_TRUE(generator.Generate("android", &out));
- std::string output = out.str();
+ out.Flush();
+
EXPECT_THAT(output, HasSubstr("public static final int one=0x01020000;"));
EXPECT_THAT(output, HasSubstr("public static final int two=0x01020001;"));
EXPECT_THAT(output, Not(HasSubstr("three")));
@@ -169,9 +179,11 @@
options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
{
JavaClassGenerator generator(context.get(), table.get(), options);
- std::stringstream out;
+ std::string output;
+ StringOutputStream out(&output);
ASSERT_TRUE(generator.Generate("android", &out));
- std::string output = out.str();
+ out.Flush();
+
EXPECT_THAT(output, HasSubstr("public static final int one=0x01020000;"));
EXPECT_THAT(output, HasSubstr("public static final int two=0x01020001;"));
EXPECT_THAT(output, HasSubstr("public static final int three=0x01020002;"));
@@ -235,10 +247,11 @@
.Build();
JavaClassGenerator generator(context.get(), table.get(), {});
- std::stringstream out;
+ std::string output;
+ StringOutputStream out(&output);
EXPECT_TRUE(generator.Generate("android", &out));
+ out.Flush();
- std::string output = out.str();
EXPECT_THAT(output, HasSubstr("int foo_bar="));
EXPECT_THAT(output, HasSubstr("int foo_com_lib_bar="));
}
@@ -258,9 +271,11 @@
.SetNameManglerPolicy(NameManglerPolicy{"android"})
.Build();
JavaClassGenerator generator(context.get(), table.get(), {});
- std::stringstream out;
+
+ std::string output;
+ StringOutputStream out(&output);
ASSERT_TRUE(generator.Generate("android", &out));
- std::string output = out.str();
+ out.Flush();
const char* expected_text =
R"EOF(/**
@@ -298,9 +313,11 @@
JavaClassGeneratorOptions options;
options.use_final = false;
JavaClassGenerator generator(context.get(), table.get(), options);
- std::stringstream out;
+
+ std::string output;
+ StringOutputStream out(&output);
ASSERT_TRUE(generator.Generate("android", &out));
- std::string output = out.str();
+ out.Flush();
EXPECT_THAT(output, HasSubstr("attr name android:one"));
EXPECT_THAT(output, HasSubstr("attr description"));
@@ -332,9 +349,11 @@
JavaClassGeneratorOptions options;
JavaClassGenerator generator(context.get(), table.get(), {});
- std::stringstream out;
+
+ std::string output;
+ StringOutputStream out(&output);
ASSERT_TRUE(generator.Generate("android", &out));
- std::string output = out.str();
+ out.Flush();
std::string::size_type actionbar_pos = output.find("int[] ActionBar");
ASSERT_THAT(actionbar_pos, Ne(std::string::npos));
@@ -373,9 +392,11 @@
JavaClassGeneratorOptions options;
options.use_final = false;
JavaClassGenerator generator(context.get(), table.get(), options);
- std::stringstream out;
+
+ std::string output;
+ StringOutputStream out(&output);
ASSERT_TRUE(generator.Generate("android", &out));
- std::string output = out.str();
+ out.Flush();
EXPECT_THAT(output, Not(HasSubstr("@attr name android:one")));
EXPECT_THAT(output, Not(HasSubstr("@attr description")));
@@ -409,10 +430,10 @@
options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{{"com.foo", "com.boo"}};
JavaClassGenerator generator(context.get(), table.get(), options);
- std::stringstream out;
+ std::string output;
+ StringOutputStream out(&output);
ASSERT_TRUE(generator.Generate("android", &out));
-
- std::string output = out.str();
+ out.Flush();
EXPECT_THAT(output, HasSubstr("void onResourcesLoaded"));
EXPECT_THAT(output, HasSubstr("com.foo.R.onResourcesLoaded"));
diff --git a/tools/aapt2/java/ManifestClassGenerator.h b/tools/aapt2/java/ManifestClassGenerator.h
index b12202a..3f6645f 100644
--- a/tools/aapt2/java/ManifestClassGenerator.h
+++ b/tools/aapt2/java/ManifestClassGenerator.h
@@ -23,8 +23,7 @@
namespace aapt {
-std::unique_ptr<ClassDefinition> GenerateManifestClass(IDiagnostics* diag,
- xml::XmlResource* res);
+std::unique_ptr<ClassDefinition> GenerateManifestClass(IDiagnostics* diag, xml::XmlResource* res);
} // namespace aapt
diff --git a/tools/aapt2/java/ManifestClassGenerator_test.cpp b/tools/aapt2/java/ManifestClassGenerator_test.cpp
index ada5634..c324238 100644
--- a/tools/aapt2/java/ManifestClassGenerator_test.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator_test.cpp
@@ -16,8 +16,10 @@
#include "java/ManifestClassGenerator.h"
+#include "io/StringStream.h"
#include "test/Test.h"
+using ::aapt::io::StringOutputStream;
using ::testing::HasSubstr;
using ::testing::Not;
@@ -144,12 +146,9 @@
return ::testing::AssertionFailure() << "manifest_class == nullptr";
}
- std::stringstream out;
- if (!manifest_class->WriteJavaFile(manifest_class.get(), "android", true, &out)) {
- return ::testing::AssertionFailure() << "failed to write java file";
- }
-
- *out_str = out.str();
+ StringOutputStream out(out_str);
+ manifest_class->WriteJavaFile(manifest_class.get(), "android", true, &out);
+ out.Flush();
return ::testing::AssertionSuccess();
}
diff --git a/tools/aapt2/java/ProguardRules.cpp b/tools/aapt2/java/ProguardRules.cpp
index b214d21..132b234 100644
--- a/tools/aapt2/java/ProguardRules.cpp
+++ b/tools/aapt2/java/ProguardRules.cpp
@@ -20,14 +20,18 @@
#include <string>
#include "android-base/macros.h"
+#include "androidfw/StringPiece.h"
#include "JavaClassGenerator.h"
#include "ResourceUtils.h"
#include "ValueVisitor.h"
-#include "androidfw/StringPiece.h"
+#include "text/Printer.h"
#include "util/Util.h"
#include "xml/XmlDom.h"
+using ::aapt::io::OutputStream;
+using ::aapt::text::Printer;
+
namespace aapt {
namespace proguard {
@@ -326,12 +330,13 @@
return true;
}
-bool WriteKeepSet(std::ostream* out, const KeepSet& keep_set) {
+void WriteKeepSet(const KeepSet& keep_set, OutputStream* out) {
+ Printer printer(out);
for (const auto& entry : keep_set.manifest_class_set_) {
for (const UsageLocation& location : entry.second) {
- *out << "# Referenced at " << location.source << "\n";
+ printer.Print("# Referenced at ").Println(location.source.to_string());
}
- *out << "-keep class " << entry.first << " { <init>(...); }\n" << std::endl;
+ printer.Print("-keep class ").Print(entry.first).Println(" { <init>(...); }");
}
for (const auto& entry : keep_set.conditional_class_set_) {
@@ -342,26 +347,31 @@
}
for (const UsageLocation& location : entry.second) {
- *out << "# Referenced at " << location.source << "\n";
+ printer.Print("# Referenced at ").Println(location.source.to_string());
}
if (keep_set.conditional_keep_rules_ && can_be_conditional) {
- *out << "-if class **.R$layout {\n";
+ printer.Println("-if class **.R$layout {");
+ printer.Indent();
for (const UsageLocation& location : locations) {
- auto transformed_name = JavaClassGenerator::TransformToFieldName(location.name.entry);
- *out << " int " << transformed_name << ";\n";
+ printer.Print("int ")
+ .Print(JavaClassGenerator::TransformToFieldName(location.name.entry))
+ .Println(";");
}
- *out << "}\n";
+ printer.Undent();
+ printer.Println("}");
+ printer.Println();
}
- *out << "-keep class " << entry.first << " { <init>(...); }\n" << std::endl;
+ printer.Print("-keep class ").Print(entry.first).Println(" { <init>(...); }");
+ printer.Println();
}
for (const auto& entry : keep_set.method_set_) {
for (const UsageLocation& location : entry.second) {
- *out << "# Referenced at " << location.source << "\n";
+ printer.Print("# Referenced at ").Println(location.source.to_string());
}
- *out << "-keepclassmembers class * { *** " << entry.first << "(...); }\n" << std::endl;
+ printer.Print("-keepclassmembers class * { *** ").Print(entry.first).Println("(...); }");
+ printer.Println();
}
- return true;
}
bool CollectLocations(const UsageLocation& location, const KeepSet& keep_set,
diff --git a/tools/aapt2/java/ProguardRules.h b/tools/aapt2/java/ProguardRules.h
index 8dbe3c2..46827ee 100644
--- a/tools/aapt2/java/ProguardRules.h
+++ b/tools/aapt2/java/ProguardRules.h
@@ -22,11 +22,13 @@
#include <set>
#include <string>
+#include "androidfw/StringPiece.h"
+
#include "Resource.h"
#include "ResourceTable.h"
#include "Source.h"
#include "ValueVisitor.h"
-#include "androidfw/StringPiece.h"
+#include "io/Io.h"
#include "process/IResourceTableConsumer.h"
#include "xml/XmlDom.h"
@@ -62,7 +64,7 @@
}
private:
- friend bool WriteKeepSet(std::ostream* out, const KeepSet& keep_set);
+ friend void WriteKeepSet(const KeepSet& keep_set, io::OutputStream* out);
friend bool CollectLocations(const UsageLocation& location, const KeepSet& keep_set,
std::set<UsageLocation>* locations);
@@ -76,11 +78,12 @@
bool CollectProguardRulesForManifest(xml::XmlResource* res, KeepSet* keep_set,
bool main_dex_only = false);
-bool CollectProguardRules(xml::XmlResource* res, KeepSet* keep_set);
-bool CollectResourceReferences(aapt::IAaptContext* context, ResourceTable* table,
- KeepSet* keep_set);
-bool WriteKeepSet(std::ostream* out, const KeepSet& keep_set);
+bool CollectProguardRules(xml::XmlResource* res, KeepSet* keep_set);
+
+bool CollectResourceReferences(IAaptContext* context, ResourceTable* table, KeepSet* keep_set);
+
+void WriteKeepSet(const KeepSet& keep_set, io::OutputStream* out);
bool CollectLocations(const UsageLocation& location, const KeepSet& keep_set,
std::set<UsageLocation>* locations);
diff --git a/tools/aapt2/java/ProguardRules_test.cpp b/tools/aapt2/java/ProguardRules_test.cpp
index 802c56a..37d1a5f 100644
--- a/tools/aapt2/java/ProguardRules_test.cpp
+++ b/tools/aapt2/java/ProguardRules_test.cpp
@@ -17,13 +17,23 @@
#include "java/ProguardRules.h"
#include "link/Linkers.h"
+#include "io/StringStream.h"
#include "test/Test.h"
+using ::aapt::io::StringOutputStream;
using ::testing::HasSubstr;
using ::testing::Not;
namespace aapt {
+std::string GetKeepSetString(const proguard::KeepSet& set) {
+ std::string out;
+ StringOutputStream sout(&out);
+ proguard::WriteKeepSet(set, &sout);
+ sout.Flush();
+ return out;
+}
+
TEST(ProguardRulesTest, FragmentNameRuleIsEmitted) {
std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
@@ -34,10 +44,8 @@
proguard::KeepSet set;
ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
- std::stringstream out;
- ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
+ std::string actual = GetKeepSetString(set);
- std::string actual = out.str();
EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
}
@@ -50,10 +58,8 @@
proguard::KeepSet set;
ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
- std::stringstream out;
- ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
+ std::string actual = GetKeepSetString(set);
- std::string actual = out.str();
EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
}
@@ -68,10 +74,8 @@
proguard::KeepSet set;
ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
- std::stringstream out;
- ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
+ std::string actual = GetKeepSetString(set);
- std::string actual = out.str();
EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
EXPECT_THAT(actual, HasSubstr("com.foo.Baz"));
}
@@ -87,10 +91,8 @@
proguard::KeepSet set;
ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
- std::stringstream out;
- ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
+ std::string actual = GetKeepSetString(set);
- std::string actual = out.str();
EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
}
@@ -126,11 +128,10 @@
ASSERT_TRUE(proguard::CollectProguardRules(bar_layout.get(), &set));
ASSERT_TRUE(proguard::CollectProguardRules(foo_layout.get(), &set));
- std::stringstream out;
- ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
+ std::string actual = GetKeepSetString(set);
- std::string actual = out.str();
EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
+ EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
EXPECT_THAT(actual, HasSubstr("int foo"));
EXPECT_THAT(actual, HasSubstr("int bar"));
EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
@@ -148,10 +149,9 @@
set.AddReference({test::ParseNameOrDie("layout/bar"), {}}, layout->file.name);
ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
- std::stringstream out;
- ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
+ std::string actual = GetKeepSetString(set);
- std::string actual = out.str();
+ EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
EXPECT_THAT(actual, HasSubstr("int foo"));
EXPECT_THAT(actual, HasSubstr("int bar"));
@@ -170,11 +170,10 @@
set.AddReference({test::ParseNameOrDie("style/MyStyle"), {}}, layout->file.name);
ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
- std::stringstream out;
- ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
+ std::string actual = GetKeepSetString(set);
- std::string actual = out.str();
EXPECT_THAT(actual, Not(HasSubstr("-if")));
+ EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
}
TEST(ProguardRulesTest, ViewOnClickRuleIsEmitted) {
@@ -187,10 +186,8 @@
proguard::KeepSet set;
ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
- std::stringstream out;
- ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
+ std::string actual = GetKeepSetString(set);
- std::string actual = out.str();
EXPECT_THAT(actual, HasSubstr("bar_method"));
}
@@ -208,10 +205,8 @@
proguard::KeepSet set;
ASSERT_TRUE(proguard::CollectProguardRules(menu.get(), &set));
- std::stringstream out;
- ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
+ std::string actual = GetKeepSetString(set);
- std::string actual = out.str();
EXPECT_THAT(actual, HasSubstr("on_click"));
EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
EXPECT_THAT(actual, HasSubstr("com.foo.Baz"));
diff --git a/tools/aapt2/text/Printer.cpp b/tools/aapt2/text/Printer.cpp
index 38b3585..243800c 100644
--- a/tools/aapt2/text/Printer.cpp
+++ b/tools/aapt2/text/Printer.cpp
@@ -26,18 +26,18 @@
namespace aapt {
namespace text {
-void Printer::Println(const StringPiece& str) {
+Printer& Printer::Println(const StringPiece& str) {
Print(str);
- Print("\n");
+ return Print("\n");
}
-void Printer::Println() {
- Print("\n");
+Printer& Printer::Println() {
+ return Print("\n");
}
-void Printer::Print(const StringPiece& str) {
+Printer& Printer::Print(const StringPiece& str) {
if (error_) {
- return;
+ return *this;
}
auto remaining_str_begin = str.begin();
@@ -53,7 +53,7 @@
for (int i = 0; i < indent_level_; i++) {
if (!io::Copy(out_, " ")) {
error_ = true;
- return;
+ return *this;
}
}
needs_indent_ = false;
@@ -61,7 +61,7 @@
if (!io::Copy(out_, str_to_copy)) {
error_ = true;
- return;
+ return *this;
}
}
@@ -69,7 +69,7 @@
if (new_line_iter != remaining_str_end) {
if (!io::Copy(out_, "\n")) {
error_ = true;
- return;
+ return *this;
}
needs_indent_ = true;
// Ok to increment iterator here because we know that the '\n' character is one byte.
@@ -78,6 +78,7 @@
remaining_str_begin = new_line_iter;
}
}
+ return *this;
}
void Printer::Indent() {
diff --git a/tools/aapt2/text/Printer.h b/tools/aapt2/text/Printer.h
index 94b3c0b..f399f8e 100644
--- a/tools/aapt2/text/Printer.h
+++ b/tools/aapt2/text/Printer.h
@@ -31,9 +31,9 @@
explicit Printer(::aapt::io::OutputStream* out) : out_(out) {
}
- void Print(const ::android::StringPiece& str);
- void Println(const ::android::StringPiece& str);
- void Println();
+ Printer& Print(const ::android::StringPiece& str);
+ Printer& Println(const ::android::StringPiece& str);
+ Printer& Println();
void Indent();
void Undent();
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index a910c62..468864b 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -23,6 +23,10 @@
"Collation.cpp",
"main.cpp",
],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
shared_libs: [
"libstats_proto_host",
@@ -90,6 +94,10 @@
name: "libstatslog",
generated_sources: ["statslog.cpp"],
generated_headers: ["statslog.h"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
export_generated_headers: ["statslog.h"],
shared_libs: [
"liblog",
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index eb29150..cca1294 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -96,8 +96,6 @@
static int
write_stats_log_cpp(FILE* out, const Atoms& atoms)
{
- int errorCount;
-
// Print prelude
fprintf(out, "// This file is autogenerated\n");
fprintf(out, "\n");
@@ -109,6 +107,8 @@
fprintf(out, "namespace android {\n");
fprintf(out, "namespace util {\n");
+ fprintf(out, "// the single event tag id for all stats logs\n");
+ fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
// Print write methods
fprintf(out, "\n");
@@ -117,7 +117,7 @@
int argIndex;
fprintf(out, "void\n");
- fprintf(out, "stats_write(int code");
+ fprintf(out, "stats_write(int32_t code");
argIndex = 1;
for (vector<java_type_t>::const_iterator arg = signature->begin();
arg != signature->end(); arg++) {
@@ -128,7 +128,8 @@
fprintf(out, "{\n");
argIndex = 1;
- fprintf(out, " android_log_event_list event(code);\n");
+ fprintf(out, " android_log_event_list event(kStatsEventTag);\n");
+ fprintf(out, " event << code;\n");
for (vector<java_type_t>::const_iterator arg = signature->begin();
arg != signature->end(); arg++) {
if (*arg == JAVA_TYPE_STRING) {
@@ -157,8 +158,6 @@
static int
write_stats_log_header(FILE* out, const Atoms& atoms)
{
- int errorCount;
-
// Print prelude
fprintf(out, "// This file is autogenerated\n");
fprintf(out, "\n");
@@ -208,8 +207,7 @@
fprintf(out, "//\n");
for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
signature != atoms.signatures.end(); signature++) {
-
- fprintf(out, "void stats_write(int code");
+ fprintf(out, "void stats_write(int32_t code ");
int argIndex = 1;
for (vector<java_type_t>::const_iterator arg = signature->begin();
arg != signature->end(); arg++) {
@@ -229,8 +227,6 @@
static int
write_stats_log_java(FILE* out, const Atoms& atoms)
{
- int errorCount;
-
// Print prelude
fprintf(out, "// This file is autogenerated\n");
fprintf(out, "\n");
@@ -395,8 +391,6 @@
static int
write_stats_log_jni(FILE* out, const Atoms& atoms)
{
- int errorCount;
-
// Print prelude
fprintf(out, "// This file is autogenerated\n");
fprintf(out, "\n");
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 26a2bdd..c2f11d9 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -102,7 +102,7 @@
int getWifiEnabledState();
- void setCountryCode(String country, boolean persist);
+ void setCountryCode(String country);
String getCountryCode();
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 68e6203..66fabf3 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -16,6 +16,7 @@
package android.net.wifi;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
@@ -1748,13 +1749,12 @@
/**
* Set the country code.
* @param countryCode country code in ISO 3166 format.
- * @param persist {@code true} if this needs to be remembered
*
* @hide
*/
- public void setCountryCode(String country, boolean persist) {
+ public void setCountryCode(@NonNull String country) {
try {
- mService.setCountryCode(country, persist);
+ mService.setCountryCode(country);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/wifi/java/android/net/wifi/rtt/WifiRttManager.java b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
index 128d6c9..735e872 100644
--- a/wifi/java/android/net/wifi/rtt/WifiRttManager.java
+++ b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
@@ -44,7 +44,7 @@
@SystemService(Context.WIFI_RTT2_SERVICE)
public class WifiRttManager {
private static final String TAG = "WifiRttManager";
- private static final boolean VDBG = true;
+ private static final boolean VDBG = false;
private final Context mContext;
private final IWifiRttManager mService;
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 1364224..3cad590 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -59,6 +59,7 @@
private static final int ERROR_NOT_SET = -1;
private static final int ERROR_TEST_REASON = 5;
private static final String TEST_PACKAGE_NAME = "TestPackage";
+ private static final String TEST_COUNTRY_CODE = "US";
@Mock Context mContext;
@Mock IWifiManager mWifiService;
@@ -777,4 +778,23 @@
mWifiManager.unregisterLocalOnlyHotspotObserver();
verify(mWifiService).stopWatchLocalOnlyHotspot();
}
+
+ /**
+ * Verify that calls WifiServiceImpl to set country code when no exception happens.
+ */
+ @Test
+ public void testSetWifiCountryCode() throws Exception {
+ mWifiManager.setCountryCode(TEST_COUNTRY_CODE);
+ verify(mWifiService).setCountryCode(TEST_COUNTRY_CODE);
+ }
+
+ /**
+ * Verify that WifiManager.setCountryCode() rethrows exceptions if caller does not
+ * have necessary permissions.
+ */
+ @Test(expected = SecurityException.class)
+ public void testSetWifiCountryCodeFailedOnSecurityException() throws Exception {
+ doThrow(new SecurityException()).when(mWifiService).setCountryCode(anyString());
+ mWifiManager.setCountryCode(TEST_COUNTRY_CODE);
+ }
}