Merge "Fix GpsTimeStamp format string"
diff --git a/Android.mk b/Android.mk
index 1d797c4..c947b0e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -288,6 +288,7 @@
core/java/com/android/internal/app/IBatteryStats.aidl \
core/java/com/android/internal/app/IEphemeralResolver.aidl \
core/java/com/android/internal/app/IProcessStats.aidl \
+ core/java/com/android/internal/app/ISoundTriggerService.aidl \
core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl \
core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl \
core/java/com/android/internal/app/IVoiceInteractor.aidl \
@@ -384,6 +385,8 @@
media/java/android/media/tv/ITvInputSessionCallback.aidl \
media/java/android/service/media/IMediaBrowserService.aidl \
media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl \
+ telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl \
+ telecomm/java/com/android/internal/telecom/ICallScreeningService.aidl \
telecomm/java/com/android/internal/telecom/IVideoCallback.aidl \
telecomm/java/com/android/internal/telecom/IVideoProvider.aidl \
telecomm/java/com/android/internal/telecom/IConnectionService.aidl \
diff --git a/api/current.txt b/api/current.txt
index f4e7c16..50f8b21 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -33,6 +33,7 @@
field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+ field public static final java.lang.String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
@@ -5788,6 +5789,7 @@
method public void clearCrossProfileIntentFilters(android.content.ComponentName);
method public void clearDeviceOwnerApp(java.lang.String);
method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
+ method public void clearProfileOwner(android.content.ComponentName);
method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
method public deprecated android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
method public android.os.UserHandle createAndManageUser(android.content.ComponentName, java.lang.String, android.content.ComponentName, android.os.PersistableBundle, int);
@@ -13356,6 +13358,7 @@
method public float getResolution();
method public java.lang.String getStringType();
method public int getType();
+ method public java.util.UUID getUuid();
method public java.lang.String getVendor();
method public int getVersion();
method public boolean isWakeUpSensor();
@@ -13370,11 +13373,13 @@
field public static final java.lang.String STRING_TYPE_GRAVITY = "android.sensor.gravity";
field public static final java.lang.String STRING_TYPE_GYROSCOPE = "android.sensor.gyroscope";
field public static final java.lang.String STRING_TYPE_GYROSCOPE_UNCALIBRATED = "android.sensor.gyroscope_uncalibrated";
+ field public static final java.lang.String STRING_TYPE_HEART_BEAT = "android.sensor.heart_beat";
field public static final java.lang.String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";
field public static final java.lang.String STRING_TYPE_LIGHT = "android.sensor.light";
field public static final java.lang.String STRING_TYPE_LINEAR_ACCELERATION = "android.sensor.linear_acceleration";
field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD = "android.sensor.magnetic_field";
field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED = "android.sensor.magnetic_field_uncalibrated";
+ field public static final java.lang.String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";
field public static final deprecated java.lang.String STRING_TYPE_ORIENTATION = "android.sensor.orientation";
field public static final java.lang.String STRING_TYPE_POSE_6DOF = "android.sensor.pose_6dof";
field public static final java.lang.String STRING_TYPE_PRESSURE = "android.sensor.pressure";
@@ -13382,6 +13387,7 @@
field public static final java.lang.String STRING_TYPE_RELATIVE_HUMIDITY = "android.sensor.relative_humidity";
field public static final java.lang.String STRING_TYPE_ROTATION_VECTOR = "android.sensor.rotation_vector";
field public static final java.lang.String STRING_TYPE_SIGNIFICANT_MOTION = "android.sensor.significant_motion";
+ field public static final java.lang.String STRING_TYPE_STATIONARY_DETECT = "android.sensor.stationary_detect";
field public static final java.lang.String STRING_TYPE_STEP_COUNTER = "android.sensor.step_counter";
field public static final java.lang.String STRING_TYPE_STEP_DETECTOR = "android.sensor.step_detector";
field public static final deprecated java.lang.String STRING_TYPE_TEMPERATURE = "android.sensor.temperature";
@@ -13393,11 +13399,13 @@
field public static final int TYPE_GRAVITY = 9; // 0x9
field public static final int TYPE_GYROSCOPE = 4; // 0x4
field public static final int TYPE_GYROSCOPE_UNCALIBRATED = 16; // 0x10
+ field public static final int TYPE_HEART_BEAT = 31; // 0x1f
field public static final int TYPE_HEART_RATE = 21; // 0x15
field public static final int TYPE_LIGHT = 5; // 0x5
field public static final int TYPE_LINEAR_ACCELERATION = 10; // 0xa
field public static final int TYPE_MAGNETIC_FIELD = 2; // 0x2
field public static final int TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14; // 0xe
+ field public static final int TYPE_MOTION_DETECT = 30; // 0x1e
field public static final deprecated int TYPE_ORIENTATION = 3; // 0x3
field public static final int TYPE_POSE_6DOF = 28; // 0x1c
field public static final int TYPE_PRESSURE = 6; // 0x6
@@ -13405,6 +13413,7 @@
field public static final int TYPE_RELATIVE_HUMIDITY = 12; // 0xc
field public static final int TYPE_ROTATION_VECTOR = 11; // 0xb
field public static final int TYPE_SIGNIFICANT_MOTION = 17; // 0x11
+ field public static final int TYPE_STATIONARY_DETECT = 29; // 0x1d
field public static final int TYPE_STEP_COUNTER = 19; // 0x13
field public static final int TYPE_STEP_DETECTOR = 18; // 0x12
field public static final deprecated int TYPE_TEMPERATURE = 7; // 0x7
@@ -13438,6 +13447,7 @@
method public static void getAngleChange(float[], float[], float[]);
method public android.hardware.Sensor getDefaultSensor(int);
method public android.hardware.Sensor getDefaultSensor(int, boolean);
+ method public java.util.List<android.hardware.Sensor> getDynamicSensorList(int);
method public static float getInclination(float[]);
method public static float[] getOrientation(float[], float[]);
method public static void getQuaternionFromVector(float[], float[]);
@@ -13445,6 +13455,8 @@
method public static void getRotationMatrixFromVector(float[], float[]);
method public java.util.List<android.hardware.Sensor> getSensorList(int);
method public deprecated int getSensors();
+ method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
+ method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback, android.os.Handler);
method public deprecated boolean registerListener(android.hardware.SensorListener, int);
method public deprecated boolean registerListener(android.hardware.SensorListener, int, int);
method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int);
@@ -13453,6 +13465,7 @@
method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int, android.os.Handler);
method public static boolean remapCoordinateSystem(float[], int, int, float[]);
method public boolean requestTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
+ method public void unregisterDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
method public deprecated void unregisterListener(android.hardware.SensorListener);
method public deprecated void unregisterListener(android.hardware.SensorListener, int);
method public void unregisterListener(android.hardware.SensorEventListener, android.hardware.Sensor);
@@ -13517,6 +13530,12 @@
field public static final float STANDARD_GRAVITY = 9.80665f;
}
+ public static abstract class SensorManager.DynamicSensorConnectionCallback {
+ ctor public SensorManager.DynamicSensorConnectionCallback();
+ method public void onDynamicSensorConnected(android.hardware.Sensor);
+ method public void onDynamicSensorDisconnected(android.hardware.Sensor);
+ }
+
public final class TriggerEvent {
field public android.hardware.Sensor sensor;
field public long timestamp;
@@ -19201,6 +19220,7 @@
field public static final android.os.Parcelable.Creator<android.media.AudioAttributes> CREATOR;
field public static final int FLAG_AUDIBILITY_ENFORCED = 1; // 0x1
field public static final int FLAG_HW_AV_SYNC = 16; // 0x10
+ field public static final int FLAG_LOW_LATENCY = 256; // 0x100
field public static final int USAGE_ALARM = 4; // 0x4
field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb
field public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12; // 0xc
@@ -19320,6 +19340,7 @@
field public static final int ENCODING_DTS = 7; // 0x7
field public static final int ENCODING_DTS_HD = 8; // 0x8
field public static final int ENCODING_E_AC3 = 6; // 0x6
+ field public static final int ENCODING_IEC61937 = 13; // 0xd
field public static final int ENCODING_INVALID = 0; // 0x0
field public static final int ENCODING_PCM_16BIT = 2; // 0x2
field public static final int ENCODING_PCM_8BIT = 3; // 0x3
@@ -19597,6 +19618,7 @@
method public void flush();
method public int getAudioFormat();
method public int getAudioSessionId();
+ method public int getBufferCapacityInFrames();
method public int getBufferSizeInFrames();
method public int getChannelConfiguration();
method public int getChannelCount();
@@ -19618,6 +19640,7 @@
method public int getState();
method public int getStreamType();
method public boolean getTimestamp(android.media.AudioTimestamp);
+ method public int getUnderrunCount();
method public void pause() throws java.lang.IllegalStateException;
method public void play() throws java.lang.IllegalStateException;
method public void release();
@@ -19625,6 +19648,7 @@
method public deprecated void removeOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener);
method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
method public int setAuxEffectSendLevel(float);
+ method public int setBufferSizeInFrames(int);
method public int setLoopPoints(int, int, int);
method public int setNotificationMarkerPosition(int);
method public int setPlaybackHeadPosition(int);
@@ -20083,6 +20107,7 @@
field public static final deprecated int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00
field public static final deprecated int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
field public static final java.lang.String FEATURE_AdaptivePlayback = "adaptive-playback";
+ field public static final java.lang.String FEATURE_IntraRefresh = "intra-refresh";
field public static final java.lang.String FEATURE_SecurePlayback = "secure-playback";
field public static final java.lang.String FEATURE_TunneledPlayback = "tunneled-playback";
field public int[] colorFormats;
@@ -20125,6 +20150,21 @@
field public static final int AVCProfileHigh422 = 32; // 0x20
field public static final int AVCProfileHigh444 = 64; // 0x40
field public static final int AVCProfileMain = 2; // 0x2
+ field public static final int DolbyVisionLevelFhd24 = 4; // 0x4
+ field public static final int DolbyVisionLevelFhd30 = 8; // 0x8
+ field public static final int DolbyVisionLevelFhd60 = 16; // 0x10
+ field public static final int DolbyVisionLevelHd24 = 1; // 0x1
+ field public static final int DolbyVisionLevelHd30 = 2; // 0x2
+ field public static final int DolbyVisionLevelUhd24 = 32; // 0x20
+ field public static final int DolbyVisionLevelUhd30 = 64; // 0x40
+ field public static final int DolbyVisionLevelUhd48 = 128; // 0x80
+ field public static final int DolbyVisionLevelUhd60 = 256; // 0x100
+ field public static final int DolbyVisionProfileDvavDen = 2; // 0x2
+ field public static final int DolbyVisionProfileDvavDer = 1; // 0x1
+ field public static final int DolbyVisionProfileDvheDen = 4; // 0x4
+ field public static final int DolbyVisionProfileDvheDer = 3; // 0x3
+ field public static final int DolbyVisionProfileDvheDtr = 5; // 0x5
+ field public static final int DolbyVisionProfileDvheStn = 6; // 0x6
field public static final int H263Level10 = 1; // 0x1
field public static final int H263Level20 = 2; // 0x2
field public static final int H263Level30 = 4; // 0x4
@@ -20209,6 +20249,24 @@
field public static final int VP8Level_Version2 = 4; // 0x4
field public static final int VP8Level_Version3 = 8; // 0x8
field public static final int VP8ProfileMain = 1; // 0x1
+ field public static final int VP9Level1 = 0; // 0x0
+ field public static final int VP9Level11 = 1; // 0x1
+ field public static final int VP9Level2 = 2; // 0x2
+ field public static final int VP9Level21 = 4; // 0x4
+ field public static final int VP9Level3 = 8; // 0x8
+ field public static final int VP9Level31 = 16; // 0x10
+ field public static final int VP9Level4 = 32; // 0x20
+ field public static final int VP9Level41 = 64; // 0x40
+ field public static final int VP9Level5 = 128; // 0x80
+ field public static final int VP9Level51 = 256; // 0x100
+ field public static final int VP9Level52 = 512; // 0x200
+ field public static final int VP9Level6 = 1024; // 0x400
+ field public static final int VP9Level61 = 2048; // 0x800
+ field public static final int VP9Level62 = 4096; // 0x1000
+ field public static final int VP9Profile0 = 0; // 0x0
+ field public static final int VP9Profile1 = 1; // 0x1
+ field public static final int VP9Profile2 = 2; // 0x2
+ field public static final int VP9Profile3 = 3; // 0x3
field public int level;
field public int profile;
}
@@ -20436,6 +20494,16 @@
method public final void setInteger(java.lang.String, int);
method public final void setLong(java.lang.String, long);
method public final void setString(java.lang.String, java.lang.String);
+ field public static final int COLOR_RANGE_FULL = 1; // 0x1
+ field public static final int COLOR_RANGE_LIMITED = 2; // 0x2
+ field public static final int COLOR_STANDARD_BT2020 = 6; // 0x6
+ field public static final int COLOR_STANDARD_BT601_NTSC = 4; // 0x4
+ field public static final int COLOR_STANDARD_BT601_PAL = 2; // 0x2
+ field public static final int COLOR_STANDARD_BT709 = 1; // 0x1
+ field public static final int COLOR_TRANSFER_HLG = 7; // 0x7
+ field public static final int COLOR_TRANSFER_LINEAR = 1; // 0x1
+ field public static final int COLOR_TRANSFER_SDR_VIDEO = 3; // 0x3
+ field public static final int COLOR_TRANSFER_ST2084 = 6; // 0x6
field public static final java.lang.String KEY_AAC_DRC_ATTENUATION_FACTOR = "aac-drc-cut-level";
field public static final java.lang.String KEY_AAC_DRC_BOOST_FACTOR = "aac-drc-boost-level";
field public static final java.lang.String KEY_AAC_DRC_HEAVY_COMPRESSION = "aac-drc-heavy-compression";
@@ -20451,11 +20519,15 @@
field public static final java.lang.String KEY_CHANNEL_COUNT = "channel-count";
field public static final java.lang.String KEY_CHANNEL_MASK = "channel-mask";
field public static final java.lang.String KEY_COLOR_FORMAT = "color-format";
+ field public static final java.lang.String KEY_COLOR_RANGE = "color-range";
+ field public static final java.lang.String KEY_COLOR_STANDARD = "color-standard";
+ field public static final java.lang.String KEY_COLOR_TRANSFER = "color-transfer";
field public static final java.lang.String KEY_COMPLEXITY = "complexity";
field public static final java.lang.String KEY_DURATION = "durationUs";
field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
field public static final java.lang.String KEY_HEIGHT = "height";
+ field public static final java.lang.String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
field public static final java.lang.String KEY_IS_ADTS = "is-adts";
field public static final java.lang.String KEY_IS_AUTOSELECT = "is-autoselect";
field public static final java.lang.String KEY_IS_DEFAULT = "is-default";
@@ -20777,9 +20849,11 @@
method public static final int getAudioSourceMax();
method public int getMaxAmplitude() throws java.lang.IllegalStateException;
method public android.view.Surface getSurface();
+ method public void pause() throws java.lang.IllegalStateException;
method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
method public void release();
method public void reset();
+ method public void resume() throws java.lang.IllegalStateException;
method public void setAudioChannels(int);
method public void setAudioEncoder(int) throws java.lang.IllegalStateException;
method public void setAudioEncodingBitRate(int);
@@ -28534,6 +28608,7 @@
field public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1; // 0x1
field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
+ field public static final int SUSTAINED_PERFORMANCE_WAKE_LOCK = 256; // 0x100
}
public final class PowerManager.WakeLock {
@@ -32263,6 +32338,7 @@
public class VoicemailContract {
field public static final java.lang.String ACTION_FETCH_VOICEMAIL = "android.intent.action.FETCH_VOICEMAIL";
field public static final java.lang.String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
+ field public static final java.lang.String ACTION_SYNC_VOICEMAIL = "android.intent.action.SYNC_VOICEMAIL";
field public static final java.lang.String AUTHORITY = "com.android.voicemail";
field public static final java.lang.String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
field public static final java.lang.String PARAM_KEY_SOURCE_PACKAGE = "source_package";
@@ -32277,8 +32353,13 @@
field public static final int CONFIGURATION_STATE_OK = 0; // 0x0
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String DATA_CHANNEL_STATE = "data_channel_state";
+ field public static final int DATA_CHANNEL_STATE_BAD_CONFIGURATION = 3; // 0x3
+ field public static final int DATA_CHANNEL_STATE_COMMUNICATION_ERROR = 4; // 0x4
field public static final int DATA_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
+ field public static final int DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED = 2; // 0x2
field public static final int DATA_CHANNEL_STATE_OK = 0; // 0x0
+ field public static final int DATA_CHANNEL_STATE_SERVER_CONNECTION_ERROR = 6; // 0x6
+ field public static final int DATA_CHANNEL_STATE_SERVER_ERROR = 5; // 0x5
field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemail.source.status";
field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail.source.status";
field public static final java.lang.String NOTIFICATION_CHANNEL_STATE = "notification_channel_state";
@@ -32376,6 +32457,7 @@
method public void copyTo(short[]);
method public void copyTo(int[]);
method public void copyTo(float[]);
+ method public static android.renderscript.Allocation[] createAllocations(android.renderscript.RenderScript, android.renderscript.Type, int, int);
method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap);
method public static android.renderscript.Allocation createCubemapFromCubeFaces(android.renderscript.RenderScript, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
@@ -32391,9 +32473,12 @@
method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type, int);
method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type);
method public void generateMipmaps();
+ method public java.nio.ByteBuffer getByteBuffer();
method public int getBytesSize();
method public android.renderscript.Element getElement();
+ method public long getStride();
method public android.view.Surface getSurface();
+ method public long getTimeStamp();
method public android.renderscript.Type getType();
method public int getUsage();
method public void ioReceive();
@@ -33918,6 +34003,7 @@
field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+ field public static final int REASON_PACKAGE_SUSPENDED = 15; // 0xf
field public static final int REASON_TOPIC_BANNED = 14; // 0xe
field public static final int REASON_USER_STOPPED = 6; // 0x6
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
@@ -35333,6 +35419,30 @@
field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
}
+ public abstract class CallScreeningService extends android.app.Service {
+ ctor public CallScreeningService();
+ method public android.os.IBinder onBind(android.content.Intent);
+ method public abstract void onScreenCall(android.telecom.Call.Details);
+ method public final void respondToCall(android.telecom.Call.Details, android.telecom.CallScreeningService.CallResponse);
+ field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.CallScreeningService";
+ }
+
+ public class CallScreeningService.CallResponse {
+ method public boolean getDisallowCall();
+ method public boolean getRejectCall();
+ method public boolean getSkipCallLog();
+ method public boolean getSkipNotification();
+ }
+
+ public class CallScreeningService.CallResponse.Builder {
+ ctor public CallScreeningService.CallResponse.Builder();
+ method public android.telecom.CallScreeningService.CallResponse build();
+ method public android.telecom.CallScreeningService.CallResponse.Builder setDisallowCall(boolean);
+ method public android.telecom.CallScreeningService.CallResponse.Builder setRejectCall(boolean);
+ method public android.telecom.CallScreeningService.CallResponse.Builder setSkipCallLog(boolean);
+ method public android.telecom.CallScreeningService.CallResponse.Builder setSkipNotification(boolean);
+ }
+
public abstract class Conference extends android.telecom.Conferenceable {
ctor public Conference(android.telecom.PhoneAccountHandle);
method public final boolean addConnection(android.telecom.Connection);
@@ -35572,6 +35682,7 @@
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
method public void onCallRemoved(android.telecom.Call);
method public void onCanAddCallChanged(boolean);
+ method public void onSilenceRinger();
method public final void setAudioRoute(int);
method public final void setMuted(boolean);
field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.InCallService";
@@ -35832,6 +35943,7 @@
field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
+ field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
field public static final int PRESENTATION_ALLOWED = 1; // 0x1
field public static final int PRESENTATION_PAYPHONE = 4; // 0x4
@@ -35983,6 +36095,7 @@
field public static final java.lang.String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN = "vvm_cellular_data_required";
field public static final java.lang.String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string";
field public static final java.lang.String KEY_VVM_PORT_NUMBER_INT = "vvm_port_number_int";
+ field public static final java.lang.String KEY_VVM_PREFETCH_BOOLEAN = "vvm_prefetch";
field public static final java.lang.String KEY_VVM_TYPE_STRING = "vvm_type_string";
field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
}
@@ -36000,6 +36113,8 @@
public final class CellIdentityGsm implements android.os.Parcelable {
method public int describeContents();
+ method public int getArfcn();
+ method public int getBsic();
method public int getCid();
method public int getLac();
method public int getMcc();
@@ -36012,6 +36127,7 @@
public final class CellIdentityLte implements android.os.Parcelable {
method public int describeContents();
method public int getCi();
+ method public int getEarfcn();
method public int getMcc();
method public int getMnc();
method public int getPci();
@@ -36027,6 +36143,7 @@
method public int getMcc();
method public int getMnc();
method public int getPsc();
+ method public int getUarfcn();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityWcdma> CREATOR;
}
@@ -49882,6 +49999,9 @@
field public static final java.lang.Class<java.lang.Float> TYPE;
}
+ public abstract class FunctionalInterface implements java.lang.annotation.Annotation {
+ }
+
public class IllegalAccessError extends java.lang.IncompatibleClassChangeError {
ctor public IllegalAccessError();
ctor public IllegalAccessError(java.lang.String);
diff --git a/api/system-current.txt b/api/system-current.txt
index 61a0595..b876ca9 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -46,6 +46,7 @@
field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+ field public static final java.lang.String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
field public static final java.lang.String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT";
@@ -7607,6 +7608,8 @@
method public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
method public void startScan(android.bluetooth.le.ScanCallback);
method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
+ method public void startScanFromSource(android.os.WorkSource, android.bluetooth.le.ScanCallback);
+ method public void startScanFromSource(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.os.WorkSource, android.bluetooth.le.ScanCallback);
method public void startTruncatedScan(java.util.List<android.bluetooth.le.TruncatedFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
method public void stopScan(android.bluetooth.le.ScanCallback);
}
@@ -13755,6 +13758,7 @@
method public float getResolution();
method public java.lang.String getStringType();
method public int getType();
+ method public java.util.UUID getUuid();
method public java.lang.String getVendor();
method public int getVersion();
method public boolean isDataInjectionSupported();
@@ -13765,16 +13769,19 @@
field public static final int REPORTING_MODE_SPECIAL_TRIGGER = 3; // 0x3
field public static final java.lang.String STRING_TYPE_ACCELEROMETER = "android.sensor.accelerometer";
field public static final java.lang.String STRING_TYPE_AMBIENT_TEMPERATURE = "android.sensor.ambient_temperature";
+ field public static final java.lang.String STRING_TYPE_DYNAMIC_SENSOR_META = "android.sensor.dynamic_sensor_meta";
field public static final java.lang.String STRING_TYPE_GAME_ROTATION_VECTOR = "android.sensor.game_rotation_vector";
field public static final java.lang.String STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR = "android.sensor.geomagnetic_rotation_vector";
field public static final java.lang.String STRING_TYPE_GRAVITY = "android.sensor.gravity";
field public static final java.lang.String STRING_TYPE_GYROSCOPE = "android.sensor.gyroscope";
field public static final java.lang.String STRING_TYPE_GYROSCOPE_UNCALIBRATED = "android.sensor.gyroscope_uncalibrated";
+ field public static final java.lang.String STRING_TYPE_HEART_BEAT = "android.sensor.heart_beat";
field public static final java.lang.String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";
field public static final java.lang.String STRING_TYPE_LIGHT = "android.sensor.light";
field public static final java.lang.String STRING_TYPE_LINEAR_ACCELERATION = "android.sensor.linear_acceleration";
field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD = "android.sensor.magnetic_field";
field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED = "android.sensor.magnetic_field_uncalibrated";
+ field public static final java.lang.String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";
field public static final deprecated java.lang.String STRING_TYPE_ORIENTATION = "android.sensor.orientation";
field public static final java.lang.String STRING_TYPE_POSE_6DOF = "android.sensor.pose_6dof";
field public static final java.lang.String STRING_TYPE_PRESSURE = "android.sensor.pressure";
@@ -13782,6 +13789,7 @@
field public static final java.lang.String STRING_TYPE_RELATIVE_HUMIDITY = "android.sensor.relative_humidity";
field public static final java.lang.String STRING_TYPE_ROTATION_VECTOR = "android.sensor.rotation_vector";
field public static final java.lang.String STRING_TYPE_SIGNIFICANT_MOTION = "android.sensor.significant_motion";
+ field public static final java.lang.String STRING_TYPE_STATIONARY_DETECT = "android.sensor.stationary_detect";
field public static final java.lang.String STRING_TYPE_STEP_COUNTER = "android.sensor.step_counter";
field public static final java.lang.String STRING_TYPE_STEP_DETECTOR = "android.sensor.step_detector";
field public static final deprecated java.lang.String STRING_TYPE_TEMPERATURE = "android.sensor.temperature";
@@ -13789,16 +13797,19 @@
field public static final int TYPE_ACCELEROMETER = 1; // 0x1
field public static final int TYPE_ALL = -1; // 0xffffffff
field public static final int TYPE_AMBIENT_TEMPERATURE = 13; // 0xd
+ field public static final int TYPE_DYNAMIC_SENSOR_META = 32; // 0x20
field public static final int TYPE_GAME_ROTATION_VECTOR = 15; // 0xf
field public static final int TYPE_GEOMAGNETIC_ROTATION_VECTOR = 20; // 0x14
field public static final int TYPE_GRAVITY = 9; // 0x9
field public static final int TYPE_GYROSCOPE = 4; // 0x4
field public static final int TYPE_GYROSCOPE_UNCALIBRATED = 16; // 0x10
+ field public static final int TYPE_HEART_BEAT = 31; // 0x1f
field public static final int TYPE_HEART_RATE = 21; // 0x15
field public static final int TYPE_LIGHT = 5; // 0x5
field public static final int TYPE_LINEAR_ACCELERATION = 10; // 0xa
field public static final int TYPE_MAGNETIC_FIELD = 2; // 0x2
field public static final int TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14; // 0xe
+ field public static final int TYPE_MOTION_DETECT = 30; // 0x1e
field public static final deprecated int TYPE_ORIENTATION = 3; // 0x3
field public static final int TYPE_POSE_6DOF = 28; // 0x1c
field public static final int TYPE_PRESSURE = 6; // 0x6
@@ -13806,6 +13817,7 @@
field public static final int TYPE_RELATIVE_HUMIDITY = 12; // 0xc
field public static final int TYPE_ROTATION_VECTOR = 11; // 0xb
field public static final int TYPE_SIGNIFICANT_MOTION = 17; // 0x11
+ field public static final int TYPE_STATIONARY_DETECT = 29; // 0x1d
field public static final int TYPE_STEP_COUNTER = 19; // 0x13
field public static final int TYPE_STEP_DETECTOR = 18; // 0x12
field public static final deprecated int TYPE_TEMPERATURE = 7; // 0x7
@@ -13840,6 +13852,7 @@
method public static void getAngleChange(float[], float[], float[]);
method public android.hardware.Sensor getDefaultSensor(int);
method public android.hardware.Sensor getDefaultSensor(int, boolean);
+ method public java.util.List<android.hardware.Sensor> getDynamicSensorList(int);
method public static float getInclination(float[]);
method public static float[] getOrientation(float[], float[]);
method public static void getQuaternionFromVector(float[], float[]);
@@ -13849,6 +13862,8 @@
method public deprecated int getSensors();
method public boolean initDataInjection(boolean);
method public boolean injectSensorData(android.hardware.Sensor, float[], int, long);
+ method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
+ method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback, android.os.Handler);
method public deprecated boolean registerListener(android.hardware.SensorListener, int);
method public deprecated boolean registerListener(android.hardware.SensorListener, int, int);
method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int);
@@ -13857,6 +13872,7 @@
method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int, android.os.Handler);
method public static boolean remapCoordinateSystem(float[], int, int, float[]);
method public boolean requestTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
+ method public void unregisterDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
method public deprecated void unregisterListener(android.hardware.SensorListener);
method public deprecated void unregisterListener(android.hardware.SensorListener, int);
method public void unregisterListener(android.hardware.SensorEventListener, android.hardware.Sensor);
@@ -13921,6 +13937,12 @@
field public static final float STANDARD_GRAVITY = 9.80665f;
}
+ public static abstract class SensorManager.DynamicSensorConnectionCallback {
+ ctor public SensorManager.DynamicSensorConnectionCallback();
+ method public void onDynamicSensorConnected(android.hardware.Sensor);
+ method public void onDynamicSensorDisconnected(android.hardware.Sensor);
+ }
+
public final class TriggerEvent {
field public android.hardware.Sensor sensor;
field public long timestamp;
@@ -20525,6 +20547,7 @@
field public static final int FLAG_BYPASS_MUTE = 128; // 0x80
field public static final int FLAG_HW_AV_SYNC = 16; // 0x10
field public static final int FLAG_HW_HOTWORD = 32; // 0x20
+ field public static final int FLAG_LOW_LATENCY = 256; // 0x100
field public static final int USAGE_ALARM = 4; // 0x4
field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb
field public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12; // 0xc
@@ -20658,6 +20681,7 @@
field public static final int ENCODING_DTS = 7; // 0x7
field public static final int ENCODING_DTS_HD = 8; // 0x8
field public static final int ENCODING_E_AC3 = 6; // 0x6
+ field public static final int ENCODING_IEC61937 = 13; // 0xd
field public static final int ENCODING_INVALID = 0; // 0x0
field public static final int ENCODING_PCM_16BIT = 2; // 0x2
field public static final int ENCODING_PCM_8BIT = 3; // 0x3
@@ -20947,6 +20971,7 @@
method public void flush();
method public int getAudioFormat();
method public int getAudioSessionId();
+ method public int getBufferCapacityInFrames();
method public int getBufferSizeInFrames();
method public int getChannelConfiguration();
method public int getChannelCount();
@@ -20968,6 +20993,7 @@
method public int getState();
method public int getStreamType();
method public boolean getTimestamp(android.media.AudioTimestamp);
+ method public int getUnderrunCount();
method public void pause() throws java.lang.IllegalStateException;
method public void play() throws java.lang.IllegalStateException;
method public void release();
@@ -20975,6 +21001,7 @@
method public deprecated void removeOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener);
method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
method public int setAuxEffectSendLevel(float);
+ method public int setBufferSizeInFrames(int);
method public int setLoopPoints(int, int, int);
method public int setNotificationMarkerPosition(int);
method public int setPlaybackHeadPosition(int);
@@ -21433,6 +21460,7 @@
field public static final deprecated int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00
field public static final deprecated int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
field public static final java.lang.String FEATURE_AdaptivePlayback = "adaptive-playback";
+ field public static final java.lang.String FEATURE_IntraRefresh = "intra-refresh";
field public static final java.lang.String FEATURE_SecurePlayback = "secure-playback";
field public static final java.lang.String FEATURE_TunneledPlayback = "tunneled-playback";
field public int[] colorFormats;
@@ -21475,6 +21503,21 @@
field public static final int AVCProfileHigh422 = 32; // 0x20
field public static final int AVCProfileHigh444 = 64; // 0x40
field public static final int AVCProfileMain = 2; // 0x2
+ field public static final int DolbyVisionLevelFhd24 = 4; // 0x4
+ field public static final int DolbyVisionLevelFhd30 = 8; // 0x8
+ field public static final int DolbyVisionLevelFhd60 = 16; // 0x10
+ field public static final int DolbyVisionLevelHd24 = 1; // 0x1
+ field public static final int DolbyVisionLevelHd30 = 2; // 0x2
+ field public static final int DolbyVisionLevelUhd24 = 32; // 0x20
+ field public static final int DolbyVisionLevelUhd30 = 64; // 0x40
+ field public static final int DolbyVisionLevelUhd48 = 128; // 0x80
+ field public static final int DolbyVisionLevelUhd60 = 256; // 0x100
+ field public static final int DolbyVisionProfileDvavDen = 2; // 0x2
+ field public static final int DolbyVisionProfileDvavDer = 1; // 0x1
+ field public static final int DolbyVisionProfileDvheDen = 4; // 0x4
+ field public static final int DolbyVisionProfileDvheDer = 3; // 0x3
+ field public static final int DolbyVisionProfileDvheDtr = 5; // 0x5
+ field public static final int DolbyVisionProfileDvheStn = 6; // 0x6
field public static final int H263Level10 = 1; // 0x1
field public static final int H263Level20 = 2; // 0x2
field public static final int H263Level30 = 4; // 0x4
@@ -21559,6 +21602,24 @@
field public static final int VP8Level_Version2 = 4; // 0x4
field public static final int VP8Level_Version3 = 8; // 0x8
field public static final int VP8ProfileMain = 1; // 0x1
+ field public static final int VP9Level1 = 0; // 0x0
+ field public static final int VP9Level11 = 1; // 0x1
+ field public static final int VP9Level2 = 2; // 0x2
+ field public static final int VP9Level21 = 4; // 0x4
+ field public static final int VP9Level3 = 8; // 0x8
+ field public static final int VP9Level31 = 16; // 0x10
+ field public static final int VP9Level4 = 32; // 0x20
+ field public static final int VP9Level41 = 64; // 0x40
+ field public static final int VP9Level5 = 128; // 0x80
+ field public static final int VP9Level51 = 256; // 0x100
+ field public static final int VP9Level52 = 512; // 0x200
+ field public static final int VP9Level6 = 1024; // 0x400
+ field public static final int VP9Level61 = 2048; // 0x800
+ field public static final int VP9Level62 = 4096; // 0x1000
+ field public static final int VP9Profile0 = 0; // 0x0
+ field public static final int VP9Profile1 = 1; // 0x1
+ field public static final int VP9Profile2 = 2; // 0x2
+ field public static final int VP9Profile3 = 3; // 0x3
field public int level;
field public int profile;
}
@@ -21786,6 +21847,16 @@
method public final void setInteger(java.lang.String, int);
method public final void setLong(java.lang.String, long);
method public final void setString(java.lang.String, java.lang.String);
+ field public static final int COLOR_RANGE_FULL = 1; // 0x1
+ field public static final int COLOR_RANGE_LIMITED = 2; // 0x2
+ field public static final int COLOR_STANDARD_BT2020 = 6; // 0x6
+ field public static final int COLOR_STANDARD_BT601_NTSC = 4; // 0x4
+ field public static final int COLOR_STANDARD_BT601_PAL = 2; // 0x2
+ field public static final int COLOR_STANDARD_BT709 = 1; // 0x1
+ field public static final int COLOR_TRANSFER_HLG = 7; // 0x7
+ field public static final int COLOR_TRANSFER_LINEAR = 1; // 0x1
+ field public static final int COLOR_TRANSFER_SDR_VIDEO = 3; // 0x3
+ field public static final int COLOR_TRANSFER_ST2084 = 6; // 0x6
field public static final java.lang.String KEY_AAC_DRC_ATTENUATION_FACTOR = "aac-drc-cut-level";
field public static final java.lang.String KEY_AAC_DRC_BOOST_FACTOR = "aac-drc-boost-level";
field public static final java.lang.String KEY_AAC_DRC_HEAVY_COMPRESSION = "aac-drc-heavy-compression";
@@ -21801,11 +21872,15 @@
field public static final java.lang.String KEY_CHANNEL_COUNT = "channel-count";
field public static final java.lang.String KEY_CHANNEL_MASK = "channel-mask";
field public static final java.lang.String KEY_COLOR_FORMAT = "color-format";
+ field public static final java.lang.String KEY_COLOR_RANGE = "color-range";
+ field public static final java.lang.String KEY_COLOR_STANDARD = "color-standard";
+ field public static final java.lang.String KEY_COLOR_TRANSFER = "color-transfer";
field public static final java.lang.String KEY_COMPLEXITY = "complexity";
field public static final java.lang.String KEY_DURATION = "durationUs";
field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
field public static final java.lang.String KEY_HEIGHT = "height";
+ field public static final java.lang.String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
field public static final java.lang.String KEY_IS_ADTS = "is-adts";
field public static final java.lang.String KEY_IS_AUTOSELECT = "is-autoselect";
field public static final java.lang.String KEY_IS_DEFAULT = "is-default";
@@ -22127,9 +22202,11 @@
method public static final int getAudioSourceMax();
method public int getMaxAmplitude() throws java.lang.IllegalStateException;
method public android.view.Surface getSurface();
+ method public void pause() throws java.lang.IllegalStateException;
method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
method public void release();
method public void reset();
+ method public void resume() throws java.lang.IllegalStateException;
method public void setAudioChannels(int);
method public void setAudioEncoder(int) throws java.lang.IllegalStateException;
method public void setAudioEncodingBitRate(int);
@@ -30612,6 +30689,7 @@
field public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1; // 0x1
field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
+ field public static final int SUSTAINED_PERFORMANCE_WAKE_LOCK = 256; // 0x100
field public static final int USER_ACTIVITY_EVENT_BUTTON = 1; // 0x1
field public static final int USER_ACTIVITY_EVENT_OTHER = 0; // 0x0
field public static final int USER_ACTIVITY_EVENT_TOUCH = 2; // 0x2
@@ -34488,6 +34566,7 @@
public class VoicemailContract {
field public static final java.lang.String ACTION_FETCH_VOICEMAIL = "android.intent.action.FETCH_VOICEMAIL";
field public static final java.lang.String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
+ field public static final java.lang.String ACTION_SYNC_VOICEMAIL = "android.intent.action.SYNC_VOICEMAIL";
field public static final java.lang.String AUTHORITY = "com.android.voicemail";
field public static final java.lang.String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
field public static final java.lang.String PARAM_KEY_SOURCE_PACKAGE = "source_package";
@@ -34502,8 +34581,13 @@
field public static final int CONFIGURATION_STATE_OK = 0; // 0x0
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String DATA_CHANNEL_STATE = "data_channel_state";
+ field public static final int DATA_CHANNEL_STATE_BAD_CONFIGURATION = 3; // 0x3
+ field public static final int DATA_CHANNEL_STATE_COMMUNICATION_ERROR = 4; // 0x4
field public static final int DATA_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
+ field public static final int DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED = 2; // 0x2
field public static final int DATA_CHANNEL_STATE_OK = 0; // 0x0
+ field public static final int DATA_CHANNEL_STATE_SERVER_CONNECTION_ERROR = 6; // 0x6
+ field public static final int DATA_CHANNEL_STATE_SERVER_ERROR = 5; // 0x5
field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemail.source.status";
field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail.source.status";
field public static final java.lang.String NOTIFICATION_CHANNEL_STATE = "notification_channel_state";
@@ -34601,6 +34685,7 @@
method public void copyTo(short[]);
method public void copyTo(int[]);
method public void copyTo(float[]);
+ method public static android.renderscript.Allocation[] createAllocations(android.renderscript.RenderScript, android.renderscript.Type, int, int);
method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap);
method public static android.renderscript.Allocation createCubemapFromCubeFaces(android.renderscript.RenderScript, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
@@ -34616,9 +34701,12 @@
method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type, int);
method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type);
method public void generateMipmaps();
+ method public java.nio.ByteBuffer getByteBuffer();
method public int getBytesSize();
method public android.renderscript.Element getElement();
+ method public long getStride();
method public android.view.Surface getSurface();
+ method public long getTimeStamp();
method public android.renderscript.Type getType();
method public int getUsage();
method public void ioReceive();
@@ -36143,6 +36231,7 @@
field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+ field public static final int REASON_PACKAGE_SUSPENDED = 15; // 0xf
field public static final int REASON_TOPIC_BANNED = 14; // 0xe
field public static final int REASON_USER_STOPPED = 6; // 0x6
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
@@ -37638,6 +37727,30 @@
field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
}
+ public abstract class CallScreeningService extends android.app.Service {
+ ctor public CallScreeningService();
+ method public android.os.IBinder onBind(android.content.Intent);
+ method public abstract void onScreenCall(android.telecom.Call.Details);
+ method public final void respondToCall(android.telecom.Call.Details, android.telecom.CallScreeningService.CallResponse);
+ field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.CallScreeningService";
+ }
+
+ public class CallScreeningService.CallResponse {
+ method public boolean getDisallowCall();
+ method public boolean getRejectCall();
+ method public boolean getSkipCallLog();
+ method public boolean getSkipNotification();
+ }
+
+ public class CallScreeningService.CallResponse.Builder {
+ ctor public CallScreeningService.CallResponse.Builder();
+ method public android.telecom.CallScreeningService.CallResponse build();
+ method public android.telecom.CallScreeningService.CallResponse.Builder setDisallowCall(boolean);
+ method public android.telecom.CallScreeningService.CallResponse.Builder setRejectCall(boolean);
+ method public android.telecom.CallScreeningService.CallResponse.Builder setSkipCallLog(boolean);
+ method public android.telecom.CallScreeningService.CallResponse.Builder setSkipNotification(boolean);
+ }
+
public abstract class Conference extends android.telecom.Conferenceable {
ctor public Conference(android.telecom.PhoneAccountHandle);
method public final boolean addConnection(android.telecom.Connection);
@@ -37887,6 +38000,7 @@
method public void onCanAddCallChanged(boolean);
method public deprecated void onPhoneCreated(android.telecom.Phone);
method public deprecated void onPhoneDestroyed(android.telecom.Phone);
+ method public void onSilenceRinger();
method public final void setAudioRoute(int);
method public final void setMuted(boolean);
field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.InCallService";
@@ -37968,6 +38082,7 @@
method public void onCallAudioStateChanged(android.telecom.Phone, android.telecom.CallAudioState);
method public void onCallRemoved(android.telecom.Phone, android.telecom.Call);
method public void onCanAddCallChanged(android.telecom.Phone, boolean);
+ method public void onSilenceRinger(android.telecom.Phone);
}
public final class PhoneAccount implements android.os.Parcelable {
@@ -38227,6 +38342,7 @@
field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
+ field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
field public static final int PRESENTATION_ALLOWED = 1; // 0x1
field public static final int PRESENTATION_PAYPHONE = 4; // 0x4
@@ -38380,6 +38496,7 @@
field public static final java.lang.String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN = "vvm_cellular_data_required";
field public static final java.lang.String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string";
field public static final java.lang.String KEY_VVM_PORT_NUMBER_INT = "vvm_port_number_int";
+ field public static final java.lang.String KEY_VVM_PREFETCH_BOOLEAN = "vvm_prefetch";
field public static final java.lang.String KEY_VVM_TYPE_STRING = "vvm_type_string";
field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
}
@@ -38397,6 +38514,8 @@
public final class CellIdentityGsm implements android.os.Parcelable {
method public int describeContents();
+ method public int getArfcn();
+ method public int getBsic();
method public int getCid();
method public int getLac();
method public int getMcc();
@@ -38409,6 +38528,7 @@
public final class CellIdentityLte implements android.os.Parcelable {
method public int describeContents();
method public int getCi();
+ method public int getEarfcn();
method public int getMcc();
method public int getMnc();
method public int getPci();
@@ -38424,6 +38544,7 @@
method public int getMcc();
method public int getMnc();
method public int getPsc();
+ method public int getUarfcn();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityWcdma> CREATOR;
}
@@ -52679,6 +52800,9 @@
field public static final java.lang.Class<java.lang.Float> TYPE;
}
+ public abstract class FunctionalInterface implements java.lang.annotation.Annotation {
+ }
+
public class IllegalAccessError extends java.lang.IncompatibleClassChangeError {
ctor public IllegalAccessError();
ctor public IllegalAccessError(java.lang.String);
diff --git a/api/test-current.txt b/api/test-current.txt
index b5a7bca..57332a2 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -33,6 +33,7 @@
field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+ field public static final java.lang.String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
@@ -5790,6 +5791,7 @@
method public void clearCrossProfileIntentFilters(android.content.ComponentName);
method public void clearDeviceOwnerApp(java.lang.String);
method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
+ method public void clearProfileOwner(android.content.ComponentName);
method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
method public deprecated android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
method public android.os.UserHandle createAndManageUser(android.content.ComponentName, java.lang.String, android.content.ComponentName, android.os.PersistableBundle, int);
@@ -13364,6 +13366,7 @@
method public float getResolution();
method public java.lang.String getStringType();
method public int getType();
+ method public java.util.UUID getUuid();
method public java.lang.String getVendor();
method public int getVersion();
method public boolean isWakeUpSensor();
@@ -13378,11 +13381,13 @@
field public static final java.lang.String STRING_TYPE_GRAVITY = "android.sensor.gravity";
field public static final java.lang.String STRING_TYPE_GYROSCOPE = "android.sensor.gyroscope";
field public static final java.lang.String STRING_TYPE_GYROSCOPE_UNCALIBRATED = "android.sensor.gyroscope_uncalibrated";
+ field public static final java.lang.String STRING_TYPE_HEART_BEAT = "android.sensor.heart_beat";
field public static final java.lang.String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";
field public static final java.lang.String STRING_TYPE_LIGHT = "android.sensor.light";
field public static final java.lang.String STRING_TYPE_LINEAR_ACCELERATION = "android.sensor.linear_acceleration";
field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD = "android.sensor.magnetic_field";
field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED = "android.sensor.magnetic_field_uncalibrated";
+ field public static final java.lang.String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";
field public static final deprecated java.lang.String STRING_TYPE_ORIENTATION = "android.sensor.orientation";
field public static final java.lang.String STRING_TYPE_POSE_6DOF = "android.sensor.pose_6dof";
field public static final java.lang.String STRING_TYPE_PRESSURE = "android.sensor.pressure";
@@ -13390,6 +13395,7 @@
field public static final java.lang.String STRING_TYPE_RELATIVE_HUMIDITY = "android.sensor.relative_humidity";
field public static final java.lang.String STRING_TYPE_ROTATION_VECTOR = "android.sensor.rotation_vector";
field public static final java.lang.String STRING_TYPE_SIGNIFICANT_MOTION = "android.sensor.significant_motion";
+ field public static final java.lang.String STRING_TYPE_STATIONARY_DETECT = "android.sensor.stationary_detect";
field public static final java.lang.String STRING_TYPE_STEP_COUNTER = "android.sensor.step_counter";
field public static final java.lang.String STRING_TYPE_STEP_DETECTOR = "android.sensor.step_detector";
field public static final deprecated java.lang.String STRING_TYPE_TEMPERATURE = "android.sensor.temperature";
@@ -13401,11 +13407,13 @@
field public static final int TYPE_GRAVITY = 9; // 0x9
field public static final int TYPE_GYROSCOPE = 4; // 0x4
field public static final int TYPE_GYROSCOPE_UNCALIBRATED = 16; // 0x10
+ field public static final int TYPE_HEART_BEAT = 31; // 0x1f
field public static final int TYPE_HEART_RATE = 21; // 0x15
field public static final int TYPE_LIGHT = 5; // 0x5
field public static final int TYPE_LINEAR_ACCELERATION = 10; // 0xa
field public static final int TYPE_MAGNETIC_FIELD = 2; // 0x2
field public static final int TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14; // 0xe
+ field public static final int TYPE_MOTION_DETECT = 30; // 0x1e
field public static final deprecated int TYPE_ORIENTATION = 3; // 0x3
field public static final int TYPE_POSE_6DOF = 28; // 0x1c
field public static final int TYPE_PRESSURE = 6; // 0x6
@@ -13413,6 +13421,7 @@
field public static final int TYPE_RELATIVE_HUMIDITY = 12; // 0xc
field public static final int TYPE_ROTATION_VECTOR = 11; // 0xb
field public static final int TYPE_SIGNIFICANT_MOTION = 17; // 0x11
+ field public static final int TYPE_STATIONARY_DETECT = 29; // 0x1d
field public static final int TYPE_STEP_COUNTER = 19; // 0x13
field public static final int TYPE_STEP_DETECTOR = 18; // 0x12
field public static final deprecated int TYPE_TEMPERATURE = 7; // 0x7
@@ -13446,6 +13455,7 @@
method public static void getAngleChange(float[], float[], float[]);
method public android.hardware.Sensor getDefaultSensor(int);
method public android.hardware.Sensor getDefaultSensor(int, boolean);
+ method public java.util.List<android.hardware.Sensor> getDynamicSensorList(int);
method public static float getInclination(float[]);
method public static float[] getOrientation(float[], float[]);
method public static void getQuaternionFromVector(float[], float[]);
@@ -13453,6 +13463,8 @@
method public static void getRotationMatrixFromVector(float[], float[]);
method public java.util.List<android.hardware.Sensor> getSensorList(int);
method public deprecated int getSensors();
+ method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
+ method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback, android.os.Handler);
method public deprecated boolean registerListener(android.hardware.SensorListener, int);
method public deprecated boolean registerListener(android.hardware.SensorListener, int, int);
method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int);
@@ -13461,6 +13473,7 @@
method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int, android.os.Handler);
method public static boolean remapCoordinateSystem(float[], int, int, float[]);
method public boolean requestTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
+ method public void unregisterDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
method public deprecated void unregisterListener(android.hardware.SensorListener);
method public deprecated void unregisterListener(android.hardware.SensorListener, int);
method public void unregisterListener(android.hardware.SensorEventListener, android.hardware.Sensor);
@@ -13525,6 +13538,12 @@
field public static final float STANDARD_GRAVITY = 9.80665f;
}
+ public static abstract class SensorManager.DynamicSensorConnectionCallback {
+ ctor public SensorManager.DynamicSensorConnectionCallback();
+ method public void onDynamicSensorConnected(android.hardware.Sensor);
+ method public void onDynamicSensorDisconnected(android.hardware.Sensor);
+ }
+
public final class TriggerEvent {
field public android.hardware.Sensor sensor;
field public long timestamp;
@@ -19209,6 +19228,7 @@
field public static final android.os.Parcelable.Creator<android.media.AudioAttributes> CREATOR;
field public static final int FLAG_AUDIBILITY_ENFORCED = 1; // 0x1
field public static final int FLAG_HW_AV_SYNC = 16; // 0x10
+ field public static final int FLAG_LOW_LATENCY = 256; // 0x100
field public static final int USAGE_ALARM = 4; // 0x4
field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb
field public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12; // 0xc
@@ -19328,6 +19348,7 @@
field public static final int ENCODING_DTS = 7; // 0x7
field public static final int ENCODING_DTS_HD = 8; // 0x8
field public static final int ENCODING_E_AC3 = 6; // 0x6
+ field public static final int ENCODING_IEC61937 = 13; // 0xd
field public static final int ENCODING_INVALID = 0; // 0x0
field public static final int ENCODING_PCM_16BIT = 2; // 0x2
field public static final int ENCODING_PCM_8BIT = 3; // 0x3
@@ -19605,6 +19626,7 @@
method public void flush();
method public int getAudioFormat();
method public int getAudioSessionId();
+ method public int getBufferCapacityInFrames();
method public int getBufferSizeInFrames();
method public int getChannelConfiguration();
method public int getChannelCount();
@@ -19626,6 +19648,7 @@
method public int getState();
method public int getStreamType();
method public boolean getTimestamp(android.media.AudioTimestamp);
+ method public int getUnderrunCount();
method public void pause() throws java.lang.IllegalStateException;
method public void play() throws java.lang.IllegalStateException;
method public void release();
@@ -19633,6 +19656,7 @@
method public deprecated void removeOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener);
method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
method public int setAuxEffectSendLevel(float);
+ method public int setBufferSizeInFrames(int);
method public int setLoopPoints(int, int, int);
method public int setNotificationMarkerPosition(int);
method public int setPlaybackHeadPosition(int);
@@ -20091,6 +20115,7 @@
field public static final deprecated int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00
field public static final deprecated int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
field public static final java.lang.String FEATURE_AdaptivePlayback = "adaptive-playback";
+ field public static final java.lang.String FEATURE_IntraRefresh = "intra-refresh";
field public static final java.lang.String FEATURE_SecurePlayback = "secure-playback";
field public static final java.lang.String FEATURE_TunneledPlayback = "tunneled-playback";
field public int[] colorFormats;
@@ -20133,6 +20158,21 @@
field public static final int AVCProfileHigh422 = 32; // 0x20
field public static final int AVCProfileHigh444 = 64; // 0x40
field public static final int AVCProfileMain = 2; // 0x2
+ field public static final int DolbyVisionLevelFhd24 = 4; // 0x4
+ field public static final int DolbyVisionLevelFhd30 = 8; // 0x8
+ field public static final int DolbyVisionLevelFhd60 = 16; // 0x10
+ field public static final int DolbyVisionLevelHd24 = 1; // 0x1
+ field public static final int DolbyVisionLevelHd30 = 2; // 0x2
+ field public static final int DolbyVisionLevelUhd24 = 32; // 0x20
+ field public static final int DolbyVisionLevelUhd30 = 64; // 0x40
+ field public static final int DolbyVisionLevelUhd48 = 128; // 0x80
+ field public static final int DolbyVisionLevelUhd60 = 256; // 0x100
+ field public static final int DolbyVisionProfileDvavDen = 2; // 0x2
+ field public static final int DolbyVisionProfileDvavDer = 1; // 0x1
+ field public static final int DolbyVisionProfileDvheDen = 4; // 0x4
+ field public static final int DolbyVisionProfileDvheDer = 3; // 0x3
+ field public static final int DolbyVisionProfileDvheDtr = 5; // 0x5
+ field public static final int DolbyVisionProfileDvheStn = 6; // 0x6
field public static final int H263Level10 = 1; // 0x1
field public static final int H263Level20 = 2; // 0x2
field public static final int H263Level30 = 4; // 0x4
@@ -20217,6 +20257,24 @@
field public static final int VP8Level_Version2 = 4; // 0x4
field public static final int VP8Level_Version3 = 8; // 0x8
field public static final int VP8ProfileMain = 1; // 0x1
+ field public static final int VP9Level1 = 0; // 0x0
+ field public static final int VP9Level11 = 1; // 0x1
+ field public static final int VP9Level2 = 2; // 0x2
+ field public static final int VP9Level21 = 4; // 0x4
+ field public static final int VP9Level3 = 8; // 0x8
+ field public static final int VP9Level31 = 16; // 0x10
+ field public static final int VP9Level4 = 32; // 0x20
+ field public static final int VP9Level41 = 64; // 0x40
+ field public static final int VP9Level5 = 128; // 0x80
+ field public static final int VP9Level51 = 256; // 0x100
+ field public static final int VP9Level52 = 512; // 0x200
+ field public static final int VP9Level6 = 1024; // 0x400
+ field public static final int VP9Level61 = 2048; // 0x800
+ field public static final int VP9Level62 = 4096; // 0x1000
+ field public static final int VP9Profile0 = 0; // 0x0
+ field public static final int VP9Profile1 = 1; // 0x1
+ field public static final int VP9Profile2 = 2; // 0x2
+ field public static final int VP9Profile3 = 3; // 0x3
field public int level;
field public int profile;
}
@@ -20444,6 +20502,16 @@
method public final void setInteger(java.lang.String, int);
method public final void setLong(java.lang.String, long);
method public final void setString(java.lang.String, java.lang.String);
+ field public static final int COLOR_RANGE_FULL = 1; // 0x1
+ field public static final int COLOR_RANGE_LIMITED = 2; // 0x2
+ field public static final int COLOR_STANDARD_BT2020 = 6; // 0x6
+ field public static final int COLOR_STANDARD_BT601_NTSC = 4; // 0x4
+ field public static final int COLOR_STANDARD_BT601_PAL = 2; // 0x2
+ field public static final int COLOR_STANDARD_BT709 = 1; // 0x1
+ field public static final int COLOR_TRANSFER_HLG = 7; // 0x7
+ field public static final int COLOR_TRANSFER_LINEAR = 1; // 0x1
+ field public static final int COLOR_TRANSFER_SDR_VIDEO = 3; // 0x3
+ field public static final int COLOR_TRANSFER_ST2084 = 6; // 0x6
field public static final java.lang.String KEY_AAC_DRC_ATTENUATION_FACTOR = "aac-drc-cut-level";
field public static final java.lang.String KEY_AAC_DRC_BOOST_FACTOR = "aac-drc-boost-level";
field public static final java.lang.String KEY_AAC_DRC_HEAVY_COMPRESSION = "aac-drc-heavy-compression";
@@ -20459,11 +20527,15 @@
field public static final java.lang.String KEY_CHANNEL_COUNT = "channel-count";
field public static final java.lang.String KEY_CHANNEL_MASK = "channel-mask";
field public static final java.lang.String KEY_COLOR_FORMAT = "color-format";
+ field public static final java.lang.String KEY_COLOR_RANGE = "color-range";
+ field public static final java.lang.String KEY_COLOR_STANDARD = "color-standard";
+ field public static final java.lang.String KEY_COLOR_TRANSFER = "color-transfer";
field public static final java.lang.String KEY_COMPLEXITY = "complexity";
field public static final java.lang.String KEY_DURATION = "durationUs";
field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
field public static final java.lang.String KEY_HEIGHT = "height";
+ field public static final java.lang.String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
field public static final java.lang.String KEY_IS_ADTS = "is-adts";
field public static final java.lang.String KEY_IS_AUTOSELECT = "is-autoselect";
field public static final java.lang.String KEY_IS_DEFAULT = "is-default";
@@ -20785,9 +20857,11 @@
method public static final int getAudioSourceMax();
method public int getMaxAmplitude() throws java.lang.IllegalStateException;
method public android.view.Surface getSurface();
+ method public void pause() throws java.lang.IllegalStateException;
method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
method public void release();
method public void reset();
+ method public void resume() throws java.lang.IllegalStateException;
method public void setAudioChannels(int);
method public void setAudioEncoder(int) throws java.lang.IllegalStateException;
method public void setAudioEncodingBitRate(int);
@@ -28542,6 +28616,7 @@
field public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1; // 0x1
field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
+ field public static final int SUSTAINED_PERFORMANCE_WAKE_LOCK = 256; // 0x100
}
public final class PowerManager.WakeLock {
@@ -32277,6 +32352,7 @@
public class VoicemailContract {
field public static final java.lang.String ACTION_FETCH_VOICEMAIL = "android.intent.action.FETCH_VOICEMAIL";
field public static final java.lang.String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
+ field public static final java.lang.String ACTION_SYNC_VOICEMAIL = "android.intent.action.SYNC_VOICEMAIL";
field public static final java.lang.String AUTHORITY = "com.android.voicemail";
field public static final java.lang.String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
field public static final java.lang.String PARAM_KEY_SOURCE_PACKAGE = "source_package";
@@ -32291,8 +32367,13 @@
field public static final int CONFIGURATION_STATE_OK = 0; // 0x0
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String DATA_CHANNEL_STATE = "data_channel_state";
+ field public static final int DATA_CHANNEL_STATE_BAD_CONFIGURATION = 3; // 0x3
+ field public static final int DATA_CHANNEL_STATE_COMMUNICATION_ERROR = 4; // 0x4
field public static final int DATA_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
+ field public static final int DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED = 2; // 0x2
field public static final int DATA_CHANNEL_STATE_OK = 0; // 0x0
+ field public static final int DATA_CHANNEL_STATE_SERVER_CONNECTION_ERROR = 6; // 0x6
+ field public static final int DATA_CHANNEL_STATE_SERVER_ERROR = 5; // 0x5
field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemail.source.status";
field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail.source.status";
field public static final java.lang.String NOTIFICATION_CHANNEL_STATE = "notification_channel_state";
@@ -32390,6 +32471,7 @@
method public void copyTo(short[]);
method public void copyTo(int[]);
method public void copyTo(float[]);
+ method public static android.renderscript.Allocation[] createAllocations(android.renderscript.RenderScript, android.renderscript.Type, int, int);
method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap);
method public static android.renderscript.Allocation createCubemapFromCubeFaces(android.renderscript.RenderScript, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
@@ -32405,9 +32487,12 @@
method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type, int);
method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type);
method public void generateMipmaps();
+ method public java.nio.ByteBuffer getByteBuffer();
method public int getBytesSize();
method public android.renderscript.Element getElement();
+ method public long getStride();
method public android.view.Surface getSurface();
+ method public long getTimeStamp();
method public android.renderscript.Type getType();
method public int getUsage();
method public void ioReceive();
@@ -33932,6 +34017,7 @@
field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+ field public static final int REASON_PACKAGE_SUSPENDED = 15; // 0xf
field public static final int REASON_TOPIC_BANNED = 14; // 0xe
field public static final int REASON_USER_STOPPED = 6; // 0x6
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
@@ -35347,6 +35433,30 @@
field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
}
+ public abstract class CallScreeningService extends android.app.Service {
+ ctor public CallScreeningService();
+ method public android.os.IBinder onBind(android.content.Intent);
+ method public abstract void onScreenCall(android.telecom.Call.Details);
+ method public final void respondToCall(android.telecom.Call.Details, android.telecom.CallScreeningService.CallResponse);
+ field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.CallScreeningService";
+ }
+
+ public class CallScreeningService.CallResponse {
+ method public boolean getDisallowCall();
+ method public boolean getRejectCall();
+ method public boolean getSkipCallLog();
+ method public boolean getSkipNotification();
+ }
+
+ public class CallScreeningService.CallResponse.Builder {
+ ctor public CallScreeningService.CallResponse.Builder();
+ method public android.telecom.CallScreeningService.CallResponse build();
+ method public android.telecom.CallScreeningService.CallResponse.Builder setDisallowCall(boolean);
+ method public android.telecom.CallScreeningService.CallResponse.Builder setRejectCall(boolean);
+ method public android.telecom.CallScreeningService.CallResponse.Builder setSkipCallLog(boolean);
+ method public android.telecom.CallScreeningService.CallResponse.Builder setSkipNotification(boolean);
+ }
+
public abstract class Conference extends android.telecom.Conferenceable {
ctor public Conference(android.telecom.PhoneAccountHandle);
method public final boolean addConnection(android.telecom.Connection);
@@ -35586,6 +35696,7 @@
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
method public void onCallRemoved(android.telecom.Call);
method public void onCanAddCallChanged(boolean);
+ method public void onSilenceRinger();
method public final void setAudioRoute(int);
method public final void setMuted(boolean);
field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.InCallService";
@@ -35846,6 +35957,7 @@
field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
+ field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
field public static final int PRESENTATION_ALLOWED = 1; // 0x1
field public static final int PRESENTATION_PAYPHONE = 4; // 0x4
@@ -35997,6 +36109,7 @@
field public static final java.lang.String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN = "vvm_cellular_data_required";
field public static final java.lang.String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string";
field public static final java.lang.String KEY_VVM_PORT_NUMBER_INT = "vvm_port_number_int";
+ field public static final java.lang.String KEY_VVM_PREFETCH_BOOLEAN = "vvm_prefetch";
field public static final java.lang.String KEY_VVM_TYPE_STRING = "vvm_type_string";
field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
}
@@ -36014,6 +36127,8 @@
public final class CellIdentityGsm implements android.os.Parcelable {
method public int describeContents();
+ method public int getArfcn();
+ method public int getBsic();
method public int getCid();
method public int getLac();
method public int getMcc();
@@ -36026,6 +36141,7 @@
public final class CellIdentityLte implements android.os.Parcelable {
method public int describeContents();
method public int getCi();
+ method public int getEarfcn();
method public int getMcc();
method public int getMnc();
method public int getPci();
@@ -36041,6 +36157,7 @@
method public int getMcc();
method public int getMnc();
method public int getPsc();
+ method public int getUarfcn();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityWcdma> CREATOR;
}
@@ -49898,6 +50015,9 @@
field public static final java.lang.Class<java.lang.Float> TYPE;
}
+ public abstract class FunctionalInterface implements java.lang.annotation.Annotation {
+ }
+
public class IllegalAccessError extends java.lang.IncompatibleClassChangeError {
ctor public IllegalAccessError();
ctor public IllegalAccessError(java.lang.String);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index e36a427..11154f2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2313,7 +2313,7 @@
* <p>In order to use a Toolbar within the Activity's window content the application
* must not request the window feature {@link Window#FEATURE_ACTION_BAR FEATURE_ACTION_BAR}.</p>
*
- * @param toolbar Toolbar to set as the Activity's action bar
+ * @param toolbar Toolbar to set as the Activity's action bar, or {@code null} to clear it
*/
public void setActionBar(@Nullable Toolbar toolbar) {
final ActionBar ab = getActionBar();
@@ -2332,10 +2332,17 @@
ab.onDestroy();
}
- ToolbarActionBar tbab = new ToolbarActionBar(toolbar, getTitle(), this);
- mActionBar = tbab;
- mWindow.setCallback(tbab.getWrappedWindowCallback());
- mActionBar.invalidateOptionsMenu();
+ if (toolbar != null) {
+ final ToolbarActionBar tbab = new ToolbarActionBar(toolbar, getTitle(), this);
+ mActionBar = tbab;
+ mWindow.setCallback(tbab.getWrappedWindowCallback());
+ } else {
+ mActionBar = null;
+ // Re-set the original window callback since we may have already set a Toolbar wrapper
+ mWindow.setCallback(this);
+ }
+
+ invalidateOptionsMenu();
}
/**
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index fc1a355..5eed781 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -17,6 +17,7 @@
package android.app;
import com.android.internal.app.IAppOpsService;
+import com.android.internal.app.ISoundTriggerService;
import com.android.internal.appwidget.IAppWidgetService;
import com.android.internal.os.IDropBoxManagerService;
@@ -61,6 +62,7 @@
import android.media.midi.MidiManager;
import android.media.projection.MediaProjectionManager;
import android.media.session.MediaSessionManager;
+import android.media.soundtrigger.SoundTriggerManager;
import android.media.tv.ITvInputManager;
import android.media.tv.TvInputManager;
import android.net.ConnectivityManager;
@@ -708,12 +710,22 @@
public RadioManager createService(ContextImpl ctx) {
return new RadioManager(ctx);
}});
+
registerService(Context.HARDWARE_PROPERTIES_SERVICE, HardwarePropertiesManager.class,
new CachedServiceFetcher<HardwarePropertiesManager>() {
@Override
public HardwarePropertiesManager createService(ContextImpl ctx) {
return new HardwarePropertiesManager();
}});
+
+ registerService(Context.SOUND_TRIGGER_SERVICE, SoundTriggerManager.class,
+ new CachedServiceFetcher<SoundTriggerManager>() {
+ @Override
+ public SoundTriggerManager createService(ContextImpl ctx) {
+ IBinder b = ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE);
+ Log.i(TAG, "Creating new instance of SoundTriggerManager object.");
+ return new SoundTriggerManager(ctx, ISoundTriggerService.Stub.asInterface(b));
+ }});
}
/**
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 1c1526f..fef2a0e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2770,6 +2770,45 @@
}
/**
+ * Called by a device owner to set whether all users created on the device should be ephemeral.
+ *
+ * <p>The system user is exempt from this policy - it is never ephemeral.
+ *
+ * <p>The calling device admin must be the device owner. If it is not, a security exception will
+ * be thrown.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param forceEphemeralUsers If true, all the existing users will be deleted and all
+ * subsequently created users will be ephemeral.
+ * @hide
+ */
+ public void setForceEphemeralUsers(
+ @NonNull ComponentName admin, boolean forceEphemeralUsers) {
+ if (mService != null) {
+ try {
+ mService.setForceEphemeralUsers(admin, forceEphemeralUsers);
+ } catch (RemoteException e) {
+ Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ }
+ }
+ }
+
+ /**
+ * @return true if all users are created ephemeral.
+ * @hide
+ */
+ public boolean getForceEphemeralUsers(@NonNull ComponentName admin) {
+ if (mService != null) {
+ try {
+ return mService.getForceEphemeralUsers(admin);
+ } catch (RemoteException e) {
+ Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ }
+ }
+ return false;
+ }
+
+ /**
* Called by an application that is administering the device to disable keyguard customizations,
* such as widgets. After setting this, keyguard features will be disabled according to the
* provided feature list.
@@ -3205,15 +3244,14 @@
}
/**
- * @hide
* Clears the active profile owner and removes all user restrictions. The caller must
* be from the same package as the active profile owner for this user, otherwise a
* SecurityException will be thrown.
*
+ * <p>This doesn't work for managed profile owners.
+ *
* @param admin The component to remove as the profile owner.
- * @return
*/
- @SystemApi
public void clearProfileOwner(@NonNull ComponentName admin) {
if (mService != null) {
try {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index a80ed9b..20d4a29 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -230,6 +230,9 @@
void setAutoTimeRequired(in ComponentName who, boolean required);
boolean getAutoTimeRequired();
+ void setForceEphemeralUsers(in ComponentName who, boolean forceEpehemeralUsers);
+ boolean getForceEphemeralUsers(in ComponentName who);
+
boolean isRemovingAdmin(in ComponentName adminReceiver, int userHandle);
void setUserIcon(in ComponentName admin, in Bitmap icon);
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 3660be7..6b5f77f 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -23,6 +23,7 @@
import android.bluetooth.le.ScanSettings;
import android.bluetooth.le.ResultStorageDescriptor;
import android.os.ParcelUuid;
+import android.os.WorkSource;
import android.bluetooth.IBluetoothGattCallback;
import android.bluetooth.IBluetoothGattServerCallback;
@@ -35,8 +36,8 @@
List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
void startScan(in int appIf, in boolean isServer, in ScanSettings settings,
- in List<ScanFilter> filters,
- in List scanStorages, in String callingPackage);
+ in List<ScanFilter> filters, in WorkSource workSource, in List scanStorages,
+ in String callingPackage);
void stopScan(in int appIf, in boolean isServer);
void flushPendingBatchResults(in int appIf, in boolean isServer);
void startMultiAdvertising(in int appIf,
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index 2ba87744..03449cc 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -29,6 +29,7 @@
import android.os.Looper;
import android.os.ParcelUuid;
import android.os.RemoteException;
+import android.os.WorkSource;
import android.util.Log;
import java.util.ArrayList;
@@ -89,9 +90,6 @@
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public void startScan(final ScanCallback callback) {
- if (callback == null) {
- throw new IllegalArgumentException("callback is null");
- }
startScan(null, new ScanSettings.Builder().build(), callback);
}
@@ -112,14 +110,53 @@
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public void startScan(List<ScanFilter> filters, ScanSettings settings,
final ScanCallback callback) {
- startScan(filters, settings, callback, null);
+ startScan(filters, settings, null, callback, null);
+ }
+
+ /**
+ * Start Bluetooth LE scan. Same as {@link #startScan(ScanCallback)} but allows the caller to
+ * specify on behalf of which application(s) the work is being done.
+ *
+ * @param workSource {@link WorkSource} identifying the application(s) for which to blame for
+ * the scan.
+ * @param callback Callback used to deliver scan results.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(allOf = {
+ Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS })
+ public void startScanFromSource(final WorkSource workSource, final ScanCallback callback) {
+ startScanFromSource(null, new ScanSettings.Builder().build(), workSource, callback);
+ }
+
+ /**
+ * Start Bluetooth LE scan. Same as {@link #startScan(List, ScanSettings, ScanCallback)} but
+ * allows the caller to specify on behalf of which application(s) the work is being done.
+ *
+ * @param filters {@link ScanFilter}s for finding exact BLE devices.
+ * @param settings Settings for the scan.
+ * @param workSource {@link WorkSource} identifying the application(s) for which to blame for
+ * the scan.
+ * @param callback Callback used to deliver scan results.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(allOf = {
+ Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS })
+ public void startScanFromSource(List<ScanFilter> filters, ScanSettings settings,
+ final WorkSource workSource, final ScanCallback callback) {
+ startScan(filters, settings, workSource, callback, null);
}
private void startScan(List<ScanFilter> filters, ScanSettings settings,
- final ScanCallback callback, List<List<ResultStorageDescriptor>> resultStorages) {
+ final WorkSource workSource, final ScanCallback callback,
+ List<List<ResultStorageDescriptor>> resultStorages) {
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
- if (settings == null || callback == null) {
- throw new IllegalArgumentException("settings or callback is null");
+ if (callback == null) {
+ throw new IllegalArgumentException("callback is null");
+ }
+ if (settings == null) {
+ throw new IllegalArgumentException("settings is null");
}
synchronized (mLeScanClients) {
if (mLeScanClients.containsKey(callback)) {
@@ -152,7 +189,7 @@
return;
}
BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
- settings, callback, resultStorages);
+ settings, workSource, callback, resultStorages);
wrapper.startRegisteration();
}
}
@@ -215,7 +252,7 @@
scanFilters.add(filter.getFilter());
scanStorages.add(filter.getStorageDescriptors());
}
- startScan(scanFilters, settings, callback, scanStorages);
+ startScan(scanFilters, settings, null, callback, scanStorages);
}
/**
@@ -235,6 +272,7 @@
private final ScanCallback mScanCallback;
private final List<ScanFilter> mFilters;
+ private final WorkSource mWorkSource;
private ScanSettings mSettings;
private IBluetoothGatt mBluetoothGatt;
private List<List<ResultStorageDescriptor>> mResultStorages;
@@ -246,10 +284,12 @@
public BleScanCallbackWrapper(IBluetoothGatt bluetoothGatt,
List<ScanFilter> filters, ScanSettings settings,
- ScanCallback scanCallback, List<List<ResultStorageDescriptor>> resultStorages) {
+ WorkSource workSource, ScanCallback scanCallback,
+ List<List<ResultStorageDescriptor>> resultStorages) {
mBluetoothGatt = bluetoothGatt;
mFilters = filters;
mSettings = settings;
+ mWorkSource = workSource;
mScanCallback = scanCallback;
mClientIf = 0;
mResultStorages = resultStorages;
@@ -322,7 +362,9 @@
mClientIf = clientIf;
try {
mBluetoothGatt.startScan(mClientIf, false, mSettings, mFilters,
- mResultStorages, ActivityThread.currentOpPackageName());
+ mWorkSource, mResultStorages,
+ ActivityThread.currentOpPackageName());
+
} catch (RemoteException e) {
Log.e(TAG, "fail to start le scan: " + e);
mClientIf = -1;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 27cdd50..3142b40 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2613,6 +2613,7 @@
MIDI_SERVICE,
RADIO_SERVICE,
HARDWARE_PROPERTIES_SERVICE,
+ //@hide: SOUND_TRIGGER_SERVICE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ServiceName {}
@@ -3195,6 +3196,16 @@
public static final String VOICE_INTERACTION_MANAGER_SERVICE = "voiceinteraction";
/**
+ * Use with {@link #getSystemService} to access the
+ * {@link com.android.server.voiceinteraction.SoundTriggerService}.
+ *
+ * @hide
+ * @see #getSystemService
+ */
+ public static final String SOUND_TRIGGER_SERVICE = "soundtrigger";
+
+
+ /**
* Use with {@link #getSystemService} to retrieve an
* {@link android.app.backup.IBackupManager IBackupManager} for communicating
* with the backup mechanism.
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 06da4955..158a284 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2618,8 +2618,7 @@
* turned off</li>
* </ul>
*
- * <p class="note">This is a protected intent that can only be sent
- * by the system.
+ * <p class="note">This is a protected intent that can only be sent by the system.</p>
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE";
@@ -3210,6 +3209,18 @@
public static final String
ACTION_OPEN_EXTERNAL_DIRECTORY = "android.intent.action.OPEN_EXTERNAL_DIRECTORY";
+ /**
+ * Broadcast Action: List of dynamic sensor is changed due to new sensor being connected or
+ * exisiting sensor being disconnected.
+ *
+ * <p class="note">This is a protected intent that can only be sent by the system.</p>
+ *
+ * {@hide}
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String
+ ACTION_DYNAMIC_SENSOR_CHANGED = "android.intent.action.DYNAMIC_SENSOR_CHANGED";
+
/** {@hide} */
public static final String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
@@ -5698,6 +5709,9 @@
case "--receiver-replace-pending":
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
break;
+ case "--receiver-foreground":
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ break;
case "--selector":
intent.setDataAndType(data, type);
intent = new Intent();
@@ -5807,6 +5821,7 @@
" [--esal <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]",
" (mutiple extras passed as List<String>; to embed a comma into a string,",
" escape it using \"\\,\")",
+ " [--f <FLAG>]",
" [--grant-read-uri-permission] [--grant-write-uri-permission]",
" [--grant-persistable-uri-permission] [--grant-prefix-uri-permission]",
" [--debug-log-resolution] [--exclude-stopped-packages]",
@@ -5820,6 +5835,7 @@
" [--activity-single-top] [--activity-clear-task]",
" [--activity-task-on-home]",
" [--receiver-registered-only] [--receiver-replace-pending]",
+ " [--receiver-foreground]",
" [--selector]",
" [<URI> | <PACKAGE> | <COMPONENT>]"
};
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index e5efd56..841e5b0 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -17,8 +17,10 @@
package android.hardware;
-import android.os.Build;
import android.annotation.SystemApi;
+import android.os.Build;
+
+import java.util.UUID;
/**
* Class representing a sensor. Use {@link SensorManager#getSensorList} to get
@@ -557,6 +559,8 @@
* Similar to {@link #TYPE_ROTATION_VECTOR}, with additional delta
* translation from an arbitrary reference point.
*
+ * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
+ *
* Can use camera, depth sensor etc to compute output value.
*
* This is expected to be a high power sensor and expected only to be
@@ -574,9 +578,78 @@
*/
public static final String STRING_TYPE_POSE_6DOF = "android.sensor.pose_6dof";
+ /**
+ * A constant describing a stationary detect sensor.
+ *
+ * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
+ *
+ */
+ public static final int TYPE_STATIONARY_DETECT = 29;
+
+ /**
+ * A constant string describing a stationary detection sensor.
+ *
+ * @see #TYPE_STATIONARY_DETECT
+ */
+ public static final String STRING_TYPE_STATIONARY_DETECT = "android.sensor.stationary_detect";
+
+ /**
+ * A constant describing a motion detect sensor.
+ *
+ * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
+ *
+ */
+ public static final int TYPE_MOTION_DETECT = 30;
+
+ /**
+ * A constant string describing a motion detection sensor.
+ *
+ * @see #TYPE_MOTION_DETECT
+ */
+ public static final String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";
+
+ /**
+ * A constant describing a motion detect sensor.
+ *
+ * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
+ *
+ */
+ public static final int TYPE_HEART_BEAT = 31;
+
+ /**
+ * A constant string describing a heart beat sensor.
+ *
+ * @see #TYPE_HEART_BEAT
+ */
+
+ public static final String STRING_TYPE_HEART_BEAT = "android.sensor.heart_beat";
+ /**
+ * A constant describing a dynamic sensor meta event sensor.
+ *
+ * A sensor event of this type is received when a dynamic sensor is added to or removed from
+ * the system. This sensor type should always use special trigger report mode ({@code
+ * SensorManager.REPORTING_MODE_SPECIAL_TRIGGER}).
+ *
+ * @hide This sensor is expected to be used only by system services.
+ */
+ @SystemApi
+ public static final int TYPE_DYNAMIC_SENSOR_META = 32;
+
+ /**
+ * A constant string describing a dynamic sensor meta event sensor.
+ *
+ * @see #TYPE_DYNAMIC_SENSOR_META
+ *
+ * @hide This sensor is expected to only be used by the system service
+ */
+ @SystemApi
+ public static final String STRING_TYPE_DYNAMIC_SENSOR_META =
+ "android.sensor.dynamic_sensor_meta";
+
/**
* A constant describing all sensor types.
*/
+
public static final int TYPE_ALL = -1;
// If this flag is set, the sensor defined as a wake up sensor. This field and REPORTING_MODE_*
@@ -660,7 +733,11 @@
1, // SENSOR_TYPE_PICK_UP_GESTURE
1, // SENSOR_TYPE_WRIST_TILT_GESTURE
1, // SENSOR_TYPE_DEVICE_ORIENTATION
- 16, // SENSOR_TYPE_POSE_6DOF
+ 16,// SENSOR_TYPE_POSE_6DOF
+ 1, // SENSOR_TYPE_STATIONARY_DETECT
+ 1, // SENSOR_TYPE_MOTION_DETECT
+ 1, // SENSOR_TYPE_HEART_BEAT
+ 2, // SENSOR_TYPE_DYNAMIC_SENSOR_META
};
/**
@@ -686,12 +763,10 @@
}
int offset = sensor.mType;
if (offset >= sSensorReportingModes.length) {
- // we don't know about this sensor, so this is probably a
- // vendor-defined sensor, in that case, we don't know how many value
- // it has
- // so we return the maximum and assume the app will know.
- // FIXME: sensor HAL should advertise how much data is returned per
- // sensor
+ // we don't know about this sensor, so this is probably a vendor-defined sensor, in that
+ // case, we don't know how many value it has so we return the maximum and assume the app
+ // will know.
+ // FIXME: sensor HAL should advertise how much data is returned per sensor
return 16;
}
return sSensorReportingModes[offset];
@@ -715,6 +790,7 @@
private String mRequiredPermission;
private int mMaxDelay;
private int mFlags;
+ private UUID mUuid;
Sensor() {
}
@@ -803,6 +879,13 @@
}
/**
+ * @return The type of this sensor as a string.
+ */
+ public UUID getUuid() {
+ return mUuid;
+ }
+
+ /**
* @hide
* @return The permission required to access this sensor. If empty, no permission is required.
*/
@@ -985,6 +1068,9 @@
case TYPE_DEVICE_ORIENTATION:
mStringType = STRING_TYPE_DEVICE_ORIENTATION;
return true;
+ case TYPE_DYNAMIC_SENSOR_META:
+ mStringType = STRING_TYPE_DYNAMIC_SENSOR_META;
+ return true;
default:
return false;
}
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 416c74c..35c96f7 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -396,7 +396,7 @@
* dv = 216.7 *
* (rh / 100.0 * 6.112 * Math.exp(17.62 * t / (243.12 + t)) / (273.15 + t));
* </pre>
- *
+ *
* <h4>{@link android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE Sensor.TYPE_AMBIENT_TEMPERATURE}:
* </h4>
*
@@ -531,6 +531,53 @@
*
* </ul>
*
+ * <h4>{@link android.hardware.Sensor#TYPE_STATIONARY_DETECT
+ * Sensor.TYPE_STATIONARY_DETECT}:</h4>
+ *
+ * A TYPE_STATIONARY_DETECT event is produced if the device has been
+ * stationary for at least 5 seconds with a maximal latency of 5
+ * additional seconds. ie: it may take up anywhere from 5 to 10 seconds
+ * afte the device has been at rest to trigger this event.
+ *
+ * The only allowed value is 1.0.
+ *
+ * <ul>
+ * <li> values[0]: 1.0 </li>
+ * </ul>
+ *
+ * <h4>{@link android.hardware.Sensor#TYPE_MOTION_DETECT
+ * Sensor.TYPE_MOTION_DETECT}:</h4>
+ *
+ * A TYPE_MOTION_DETECT event is produced if the device has been in
+ * motion for at least 5 seconds with a maximal latency of 5
+ * additional seconds. ie: it may take up anywhere from 5 to 10 seconds
+ * afte the device has been at rest to trigger this event.
+ *
+ * The only allowed value is 1.0.
+ *
+ * <ul>
+ * <li> values[0]: 1.0 </li>
+ * </ul>
+ *
+ * <h4>{@link android.hardware.Sensor#TYPE_HEART_BEAT
+ * Sensor.TYPE_HEART_BEAT}:</h4>
+ *
+ * A sensor of this type returns an event everytime a hear beat peak is
+ * detected.
+ *
+ * Peak here ideally corresponds to the positive peak in the QRS complex of
+ * an ECG signal.
+ *
+ * <ul>
+ * <li> values[0]: confidence</li>
+ * </ul>
+ *
+ * <p>
+ * A confidence value of 0.0 indicates complete uncertainty - that a peak
+ * is as likely to be at the indicated timestamp as anywhere else.
+ * A confidence value of 1.0 indicates complete certainly - that a peak is
+ * completely unlikely to be anywhere else on the QRS complex.
+ * </p>
*/
public final float[] values;
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 5d405f9..f0b17c30 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -377,6 +377,12 @@
protected abstract List<Sensor> getFullSensorList();
/**
+ * Gets the full list of dynamic sensors that are available.
+ * @hide
+ */
+ protected abstract List<Sensor> getFullDynamicSensorList();
+
+ /**
* @return available sensors.
* @deprecated This method is deprecated, use
* {@link SensorManager#getSensorList(int)} instead
@@ -430,6 +436,38 @@
}
/**
+ * Use this method to get a list of available dynamic sensors of a certain type.
+ * Make multiple calls to get sensors of different types or use
+ * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all dynamic sensors.
+ *
+ * <p class="note">
+ * NOTE: Both wake-up and non wake-up sensors matching the given type are
+ * returned. Check {@link Sensor#isWakeUpSensor()} to know the wake-up properties
+ * of the returned {@link Sensor}.
+ * </p>
+ *
+ * @param type of sensors requested
+ *
+ * @return a list of dynamic sensors matching the requested type.
+ *
+ * @see Sensor
+ */
+ public List<Sensor> getDynamicSensorList(int type) {
+ // cache the returned lists the first time
+ final List<Sensor> fullList = getFullDynamicSensorList();
+ if (type == Sensor.TYPE_ALL) {
+ return Collections.unmodifiableList(fullList);
+ } else {
+ List<Sensor> list = new ArrayList();
+ for (Sensor i : fullList) {
+ if (i.getType() == type)
+ list.add(i);
+ }
+ return Collections.unmodifiableList(list);
+ }
+ }
+
+ /**
* Use this method to get the default sensor for a given type. Note that the
* returned sensor could be a composite sensor, and its data could be
* averaged or filtered. If you need to access the raw sensors use
@@ -841,6 +879,86 @@
/** @hide */
protected abstract boolean flushImpl(SensorEventListener listener);
+
+ /**
+ * Used for receiving notifications from the SensorManager when dynamic sensors are connected or
+ * disconnected.
+ */
+ public static abstract class DynamicSensorConnectionCallback {
+ /**
+ * Called when there is a dynamic sensor being connected to the system.
+ *
+ * @param sensor the newly connected sensor. See {@link android.hardware.Sensor Sensor}.
+ */
+ public void onDynamicSensorConnected(Sensor sensor) {}
+
+ /**
+ * Called when there is a dynamic sensor being disconnected from the system.
+ *
+ * @param sensor the disconnected sensor. See {@link android.hardware.Sensor Sensor}.
+ */
+ public void onDynamicSensorDisconnected(Sensor sensor) {}
+ }
+
+
+ /**
+ * Add a {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
+ * DynamicSensorConnectionCallback} to receive dynamic sensor connection callbacks. Repeat
+ * registration with the already registered callback object will have no additional effect.
+ *
+ * @param callback An object that implements the
+ * {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
+ * DynamicSensorConnectionCallback}
+ * interface for receiving callbacks.
+ * @see #addDynamicSensorCallback(DynamicSensorConnectionCallback, Handler)
+ *
+ * @throws IllegalArgumentException when callback is null.
+ */
+ public void registerDynamicSensorCallback(DynamicSensorConnectionCallback callback) {
+ registerDynamicSensorCallback(callback, null);
+ }
+
+ /**
+ * Add a {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
+ * DynamicSensorConnectionCallback} to receive dynamic sensor connection callbacks. Repeat
+ * registration with the already registered callback object will have no additional effect.
+ *
+ * @param callback An object that implements the
+ * {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
+ * DynamicSensorConnectionCallback} interface for receiving callbacks.
+ * @param handler The {@link android.os.Handler Handler} the {@link
+ * android.hardware.SensorManager.DynamicSensorConnectionCallback
+ * sensor connection events} will be delivered to.
+ *
+ * @throws IllegalArgumentException when callback is null.
+ */
+ public void registerDynamicSensorCallback(
+ DynamicSensorConnectionCallback callback, Handler handler) {
+ registerDynamicSensorCallbackImpl(callback, handler);
+ }
+
+ /**
+ * Remove a {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
+ * DynamicSensorConnectionCallback} to stop sending dynamic sensor connection events to that
+ * callback.
+ *
+ * @param callback An object that implements the
+ * {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
+ * DynamicSensorConnectionCallback}
+ * interface for receiving callbacks.
+ */
+ public void unregisterDynamicSensorCallback(DynamicSensorConnectionCallback callback) {
+ unregisterDynamicSensorCallbackImpl(callback);
+ }
+
+ /** @hide */
+ protected abstract void registerDynamicSensorCallbackImpl(
+ DynamicSensorConnectionCallback callback, Handler handler);
+
+ /** @hide */
+ protected abstract void unregisterDynamicSensorCallbackImpl(
+ DynamicSensorConnectionCallback callback);
+
/**
* <p>
* Computes the inclination matrix <b>I</b> as well as the rotation matrix
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 2fe8fb6..e91195c 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -17,7 +17,10 @@
package android.hardware;
import android.Manifest;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
@@ -32,6 +35,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* Sensor manager implementation that communicates with the built-in
@@ -40,10 +44,14 @@
* @hide
*/
public class SystemSensorManager extends SensorManager {
+ //TODO: disable extra logging before release
+ private static boolean DEBUG_DYNAMIC_SENSOR = true;
+
private static native void nativeClassInit();
private static native long nativeCreate(String opPackageName);
private static native boolean nativeGetSensorAtIndex(long nativeInstance,
Sensor sensor, int index);
+ private static native void nativeGetDynamicSensors(long nativeInstance, List<Sensor> list);
private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);
private static boolean sSensorModuleInitialized = false;
@@ -52,7 +60,10 @@
private final Object mLock = new Object();
private final ArrayList<Sensor> mFullSensorsList = new ArrayList<>();
- private final SparseArray<Sensor> mHandleToSensor = new SparseArray<>();
+ private List<Sensor> mFullDynamicSensorsList = new ArrayList<>();
+ private boolean mDynamicSensorListDirty = true;
+
+ private final HashMap<Integer, Sensor> mHandleToSensor = new HashMap<>();
// Listener list
private final HashMap<SensorEventListener, SensorEventQueue> mSensorListeners =
@@ -60,6 +71,11 @@
private final HashMap<TriggerEventListener, TriggerEventQueue> mTriggerListeners =
new HashMap<TriggerEventListener, TriggerEventQueue>();
+ // Dynamic Sensor callbacks
+ private HashMap<DynamicSensorConnectionCallback, Handler>
+ mDynamicSensorCallbacks = new HashMap<>();
+ private BroadcastReceiver mDynamicSensorBroadcastReceiver;
+
// Looper associated with the context in which this instance was created.
private final Looper mMainLooper;
private final int mTargetSdkLevel;
@@ -84,7 +100,7 @@
Sensor sensor = new Sensor();
if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
mFullSensorsList.add(sensor);
- mHandleToSensor.append(sensor.getHandle(), sensor);
+ mHandleToSensor.put(sensor.getHandle(), sensor);
}
}
}
@@ -96,6 +112,15 @@
return mFullSensorsList;
}
+ /** @hide */
+ @Override
+ protected List<Sensor> getFullDynamicSensorList() {
+ // only set up broadcast receiver if the application tries to find dynamic sensors or
+ // explicitly register a DynamicSensorConnectionCallback
+ setupDynamicSensorBroadcastReceiver();
+ updateDynamicSensorList();
+ return mFullDynamicSensorsList;
+ }
/** @hide */
@Override
@@ -274,6 +299,187 @@
}
}
+ private void cleanupSensorConnection(Sensor sensor) {
+ mHandleToSensor.remove(sensor.getHandle());
+
+ if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
+ synchronized(mTriggerListeners) {
+ for (TriggerEventListener l: mTriggerListeners.keySet()) {
+ if (DEBUG_DYNAMIC_SENSOR){
+ Log.i(TAG, "removed trigger listener" + l.toString() +
+ " due to sensor disconnection");
+ }
+ cancelTriggerSensorImpl(l, sensor, true);
+ }
+ }
+ } else {
+ synchronized(mSensorListeners) {
+ for (SensorEventListener l: mSensorListeners.keySet()) {
+ if (DEBUG_DYNAMIC_SENSOR){
+ Log.i(TAG, "removed event listener" + l.toString() +
+ " due to sensor disconnection");
+ }
+ unregisterListenerImpl(l, sensor);
+ }
+ }
+ }
+ }
+
+ private void updateDynamicSensorList() {
+ synchronized(mFullDynamicSensorsList) {
+ if (mDynamicSensorListDirty) {
+ List<Sensor> list = new ArrayList<>();
+ nativeGetDynamicSensors(mNativeInstance, list);
+
+ final List<Sensor> updatedList = new ArrayList<>();
+ final List<Sensor> addedList = new ArrayList<>();
+ final List<Sensor> removedList = new ArrayList<>();
+
+ boolean changed = diffSortedSensorList(
+ mFullDynamicSensorsList, list, updatedList, addedList, removedList);
+
+ if (changed) {
+ if (DEBUG_DYNAMIC_SENSOR) {
+ Log.i(TAG, "DYNS dynamic sensor list cached should be updated");
+ }
+ mFullDynamicSensorsList = updatedList;
+
+ for (Sensor s: addedList) {
+ mHandleToSensor.put(s.getHandle(), s);
+ }
+
+ Handler mainHandler = new Handler(mContext.getMainLooper());
+
+ for (Map.Entry<DynamicSensorConnectionCallback, Handler> entry :
+ mDynamicSensorCallbacks.entrySet()) {
+ final DynamicSensorConnectionCallback callback = entry.getKey();
+ Handler handler =
+ entry.getValue() == null ? mainHandler : entry.getValue();
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ for (Sensor s: addedList) {
+ callback.onDynamicSensorConnected(s);
+ }
+ for (Sensor s: removedList) {
+ callback.onDynamicSensorDisconnected(s);
+ }
+ }
+ });
+ }
+
+ for (Sensor s: removedList) {
+ cleanupSensorConnection(s);
+ }
+ }
+
+ mDynamicSensorListDirty = false;
+ }
+ }
+ }
+
+ private void setupDynamicSensorBroadcastReceiver() {
+ if (mDynamicSensorBroadcastReceiver == null) {
+ mDynamicSensorBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction() == Intent.ACTION_DYNAMIC_SENSOR_CHANGED) {
+ if (DEBUG_DYNAMIC_SENSOR) {
+ Log.i(TAG, "DYNS received DYNAMIC_SENSOR_CHANED broadcast");
+ }
+ // Dynamic sensors probably changed
+ mDynamicSensorListDirty = true;
+ updateDynamicSensorList();
+ }
+ }
+ };
+
+ IntentFilter filter = new IntentFilter("dynamic_sensor_change");
+ filter.addAction(Intent.ACTION_DYNAMIC_SENSOR_CHANGED);
+ mContext.registerReceiver(mDynamicSensorBroadcastReceiver, filter);
+ }
+ }
+
+ private void teardownDynamicSensorBroadcastReceiver() {
+ mDynamicSensorCallbacks.clear();
+ mContext.unregisterReceiver(mDynamicSensorBroadcastReceiver);
+ mDynamicSensorBroadcastReceiver = null;
+ }
+
+ /** @hide */
+ protected void registerDynamicSensorCallbackImpl(
+ DynamicSensorConnectionCallback callback, Handler handler) {
+ if (DEBUG_DYNAMIC_SENSOR) {
+ Log.i(TAG, "DYNS Register dynamic sensor callback");
+ }
+
+ if (callback == null) {
+ throw new IllegalArgumentException("callback cannot be null");
+ }
+ if (mDynamicSensorCallbacks.containsKey(callback)) {
+ // has been already registered, ignore
+ return;
+ }
+
+ setupDynamicSensorBroadcastReceiver();
+ mDynamicSensorCallbacks.put(callback, handler);
+ }
+
+ /** @hide */
+ protected void unregisterDynamicSensorCallbackImpl(
+ DynamicSensorConnectionCallback callback) {
+ if (DEBUG_DYNAMIC_SENSOR) {
+ Log.i(TAG, "Removing dynamic sensor listerner");
+ }
+ mDynamicSensorCallbacks.remove(callback);
+ }
+
+ /*
+ * Find the difference of two List<Sensor> assuming List are sorted by handle of sensor,
+ * assuming the input list is already sorted by handle. Inputs are ol and nl; outputs are
+ * updated, added and removed. Any of the output lists can be null in case the result is not
+ * interested.
+ */
+ private static boolean diffSortedSensorList(
+ List<Sensor> oldList, List<Sensor> newList, List<Sensor> updated,
+ List<Sensor> added, List<Sensor> removed) {
+
+ boolean changed = false;
+
+ int i = 0, j = 0;
+ while (true) {
+ if (j < oldList.size() && ( i >= newList.size() ||
+ newList.get(i).getHandle() > oldList.get(j).getHandle()) ) {
+ changed = true;
+ if (removed != null) {
+ removed.add(oldList.get(j));
+ }
+ ++j;
+ } else if (i < newList.size() && ( j >= oldList.size() ||
+ newList.get(i).getHandle() < oldList.get(j).getHandle())) {
+ changed = true;
+ if (added != null) {
+ added.add(newList.get(i));
+ }
+ if (updated != null) {
+ updated.add(newList.get(i));
+ }
+ ++i;
+ } else if (i < newList.size() && j < oldList.size() &&
+ newList.get(i).getHandle() == oldList.get(j).getHandle()) {
+ if (updated != null) {
+ updated.add(oldList.get(j));
+ }
+ ++i;
+ ++j;
+ } else {
+ break;
+ }
+ }
+ return changed;
+ }
+
/*
* BaseEventQueue is the communication channel with the sensor service,
* SensorEventQueue, TriggerEventQueue are subclases and there is one-to-one mapping between
@@ -297,7 +503,6 @@
private long nSensorEventQueue;
private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
protected final SparseIntArray mSensorAccuracies = new SparseIntArray();
- protected final SparseBooleanArray mFirstEvent = new SparseBooleanArray();
private final CloseGuard mCloseGuard = CloseGuard.get();
private final float[] mScratch = new float[16];
protected final SystemSensorManager mManager;
@@ -348,7 +553,7 @@
mActiveSensors.put(handle, false);
removeSensorEvent(sensor);
} else {
- // it should never happen -- just ignore.
+ // sensor just disconnected -- just ignore.
}
}
}
@@ -456,6 +661,11 @@
protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
long timestamp) {
final Sensor sensor = mManager.mHandleToSensor.get(handle);
+ if (sensor == null) {
+ // sensor disconnected
+ return;
+ }
+
SensorEvent t = null;
synchronized (mSensorsEvents) {
t = mSensorsEvents.get(handle);
@@ -485,6 +695,10 @@
protected void dispatchFlushCompleteEvent(int handle) {
if (mListener instanceof SensorEventListener2) {
final Sensor sensor = mManager.mHandleToSensor.get(handle);
+ if (sensor == null) {
+ // sensor disconnected
+ return;
+ }
((SensorEventListener2)mListener).onFlushCompleted(sensor);
}
return;
@@ -523,6 +737,10 @@
protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
long timestamp) {
final Sensor sensor = mManager.mHandleToSensor.get(handle);
+ if (sensor == null) {
+ // sensor disconnected
+ return;
+ }
TriggerEvent t = null;
synchronized (mTriggerEvents) {
t = mTriggerEvents.get(handle);
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 28bb22a..6aacc9c 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -575,14 +575,16 @@
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_3 LEVEL_3}) devices
* support at least the following stream combinations for creating a reprocessable capture
* session in addition to those for
- * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} devices. Note that targets in the "Reprocess-only target" column may only be
- * used as an output target for a reprocess capture request, not as an output to a regular capture request.
+ * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} devices. Note that while
+ * the second configuration allows for configuring {@code MAXIMUM} {@code YUV} and {@code JPEG}
+ * outputs at the same time, that configuration is not listed for regular capture sessions, and
+ * therefore simultaneous output to both targets is not allowed.
*
* <table>
* <tr><th colspan="13">LEVEL-3 additional guaranteed configurations for creating a reprocessable capture session<br>({@code PRIV} input is guaranteed only if PRIVATE reprocessing is supported. {@code YUV} input is always guaranteed.</th></tr>
- * <tr><th colspan="2" id="rb">Input</th><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th colspan="2" id="rb">Target 4</th><th colspan="2" id="rb">Reprocess-only target</th><th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr><th colspan="2" id="rb">Input</th><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th colspan="2" id="rb">Target 4</th><th colspan="2" id="rb">Target 5</th><th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
- * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code 640x480}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td> <td></td><td id="rb"></td> <td>In-app viewfinder analysis with ZSL and RAW.</td> </tr>
+ * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code 640x480}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td> <td></td><td id="rb"></td> <td>In-app viewfinder analysis with ZSL and RAW.</td> </tr>
* <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code 640x480}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td><td>In-app viewfinder analysis with ZSL, RAW, and JPEG reprocessing output.</td> </tr>
* </table><br>
* </p>
diff --git a/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl b/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl
index 2f6dbe7..597efa5 100644
--- a/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl
+++ b/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl
@@ -25,9 +25,12 @@
/**
* Called when the keyphrase is spoken.
*
- * @param data Optional trigger audio data, if it was requested and is available.
+ * @param recognitionEvent Object containing data relating to the
+ * recognition event such as trigger audio data, if it was requested
+ * and is available.
*/
- void onDetected(in SoundTrigger.KeyphraseRecognitionEvent recognitionEvent);
+ void onDetected(in SoundTrigger.RecognitionEvent recognitionEvent);
+
/**
* Called when the detection fails due to an error.
*
@@ -42,4 +45,4 @@
* Called when the recognition is resumed after it was temporarily paused.
*/
void onRecognitionResumed();
-}
\ No newline at end of file
+}
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.aidl b/core/java/android/hardware/soundtrigger/SoundTrigger.aidl
index e16ea71..fec64ea 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.aidl
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.aidl
@@ -18,8 +18,11 @@
parcelable SoundTrigger.ConfidenceLevel;
parcelable SoundTrigger.Keyphrase;
+parcelable SoundTrigger.RecognitionEvent;
parcelable SoundTrigger.KeyphraseRecognitionEvent;
+parcelable SoundTrigger.GenericSoundRecognitionEvent;
parcelable SoundTrigger.KeyphraseRecognitionExtra;
parcelable SoundTrigger.KeyphraseSoundModel;
+parcelable SoundTrigger.GenericSoundModel;
parcelable SoundTrigger.ModuleProperties;
parcelable SoundTrigger.RecognitionConfig;
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index d490409..882908a 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -195,6 +195,12 @@
/** Keyphrase sound model */
public static final int TYPE_KEYPHRASE = 0;
+ /**
+ * A generic sound model. Use this type only for non-keyphrase sound models such as
+ * ones that match a particular sound pattern.
+ */
+ public static final int TYPE_GENERIC_SOUND = 1;
+
/** Unique sound model identifier */
public final UUID uuid;
@@ -458,6 +464,63 @@
}
}
+
+ /*****************************************************************************
+ * A GenericSoundModel is a specialized {@link SoundModel} for non-voice sound
+ * patterns.
+ ****************************************************************************/
+ public static class GenericSoundModel extends SoundModel implements Parcelable {
+
+ public static final Parcelable.Creator<GenericSoundModel> CREATOR
+ = new Parcelable.Creator<GenericSoundModel>() {
+ public GenericSoundModel createFromParcel(Parcel in) {
+ return GenericSoundModel.fromParcel(in);
+ }
+
+ public GenericSoundModel[] newArray(int size) {
+ return new GenericSoundModel[size];
+ }
+ };
+
+ public GenericSoundModel(UUID uuid, UUID vendorUuid, byte[] data) {
+ super(uuid, vendorUuid, TYPE_GENERIC_SOUND, data);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ private static GenericSoundModel fromParcel(Parcel in) {
+ UUID uuid = UUID.fromString(in.readString());
+ UUID vendorUuid = null;
+ int length = in.readInt();
+ if (length >= 0) {
+ vendorUuid = UUID.fromString(in.readString());
+ }
+ byte[] data = in.readBlob();
+ return new GenericSoundModel(uuid, vendorUuid, data);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(uuid.toString());
+ if (vendorUuid == null) {
+ dest.writeInt(-1);
+ } else {
+ dest.writeInt(vendorUuid.toString().length());
+ dest.writeString(vendorUuid.toString());
+ }
+ dest.writeBlob(data);
+ }
+
+ @Override
+ public String toString() {
+ return "GenericSoundModel [uuid=" + uuid + ", vendorUuid=" + vendorUuid
+ + ", type=" + type + ", data=" + (data == null ? 0 : data.length) + "]";
+ }
+ }
+
/**
* Modes for key phrase recognition
*/
@@ -1019,6 +1082,21 @@
}
/**
+ * Sub-class of RecognitionEvent specifically for sound-trigger based sound
+ * models(non-keyphrase). Currently does not contain any additional fields.
+ */
+ public static class GenericRecognitionEvent extends RecognitionEvent {
+ public GenericRecognitionEvent(int status, int soundModelHandle,
+ boolean captureAvailable, int captureSession, int captureDelayMs,
+ int capturePreambleMs, boolean triggerInData, AudioFormat captureFormat,
+ byte[] data) {
+ super(status, soundModelHandle, captureAvailable, captureSession,
+ captureDelayMs, capturePreambleMs, triggerInData, captureFormat,
+ data);
+ }
+ }
+
+ /**
* Status codes for {@link SoundModelEvent}
*/
/** Sound Model was updated */
@@ -1118,7 +1196,7 @@
public static final int SERVICE_STATE_DISABLED = 1;
/**
- * Returns a list of descriptors for all harware modules loaded.
+ * Returns a list of descriptors for all hardware modules loaded.
* @param modules A ModuleProperties array where the list will be returned.
* @return - {@link #STATUS_OK} in case of success
* - {@link #STATUS_ERROR} in case of unspecified error
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9180506..52fa2ed 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -201,9 +201,14 @@
private static final String BATTERY_LEVEL_DATA = "lv";
private static final String GLOBAL_WIFI_DATA = "gwfl";
private static final String WIFI_DATA = "wfl";
- private static final String GLOBAL_BLUETOOTH_DATA = "gble";
+ private static final String GLOBAL_WIFI_CONTROLLER_DATA = "gwfcd";
+ private static final String WIFI_CONTROLLER_DATA = "wfcd";
+ private static final String GLOBAL_BLUETOOTH_CONTROLLER_DATA = "gble";
+ private static final String BLUETOOTH_CONTROLLER_DATA = "ble";
private static final String MISC_DATA = "m";
private static final String GLOBAL_NETWORK_DATA = "gn";
+ private static final String GLOBAL_MODEM_CONTROLLER_DATA = "gmcd";
+ private static final String MODEM_CONTROLLER_DATA = "mcd";
private static final String HISTORY_STRING_POOL = "hsp";
private static final String HISTORY_DATA = "h";
private static final String SCREEN_BRIGHTNESS_DATA = "br";
@@ -271,6 +276,39 @@
}
/**
+ * Container class that aggregates counters for transmit, receive, and idle state of a
+ * radio controller.
+ */
+ public static abstract class ControllerActivityCounter {
+ /**
+ * @return a non-null {@link LongCounter} representing time spent (milliseconds) in the
+ * idle state.
+ */
+ public abstract LongCounter getIdleTimeCounter();
+
+ /**
+ * @return a non-null {@link LongCounter} representing time spent (milliseconds) in the
+ * receive state.
+ */
+ public abstract LongCounter getRxTimeCounter();
+
+ /**
+ * An array of {@link LongCounter}, representing various transmit levels, where each level
+ * may draw a different amount of power. The levels themselves are controller-specific.
+ * @return non-null array of {@link LongCounter}s representing time spent (milliseconds) in
+ * various transmit level states.
+ */
+ public abstract LongCounter[] getTxTimeCounters();
+
+ /**
+ * @return a non-null {@link LongCounter} representing the power consumed by the controller
+ * in all states, measured in milli-ampere-milliseconds (mAms). The counter may always
+ * yield a value of 0 if the device doesn't support power calculations.
+ */
+ public abstract LongCounter getPowerCounter();
+ }
+
+ /**
* State for keeping track of timing information.
*/
public static abstract class Timer {
@@ -367,25 +405,9 @@
*/
public abstract ArrayMap<String, ? extends Pkg> getPackageStats();
- /**
- * Returns the time in milliseconds that this app kept the WiFi controller in the
- * specified state <code>type</code>.
- * @param type one of {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, or
- * {@link #CONTROLLER_TX_TIME}.
- * @param which one of {@link #STATS_CURRENT}, {@link #STATS_SINCE_CHARGED}, or
- * {@link #STATS_SINCE_UNPLUGGED}.
- */
- public abstract long getWifiControllerActivity(int type, int which);
-
- /**
- * Returns the time in milliseconds that this app kept the Bluetooth controller in the
- * specified state <code>type</code>.
- * @param type one of {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, or
- * {@link #CONTROLLER_TX_TIME}.
- * @param which one of {@link #STATS_CURRENT}, {@link #STATS_SINCE_CHARGED}, or
- * {@link #STATS_SINCE_UNPLUGGED}.
- */
- public abstract long getBluetoothControllerActivity(int type, int which);
+ public abstract ControllerActivityCounter getWifiControllerActivity();
+ public abstract ControllerActivityCounter getBluetoothControllerActivity();
+ public abstract ControllerActivityCounter getModemControllerActivity();
/**
* {@hide}
@@ -2031,43 +2053,47 @@
public abstract long getNetworkActivityBytes(int type, int which);
public abstract long getNetworkActivityPackets(int type, int which);
- public static final int CONTROLLER_IDLE_TIME = 0;
- public static final int CONTROLLER_RX_TIME = 1;
- public static final int CONTROLLER_TX_TIME = 2;
- public static final int CONTROLLER_POWER_DRAIN = 3;
- public static final int NUM_CONTROLLER_ACTIVITY_TYPES = CONTROLLER_POWER_DRAIN + 1;
-
- /**
- * Returns true if the BatteryStats object has detailed bluetooth power reports.
- * When true, calling {@link #getBluetoothControllerActivity(int, int)} will yield the
- * actual power data.
- */
- public abstract boolean hasBluetoothActivityReporting();
-
- /**
- * For {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, and
- * {@link #CONTROLLER_TX_TIME}, returns the time spent (in milliseconds) in the
- * respective state.
- * For {@link #CONTROLLER_POWER_DRAIN}, returns the power used by the controller in
- * milli-ampere-milliseconds (mAms).
- */
- public abstract long getBluetoothControllerActivity(int type, int which);
-
/**
* Returns true if the BatteryStats object has detailed WiFi power reports.
- * When true, calling {@link #getWifiControllerActivity(int, int)} will yield the
+ * When true, calling {@link #getWifiControllerActivity()} will yield the
* actual power data.
*/
public abstract boolean hasWifiActivityReporting();
/**
- * For {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, and
- * {@link #CONTROLLER_TX_TIME}, returns the time spent (in milliseconds) in the
- * respective state.
- * For {@link #CONTROLLER_POWER_DRAIN}, returns the power used by the controller in
- * milli-ampere-milliseconds (mAms).
+ * Returns a {@link ControllerActivityCounter} which is an aggregate of the times spent
+ * in various radio controller states, such as transmit, receive, and idle.
+ * @return non-null {@link ControllerActivityCounter}
*/
- public abstract long getWifiControllerActivity(int type, int which);
+ public abstract ControllerActivityCounter getWifiControllerActivity();
+
+ /**
+ * Returns true if the BatteryStats object has detailed bluetooth power reports.
+ * When true, calling {@link #getBluetoothControllerActivity()} will yield the
+ * actual power data.
+ */
+ public abstract boolean hasBluetoothActivityReporting();
+
+ /**
+ * Returns a {@link ControllerActivityCounter} which is an aggregate of the times spent
+ * in various radio controller states, such as transmit, receive, and idle.
+ * @return non-null {@link ControllerActivityCounter}
+ */
+ public abstract ControllerActivityCounter getBluetoothControllerActivity();
+
+ /**
+ * Returns true if the BatteryStats object has detailed modem power reports.
+ * When true, calling {@link #getModemControllerActivity()} will yield the
+ * actual power data.
+ */
+ public abstract boolean hasModemActivityReporting();
+
+ /**
+ * Returns a {@link ControllerActivityCounter} which is an aggregate of the times spent
+ * in various radio controller states, such as transmit, receive, and idle.
+ * @return non-null {@link ControllerActivityCounter}
+ */
+ public abstract ControllerActivityCounter getModemControllerActivity();
/**
* Return the wall clock time when battery stats data collection started.
@@ -2496,6 +2522,17 @@
return ",";
}
+ private static final void dumpLineHeader(PrintWriter pw, int uid, String category,
+ String type) {
+ pw.print(BATTERY_STATS_CHECKIN_VERSION);
+ pw.print(',');
+ pw.print(uid);
+ pw.print(',');
+ pw.print(category);
+ pw.print(',');
+ pw.print(type);
+ }
+
/**
* Dump a comma-separated line of values for terse checkin mode.
*
@@ -2506,14 +2543,7 @@
*/
private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
Object... args ) {
- pw.print(BATTERY_STATS_CHECKIN_VERSION);
- pw.print(',');
- pw.print(uid);
- pw.print(',');
- pw.print(category);
- pw.print(',');
- pw.print(type);
-
+ dumpLineHeader(pw, uid, category, type);
for (Object arg : args) {
pw.print(',');
pw.print(arg);
@@ -2546,6 +2576,140 @@
}
/**
+ * Checks if the ControllerActivityCounter has any data worth dumping.
+ */
+ private static boolean controllerActivityHasData(ControllerActivityCounter counter, int which) {
+ if (counter == null) {
+ return false;
+ }
+
+ if (counter.getIdleTimeCounter().getCountLocked(which) != 0
+ || counter.getRxTimeCounter().getCountLocked(which) != 0
+ || counter.getPowerCounter().getCountLocked(which) != 0) {
+ return true;
+ }
+
+ for (LongCounter c : counter.getTxTimeCounters()) {
+ if (c.getCountLocked(which) != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Dumps the ControllerActivityCounter if it has any data worth dumping.
+ * The order of the arguments in the final check in line is:
+ *
+ * idle, rx, power, tx...
+ *
+ * where tx... is one or more transmit level times.
+ */
+ private static final void dumpControllerActivityLine(PrintWriter pw, int uid, String category,
+ String type,
+ ControllerActivityCounter counter,
+ int which) {
+ if (!controllerActivityHasData(counter, which)) {
+ return;
+ }
+
+ dumpLineHeader(pw, uid, category, type);
+ pw.print(",");
+ pw.print(counter.getIdleTimeCounter().getCountLocked(which));
+ pw.print(",");
+ pw.print(counter.getRxTimeCounter().getCountLocked(which));
+ pw.print(",");
+ pw.print(counter.getPowerCounter().getCountLocked(which) / (1000 * 60 * 60));
+ for (LongCounter c : counter.getTxTimeCounters()) {
+ pw.print(",");
+ pw.print(c.getCountLocked(which));
+ }
+ pw.println();
+ }
+
+ private final void printControllerActivityIfInteresting(PrintWriter pw, StringBuilder sb,
+ String prefix, String controllerName,
+ ControllerActivityCounter counter,
+ int which) {
+ if (controllerActivityHasData(counter, which)) {
+ printControllerActivity(pw, sb, prefix, controllerName, counter, which);
+ }
+ }
+
+ private final void printControllerActivity(PrintWriter pw, StringBuilder sb, String prefix,
+ String controllerName,
+ ControllerActivityCounter counter, int which) {
+ final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
+ final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
+ final long powerDrainMaMs = counter.getPowerCounter().getCountLocked(which);
+ long totalTxTimeMs = 0;
+ for (LongCounter txState : counter.getTxTimeCounters()) {
+ totalTxTimeMs += txState.getCountLocked(which);
+ }
+
+ final long totalTimeMs = idleTimeMs + rxTimeMs + totalTxTimeMs;
+
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" ");
+ sb.append(controllerName);
+ sb.append(" Idle time: ");
+ formatTimeMs(sb, idleTimeMs);
+ sb.append("(");
+ sb.append(formatRatioLocked(idleTimeMs, totalTimeMs));
+ sb.append(")");
+ pw.println(sb.toString());
+
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" ");
+ sb.append(controllerName);
+ sb.append(" Rx time: ");
+ formatTimeMs(sb, rxTimeMs);
+ sb.append("(");
+ sb.append(formatRatioLocked(rxTimeMs, totalTimeMs));
+ sb.append(")");
+ pw.println(sb.toString());
+
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" ");
+ sb.append(controllerName);
+ sb.append(" Tx time: ");
+ formatTimeMs(sb, totalTxTimeMs);
+ sb.append("(");
+ sb.append(formatRatioLocked(totalTxTimeMs, totalTimeMs));
+ sb.append(")");
+ pw.println(sb.toString());
+
+ final int numTxLvls = counter.getTxTimeCounters().length;
+ if (numTxLvls > 1) {
+ for (int lvl = 0; lvl < numTxLvls; lvl++) {
+ final long txLvlTimeMs = counter.getTxTimeCounters()[lvl].getCountLocked(which);
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" [");
+ sb.append(lvl);
+ sb.append("] ");
+ formatTimeMs(sb, txLvlTimeMs);
+ sb.append("(");
+ sb.append(formatRatioLocked(txLvlTimeMs, totalTxTimeMs));
+ sb.append(")");
+ pw.println(sb.toString());
+ }
+ }
+
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" ");
+ sb.append(controllerName);
+ sb.append(" Power drain: ").append(
+ BatteryStatsHelper.makemAh(powerDrainMaMs / (double) (1000*60*60)));
+ sb.append("mAh");
+ pw.println(sb.toString());
+ }
+
+ /**
* Temporary for settings.
*/
public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid) {
@@ -2637,24 +2801,22 @@
mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
mobileRxTotalPackets, mobileTxTotalPackets, wifiRxTotalPackets, wifiTxTotalPackets);
+ // Dump Modem controller stats
+ dumpControllerActivityLine(pw, 0 /* uid */, category, GLOBAL_MODEM_CONTROLLER_DATA,
+ getModemControllerActivity(), which);
+
// Dump Wifi controller stats
final long wifiOnTime = getWifiOnTime(rawRealtime, which);
final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
- final long wifiIdleTimeMs = getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
- final long wifiRxTimeMs = getWifiControllerActivity(CONTROLLER_RX_TIME, which);
- final long wifiTxTimeMs = getWifiControllerActivity(CONTROLLER_TX_TIME, which);
- final long wifiPowerMaMs = getWifiControllerActivity(CONTROLLER_POWER_DRAIN, which);
- dumpLine(pw, 0 /* uid */, category, GLOBAL_WIFI_DATA,
- wifiOnTime / 1000, wifiRunningTime / 1000,
- wifiIdleTimeMs, wifiRxTimeMs, wifiTxTimeMs, wifiPowerMaMs / (1000*60*60));
+ dumpLine(pw, 0 /* uid */, category, GLOBAL_WIFI_DATA, wifiOnTime / 1000,
+ wifiRunningTime / 1000, /* legacy fields follow, keep at 0 */ 0, 0, 0, 0);
+
+ dumpControllerActivityLine(pw, 0 /* uid */, category, GLOBAL_WIFI_CONTROLLER_DATA,
+ getWifiControllerActivity(), which);
// Dump Bluetooth controller stats
- final long btIdleTimeMs = getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
- final long btRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
- final long btTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
- final long btPowerMaMs = getBluetoothControllerActivity(CONTROLLER_POWER_DRAIN, which);
- dumpLine(pw, 0 /* uid */, category, GLOBAL_BLUETOOTH_DATA,
- btIdleTimeMs, btRxTimeMs, btTxTimeMs, btPowerMaMs / (1000*60*60));
+ dumpControllerActivityLine(pw, 0 /* uid */, category, GLOBAL_BLUETOOTH_CONTROLLER_DATA,
+ getBluetoothControllerActivity(), which);
// Dump misc stats
dumpLine(pw, 0 /* uid */, category, MISC_DATA,
@@ -2865,21 +3027,25 @@
mobileActiveTime, mobileActiveCount);
}
+ // Dump modem controller data, per UID.
+ dumpControllerActivityLine(pw, uid, category, MODEM_CONTROLLER_DATA,
+ u.getModemControllerActivity(), which);
+
+ // Dump Wifi controller data, per UID.
final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
final int wifiScanCount = u.getWifiScanCount(which);
final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
- final long uidWifiIdleTimeMs = u.getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
- final long uidWifiRxTimeMs = u.getWifiControllerActivity(CONTROLLER_RX_TIME, which);
- final long uidWifiTxTimeMs = u.getWifiControllerActivity(CONTROLLER_TX_TIME, which);
if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0
- || uidWifiRunningTime != 0 || uidWifiIdleTimeMs != 0 || uidWifiRxTimeMs != 0
- || uidWifiTxTimeMs != 0) {
- dumpLine(pw, uid, category, WIFI_DATA,
- fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime, wifiScanCount,
- uidWifiIdleTimeMs, uidWifiRxTimeMs, uidWifiTxTimeMs);
+ || uidWifiRunningTime != 0) {
+ dumpLine(pw, uid, category, WIFI_DATA, fullWifiLockOnTime, wifiScanTime,
+ uidWifiRunningTime, wifiScanCount,
+ /* legacy fields follow, keep at 0 */ 0, 0, 0, 0);
}
+ dumpControllerActivityLine(pw, uid, category, WIFI_CONTROLLER_DATA,
+ u.getWifiControllerActivity(), which);
+
if (u.hasUserActivity()) {
args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
boolean hasData = false;
@@ -3409,6 +3575,8 @@
pw.println(sb.toString());
}
+ printControllerActivity(pw, sb, prefix, "Radio", getModemControllerActivity(), which);
+
pw.print(prefix);
pw.print(" Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotalBytes));
pw.print(", sent: "); pw.print(formatBytesLocked(wifiTxTotalBytes));
@@ -3494,85 +3662,14 @@
if (!didOne) sb.append(" (no activity)");
pw.println(sb.toString());
- final long wifiIdleTimeMs = getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
- final long wifiRxTimeMs = getWifiControllerActivity(CONTROLLER_RX_TIME, which);
- final long wifiTxTimeMs = getWifiControllerActivity(CONTROLLER_TX_TIME, which);
- final long wifiPowerDrainMaMs = getWifiControllerActivity(CONTROLLER_POWER_DRAIN, which);
- final long wifiTotalTimeMs = wifiIdleTimeMs + wifiRxTimeMs + wifiTxTimeMs;
-
- sb.setLength(0);
- sb.append(prefix);
- sb.append(" WiFi Idle time: "); formatTimeMs(sb, wifiIdleTimeMs);
- sb.append("(");
- sb.append(formatRatioLocked(wifiIdleTimeMs, wifiTotalTimeMs));
- sb.append(")");
- pw.println(sb.toString());
-
- sb.setLength(0);
- sb.append(prefix);
- sb.append(" WiFi Rx time: "); formatTimeMs(sb, wifiRxTimeMs);
- sb.append("(");
- sb.append(formatRatioLocked(wifiRxTimeMs, wifiTotalTimeMs));
- sb.append(")");
- pw.println(sb.toString());
-
- sb.setLength(0);
- sb.append(prefix);
- sb.append(" WiFi Tx time: "); formatTimeMs(sb, wifiTxTimeMs);
- sb.append("(");
- sb.append(formatRatioLocked(wifiTxTimeMs, wifiTotalTimeMs));
- sb.append(")");
- pw.println(sb.toString());
-
- sb.setLength(0);
- sb.append(prefix);
- sb.append(" WiFi Power drain: ").append(
- BatteryStatsHelper.makemAh(wifiPowerDrainMaMs / (double) (1000*60*60)));
- sb.append("mAh");
- pw.println(sb.toString());
+ printControllerActivity(pw, sb, prefix, "WiFi", getWifiControllerActivity(), which);
pw.print(prefix);
pw.print(" Bluetooth total received: "); pw.print(formatBytesLocked(btRxTotalBytes));
pw.print(", sent: "); pw.println(formatBytesLocked(btTxTotalBytes));
- final long bluetoothIdleTimeMs =
- getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
- final long bluetoothRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
- final long bluetoothTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
- final long bluetoothTotalTimeMs = bluetoothIdleTimeMs + bluetoothRxTimeMs +
- bluetoothTxTimeMs;
-
- sb.setLength(0);
- sb.append(prefix);
- sb.append(" Bluetooth Idle time: "); formatTimeMs(sb, bluetoothIdleTimeMs);
- sb.append("(");
- sb.append(formatRatioLocked(bluetoothIdleTimeMs, bluetoothTotalTimeMs));
- sb.append(")");
- pw.println(sb.toString());
-
- sb.setLength(0);
- sb.append(prefix);
- sb.append(" Bluetooth Rx time: "); formatTimeMs(sb, bluetoothRxTimeMs);
- sb.append("(");
- sb.append(formatRatioLocked(bluetoothRxTimeMs, bluetoothTotalTimeMs));
- sb.append(")");
- pw.println(sb.toString());
-
- sb.setLength(0);
- sb.append(prefix);
- sb.append(" Bluetooth Tx time: "); formatTimeMs(sb, bluetoothTxTimeMs);
- sb.append("(");
- sb.append(formatRatioLocked(bluetoothTxTimeMs, bluetoothTotalTimeMs));
- sb.append(")");
- pw.println(sb.toString());
-
- sb.setLength(0);
- sb.append(prefix);
- sb.append(" Bluetooth Power drain: ").append(BatteryStatsHelper.makemAh(
- getBluetoothControllerActivity(CONTROLLER_POWER_DRAIN, which) /
- (double)(1000*60*60)));
- sb.append("mAh");
- pw.println(sb.toString());
+ printControllerActivity(pw, sb, prefix, "Bluetooth", getBluetoothControllerActivity(),
+ which);
pw.println();
@@ -3897,6 +3994,9 @@
pw.println(sb.toString());
}
+ printControllerActivityIfInteresting(pw, sb, prefix + " ", "Modem",
+ u.getModemControllerActivity(), which);
+
if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) {
pw.print(prefix); pw.print(" Wi-Fi network: ");
pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
@@ -3925,26 +4025,8 @@
pw.println(sb.toString());
}
- final long uidWifiIdleTimeMs = u.getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
- final long uidWifiRxTimeMs = u.getWifiControllerActivity(CONTROLLER_RX_TIME, which);
- final long uidWifiTxTimeMs = u.getWifiControllerActivity(CONTROLLER_TX_TIME, which);
- final long uidWifiTotalTimeMs = uidWifiIdleTimeMs + uidWifiRxTimeMs + uidWifiTxTimeMs;
- if (uidWifiTotalTimeMs > 0) {
- sb.setLength(0);
- sb.append(prefix).append(" WiFi Idle time: ");
- formatTimeMs(sb, uidWifiIdleTimeMs);
- sb.append("(").append(formatRatioLocked(uidWifiIdleTimeMs, uidWifiTotalTimeMs))
- .append(")\n");
-
- sb.append(prefix).append(" WiFi Rx time: "); formatTimeMs(sb, uidWifiRxTimeMs);
- sb.append("(").append(formatRatioLocked(uidWifiRxTimeMs, uidWifiTotalTimeMs))
- .append(")\n");
-
- sb.append(prefix).append(" WiFi Tx time: "); formatTimeMs(sb, uidWifiTxTimeMs);
- sb.append("(").append(formatRatioLocked(uidWifiTxTimeMs, uidWifiTotalTimeMs))
- .append(")");
- pw.println(sb.toString());
- }
+ printControllerActivityIfInteresting(pw, sb, prefix + " ", "WiFi",
+ u.getWifiControllerActivity(), which);
if (btRxBytes > 0 || btTxBytes > 0) {
pw.print(prefix); pw.print(" Bluetooth network: ");
@@ -3953,30 +4035,6 @@
pw.println(" sent");
}
- final long uidBtIdleTimeMs = u.getBluetoothControllerActivity(CONTROLLER_IDLE_TIME,
- which);
- final long uidBtRxTimeMs = u.getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
- final long uidBtTxTimeMs = u.getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
- final long uidBtTotalTimeMs = uidBtIdleTimeMs + uidBtRxTimeMs + uidBtTxTimeMs;
- if (uidBtTotalTimeMs > 0) {
- sb.setLength(0);
- sb.append(prefix).append(" Bluetooth Idle time: ");
- formatTimeMs(sb, uidBtIdleTimeMs);
- sb.append("(").append(formatRatioLocked(uidBtIdleTimeMs, uidBtTotalTimeMs))
- .append(")\n");
-
- sb.append(prefix).append(" Bluetooth Rx time: ");
- formatTimeMs(sb, uidBtRxTimeMs);
- sb.append("(").append(formatRatioLocked(uidBtRxTimeMs, uidBtTotalTimeMs))
- .append(")\n");
-
- sb.append(prefix).append(" Bluetooth Tx time: ");
- formatTimeMs(sb, uidBtTxTimeMs);
- sb.append("(").append(formatRatioLocked(uidBtTxTimeMs, uidBtTotalTimeMs))
- .append(")");
- pw.println(sb.toString());
- }
-
if (u.hasUserActivity()) {
boolean hasData = false;
for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index ba215bb..c776ef8 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -402,7 +402,7 @@
* type.
*/
public static String DIRECTORY_PODCASTS = "Podcasts";
-
+
/**
* Standard directory in which to place any audio files that should be
* in the list of ringtones that the user can select (not as regular
@@ -414,7 +414,7 @@
* type.
*/
public static String DIRECTORY_RINGTONES = "Ringtones";
-
+
/**
* Standard directory in which to place any audio files that should be
* in the list of alarms that the user can select (not as regular
@@ -426,7 +426,7 @@
* type.
*/
public static String DIRECTORY_ALARMS = "Alarms";
-
+
/**
* Standard directory in which to place any audio files that should be
* in the list of notifications that the user can select (not as regular
@@ -438,7 +438,7 @@
* type.
*/
public static String DIRECTORY_NOTIFICATIONS = "Notifications";
-
+
/**
* Standard directory in which to place pictures that are available to
* the user. Note that this is primarily a convention for the top-level
@@ -446,7 +446,7 @@
* in any directory.
*/
public static String DIRECTORY_PICTURES = "Pictures";
-
+
/**
* Standard directory in which to place movies that are available to
* the user. Note that this is primarily a convention for the top-level
@@ -454,7 +454,7 @@
* in any directory.
*/
public static String DIRECTORY_MOVIES = "Movies";
-
+
/**
* Standard directory in which to place files that have been downloaded by
* the user. Note that this is primarily a convention for the top-level
@@ -464,7 +464,7 @@
* backwards compatibility reasons.
*/
public static String DIRECTORY_DOWNLOADS = "Download";
-
+
/**
* The traditional location for pictures and videos when mounting the
* device as a camera. Note that this is primarily a convention for the
@@ -496,7 +496,7 @@
* </ul>
* @hide
*/
- public static final String[] STANDARD_DIRECTORIES = {
+ private static final String[] STANDARD_DIRECTORIES = {
DIRECTORY_MUSIC,
DIRECTORY_PODCASTS,
DIRECTORY_RINGTONES,
@@ -510,6 +510,18 @@
};
/**
+ * @hide
+ */
+ public static boolean isStandardDirectory(String dir) {
+ for (String valid : STANDARD_DIRECTORIES) {
+ if (valid.equals(dir)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Get a top-level shared/external storage directory for placing files of a
* particular type. This is where the user will typically place and manage
* their own files, so you should be careful about what you put here to
@@ -559,7 +571,7 @@
throwIfUserRequired();
return sCurrentUser.buildExternalStorageAppDataDirs(packageName);
}
-
+
/**
* Generates the raw path to an application's media
* @hide
@@ -568,7 +580,7 @@
throwIfUserRequired();
return sCurrentUser.buildExternalStorageAppMediaDirs(packageName);
}
-
+
/**
* Generates the raw path to an application's OBB files
* @hide
@@ -577,7 +589,7 @@
throwIfUserRequired();
return sCurrentUser.buildExternalStorageAppObbDirs(packageName);
}
-
+
/**
* Generates the path to an application's files.
* @hide
@@ -595,7 +607,7 @@
throwIfUserRequired();
return sCurrentUser.buildExternalStorageAppCacheDirs(packageName);
}
-
+
/**
* Return the download/cache content directory.
*/
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 4159d89..314b7d5 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -219,6 +219,15 @@
public static final int DRAW_WAKE_LOCK = 0x00000080;
/**
+ * Wake lock level: Enables Sustained Performance Mode.
+ * <p>
+ * This is used by Gaming and VR applications to ensure the device provides
+ * will provide consistent performance over a large amount of time.
+ * </p>
+ */
+ public static final int SUSTAINED_PERFORMANCE_WAKE_LOCK = 0x00000100;
+
+ /**
* Mask for the wake lock level component of a combined wake lock level and flags integer.
*
* @hide
@@ -525,6 +534,7 @@
case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
case DOZE_WAKE_LOCK:
case DRAW_WAKE_LOCK:
+ case SUSTAINED_PERFORMANCE_WAKE_LOCK:
break;
default:
throw new IllegalArgumentException("Must specify a valid wake lock level.");
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index f765336..58a0269 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -91,4 +91,19 @@
* the icon is in this method.
*/
public abstract void setUserIcon(int userId, Bitmap bitmap);
+
+ /**
+ * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to inform the
+ * user manager whether all users should be created ephemeral.
+ */
+ public abstract void setForceEphemeralUsers(boolean forceEphemeralUsers);
+
+ /**
+ * Switches to the system user and deletes all other users.
+ *
+ * <p>Called by the {@link com.android.server.devicepolicy.DevicePolicyManagerService} when
+ * the force-ephemeral-users policy is toggled on to make sure there are no pre-existing
+ * non-ephemeral users left.
+ */
+ public abstract void removeAllUsers();
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a9fd3c8..bc0d7d6 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5073,6 +5073,14 @@
public static final String TTS_DEFAULT_SYNTH = "tts_default_synth";
/**
+ * Whether text-to-speech higher speech rate is enabled.
+ * 0 = disabled.
+ * 1 = enabled.
+ * @hide
+ */
+ public static final String TTS_DEFAULT_HIGHER_SPEECH_RATE_ENABLED =
+ "tts_default_higher_speech_rate_enabled";
+ /**
* Default text-to-speech language.
*
* @deprecated this setting is no longer in use, as of the Ice Cream
@@ -5884,6 +5892,7 @@
ACCESSIBILITY_CAPTIONING_WINDOW_COLOR,
TTS_USE_DEFAULTS,
TTS_DEFAULT_RATE,
+ TTS_DEFAULT_HIGHER_SPEECH_RATE_ENABLED,
TTS_DEFAULT_PITCH,
TTS_DEFAULT_SYNTH,
TTS_DEFAULT_LANG,
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index 24683cb..8ee9d1e 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -101,6 +101,12 @@
public static final String ACTION_FETCH_VOICEMAIL = "android.intent.action.FETCH_VOICEMAIL";
/**
+ * Broadcast intent to request all voicemail sources to perform a sync with the remote server.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_SYNC_VOICEMAIL = "android.intent.action.SYNC_VOICEMAIL";
+
+ /**
* Extra included in {@link Intent#ACTION_PROVIDER_CHANGED} broadcast intents to indicate if the
* receiving package made this change.
*/
@@ -393,6 +399,14 @@
* <P>Type: INTEGER</P>
*/
public static final String CONFIGURATION_STATE = "configuration_state";
+ /**
+ * Value of {@link #CONFIGURATION_STATE} passed into
+ * {@link #setStatus(Context, PhoneAccountHandle, int, int, int)} to indicate that the
+ * {@link #CONFIGURATION_STATE} field is not to be changed
+ *
+ * @hide
+ */
+ public static final int CONFIGURATION_STATE_IGNORE = -1;
/** Value of {@link #CONFIGURATION_STATE} to indicate an all OK configuration status. */
public static final int CONFIGURATION_STATE_OK = 0;
/**
@@ -418,15 +432,50 @@
*/
public static final String DATA_CHANNEL_STATE = "data_channel_state";
/**
+ * Value of {@link #DATA_CHANNEL_STATE} passed into
+ * {@link #setStatus(Context, PhoneAccountHandle, int, int, int)} to indicate that the
+ * {@link #DATA_CHANNEL_STATE} field is not to be changed
+ *
+ * @hide
+ */
+ public static final int DATA_CHANNEL_STATE_IGNORE = -1;
+ /**
* Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel is working fine.
*/
public static final int DATA_CHANNEL_STATE_OK = 0;
/**
- * Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel connection is not
- * working.
+ * Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel failed to find a
+ * suitable network to connect to the server.
*/
public static final int DATA_CHANNEL_STATE_NO_CONNECTION = 1;
/**
+ * Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel failed to find a
+ * suitable network to connect to the server, and the carrier requires using cellular
+ * data network to connect to the server.
+ */
+ public static final int DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED = 2;
+ /**
+ * Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel received incorrect
+ * settings or credentials to connect to the server
+ */
+ public static final int DATA_CHANNEL_STATE_BAD_CONFIGURATION = 3;
+ /**
+ * Value of {@link #DATA_CHANNEL_STATE} to indicate that a error has occurred in the data
+ * channel while communicating with the server
+ */
+ public static final int DATA_CHANNEL_STATE_COMMUNICATION_ERROR = 4;
+ /**
+ * Value of {@link #DATA_CHANNEL_STATE} to indicate that the server reported an internal
+ * error to the data channel.
+ */
+ public static final int DATA_CHANNEL_STATE_SERVER_ERROR = 5;
+ /**
+ * Value of {@link #DATA_CHANNEL_STATE} to indicate that while there is a suitable network,
+ * the data channel is unable to establish a connection with the server.
+ */
+ public static final int DATA_CHANNEL_STATE_SERVER_CONNECTION_ERROR = 6;
+
+ /**
* The notification channel state of the voicemail source. This is the channel through which
* the source gets notified of new voicemails on the remote server.
* <P> Possible values:
@@ -438,6 +487,14 @@
*/
public static final String NOTIFICATION_CHANNEL_STATE = "notification_channel_state";
/**
+ * Value of {@link #NOTIFICATION_CHANNEL_STATE} passed into
+ * {@link #setStatus(Context, PhoneAccountHandle, int, int, int)} to indicate that the
+ * {@link #NOTIFICATION_CHANNEL_STATE} field is not to be changed
+ *
+ * @hide
+ */
+ public static final int NOTIFICATION_CHANNEL_STATE_IGNORE = -1;
+ /**
* Value of {@link #NOTIFICATION_CHANNEL_STATE} to indicate that the notification channel is
* working fine.
*/
@@ -497,21 +554,22 @@
*/
public static void setStatus(Context context, PhoneAccountHandle accountHandle,
int configurationState, int dataChannelState, int notificationChannelState) {
- ContentResolver contentResolver = context.getContentResolver();
- Uri statusUri = buildSourceUri(context.getPackageName());
ContentValues values = new ContentValues();
values.put(Status.PHONE_ACCOUNT_COMPONENT_NAME,
accountHandle.getComponentName().flattenToString());
values.put(Status.PHONE_ACCOUNT_ID, accountHandle.getId());
- values.put(Status.CONFIGURATION_STATE, configurationState);
- values.put(Status.DATA_CHANNEL_STATE, dataChannelState);
- values.put(Status.NOTIFICATION_CHANNEL_STATE, notificationChannelState);
-
- if (isStatusPresent(contentResolver, statusUri)) {
- contentResolver.update(statusUri, values, null, null);
- } else {
- contentResolver.insert(statusUri, values);
+ if(configurationState != CONFIGURATION_STATE_IGNORE) {
+ values.put(Status.CONFIGURATION_STATE, configurationState);
}
+ if(dataChannelState != DATA_CHANNEL_STATE_IGNORE) {
+ values.put(Status.DATA_CHANNEL_STATE, dataChannelState);
+ }
+ if(notificationChannelState != NOTIFICATION_CHANNEL_STATE_IGNORE) {
+ values.put(Status.NOTIFICATION_CHANNEL_STATE, notificationChannelState);
+ }
+ ContentResolver contentResolver = context.getContentResolver();
+ Uri statusUri = buildSourceUri(context.getPackageName());
+ contentResolver.insert(statusUri, values);
}
/**
@@ -540,28 +598,7 @@
ContentResolver contentResolver = context.getContentResolver();
Uri statusUri = buildSourceUri(context.getPackageName());
- if (isStatusPresent(contentResolver, statusUri)) {
- contentResolver.update(statusUri, values, null, null);
- } else {
- contentResolver.insert(statusUri, values);
- }
- }
-
- /**
- * Determines if a voicemail source exists in the status table.
- *
- * @param contentResolver A content resolver constructed from the appropriate context.
- * @param statusUri The content uri for the source.
- * @return {@code true} if a status entry for this source exists
- */
- private static boolean isStatusPresent(ContentResolver contentResolver, Uri statusUri) {
- Cursor cursor = null;
- try {
- cursor = contentResolver.query(statusUri, null, null, null, null);
- return cursor != null && cursor.getCount() != 0;
- } finally {
- if (cursor != null) cursor.close();
- }
+ contentResolver.insert(statusUri, values);
}
}
}
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 035462d..bd41fb5 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -98,6 +98,9 @@
/** Notification was canceled by the user banning the topic. */
public static final int REASON_TOPIC_BANNED = 14;
+ /** Notification was canceled by the device administrator suspending the package. */
+ public static final int REASON_PACKAGE_SUSPENDED = 15;
+
public class Adjustment {
int mImportance;
CharSequence mExplanation;
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index ac7d539..76a401d 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -31,6 +31,7 @@
import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
+import android.hardware.soundtrigger.SoundTrigger.RecognitionEvent;
import android.media.AudioFormat;
import android.os.AsyncTask;
import android.os.Handler;
@@ -616,7 +617,11 @@
}
@Override
- public void onDetected(KeyphraseRecognitionEvent event) {
+ public void onDetected(RecognitionEvent event) {
+ if (! (event instanceof KeyphraseRecognitionEvent)) {
+ Slog.e(TAG, "onDetected() called for a soundtrigger event.");
+ return;
+ }
if (DBG) {
Slog.d(TAG, "onDetected(" + event + ")");
} else {
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index cd19607..a985517 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -271,7 +271,7 @@
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropRect) {
+ Configuration newConfig, Rect backDropRect, boolean forceLayout) {
Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED,
reportDraw ? 1 : 0, outsets);
mCaller.sendMessage(msg);
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
index b491710..ed91239c 100644
--- a/core/java/android/text/Html.java
+++ b/core/java/android/text/Html.java
@@ -165,6 +165,11 @@
| FROM_HTML_SEPARATOR_LINE_BREAK_DIV
| FROM_HTML_SEPARATOR_LINE_BREAK_BLOCKQUOTE;
+ /**
+ * The bit which indicates if lines delimited by '\n' will be grouped into <p> elements.
+ */
+ private static final int TO_HTML_PARAGRAPH_FLAG = 0x00000001;
+
private Html() { }
/**
@@ -255,7 +260,7 @@
*/
public static String toHtml(Spanned text, int option) {
StringBuilder out = new StringBuilder();
- withinHtml(out, text);
+ withinHtml(out, text, option);
return out.toString();
}
@@ -268,7 +273,16 @@
return out.toString();
}
- private static void withinHtml(StringBuilder out, Spanned text) {
+ private static void withinHtml(StringBuilder out, Spanned text, int option) {
+ if ((option & TO_HTML_PARAGRAPH_FLAG) == TO_HTML_PARAGRAPH_LINES_CONSECUTIVE) {
+ encodeTextAlignmentByDiv(out, text, option);
+ return;
+ }
+
+ withinDiv(out, text, 0, text.length(), option);
+ }
+
+ private static void encodeTextAlignmentByDiv(StringBuilder out, Spanned text, int option) {
int len = text.length();
int next;
@@ -296,7 +310,7 @@
out.append("<div ").append(elements).append(">");
}
- withinDiv(out, text, i, next);
+ withinDiv(out, text, i, next, option);
if (needDiv) {
out.append("</div>");
@@ -304,8 +318,8 @@
}
}
- private static void withinDiv(StringBuilder out, Spanned text,
- int start, int end) {
+ private static void withinDiv(StringBuilder out, Spanned text, int start, int end,
+ int option) {
int next;
for (int i = start; i < end; i = next) {
next = text.nextSpanTransition(i, end, QuoteSpan.class);
@@ -315,7 +329,7 @@
out.append("<blockquote>");
}
- withinBlockquote(out, text, i, next);
+ withinBlockquote(out, text, i, next, option);
for (QuoteSpan quote : quotes) {
out.append("</blockquote>\n");
@@ -323,7 +337,7 @@
}
}
- private static String getOpenParaTagWithDirection(Spanned text, int start, int end) {
+ private static String getTextDirection(Spanned text, int start, int end) {
final int len = end - start;
final byte[] levels = ArrayUtils.newUnpaddedByteArray(len);
final char[] buffer = TextUtils.obtain(len);
@@ -333,16 +347,101 @@
false /* no info */);
switch(paraDir) {
case Layout.DIR_RIGHT_TO_LEFT:
- return "<p dir=\"rtl\">";
+ return " dir=\"rtl\"";
case Layout.DIR_LEFT_TO_RIGHT:
default:
- return "<p dir=\"ltr\">";
+ return " dir=\"ltr\"";
}
}
- private static void withinBlockquote(StringBuilder out, Spanned text,
- int start, int end) {
- out.append(getOpenParaTagWithDirection(text, start, end));
+ private static String getTextStyles(Spanned text, int start, int end) {
+ final StringBuilder style = new StringBuilder(" style=\"margin-top:0; margin-bottom:0;");
+
+ final AlignmentSpan[] alignmentSpans = text.getSpans(start, end, AlignmentSpan.class);
+ final int len = alignmentSpans.length;
+ if (len > 0) {
+ final Layout.Alignment alignment = alignmentSpans[len - 1].getAlignment();
+ if (alignment == Layout.Alignment.ALIGN_NORMAL) {
+ style.append(" text-align:start;");
+ } else if (alignment == Layout.Alignment.ALIGN_CENTER) {
+ style.append(" text-align:center;");
+ } else if (alignment == Layout.Alignment.ALIGN_OPPOSITE) {
+ style.append(" text-align:end;");
+ }
+ }
+
+ style.append("\"");
+ return style.toString();
+ }
+
+ private static void withinBlockquote(StringBuilder out, Spanned text, int start, int end,
+ int option) {
+ if ((option & TO_HTML_PARAGRAPH_FLAG) == TO_HTML_PARAGRAPH_LINES_CONSECUTIVE) {
+ withinBlockquoteConsecutive(out, text, start, end);
+ } else {
+ withinBlockquoteIndividual(out, text, start, end);
+ }
+ }
+
+ private static void withinBlockquoteIndividual(StringBuilder out, Spanned text, int start,
+ int end) {
+ boolean isInList = false;
+ int next;
+ for (int i = start; i <= end; i = next) {
+ next = TextUtils.indexOf(text, '\n', i, end);
+ if (next < 0) {
+ next = end;
+ }
+
+ boolean isListItem = false;
+ ParagraphStyle[] paragraphStyles = text.getSpans(i, next, ParagraphStyle.class);
+ for (ParagraphStyle paragraphStyle : paragraphStyles) {
+ final int spanFlags = text.getSpanFlags(paragraphStyle);
+ if ((spanFlags & Spanned.SPAN_PARAGRAPH) == Spanned.SPAN_PARAGRAPH
+ && paragraphStyle instanceof BulletSpan) {
+ isListItem = true;
+ break;
+ }
+ }
+
+ if (isListItem && !isInList) {
+ // Current paragraph is the first item in a list
+ isInList = true;
+ out.append("<ul>\n");
+ }
+
+ if (isInList && !isListItem) {
+ // Current paragraph is no longer a list item; close the previously opened list
+ isInList = false;
+ out.append("</ul>\n");
+ }
+
+ String tagType = isListItem ? "li" : "p";
+ out.append("<").append(tagType).append(getTextDirection(text, start, next))
+ .append(getTextStyles(text, start, next)).append(">");
+
+ if (next - i == 0) {
+ out.append("<br>");
+ } else {
+ withinParagraph(out, text, i, next);
+ }
+
+ out.append("</");
+ out.append(tagType);
+ out.append(">\n");
+
+ if (next == end && isInList) {
+ isInList = false;
+ out.append("</ul>\n");
+ }
+
+ next++;
+ }
+ }
+
+ private static void withinBlockquoteConsecutive(StringBuilder out, Spanned text, int start,
+ int end) {
+ out.append("<p").append(getTextDirection(text, start, end)).append(">");
int next;
for (int i = start; i < end; i = next) {
@@ -358,19 +457,26 @@
next++;
}
- if (withinParagraph(out, text, i, next - nl, nl, next == end)) {
- /* Paragraph should be closed */
- out.append("</p>\n");
- out.append(getOpenParaTagWithDirection(text, next, end));
+ withinParagraph(out, text, i, next - nl);
+
+ if (nl == 1) {
+ out.append("<br>\n");
+ } else {
+ for (int j = 2; j < nl; j++) {
+ out.append("<br>");
+ }
+ if (next != end) {
+ /* Paragraph should be closed and reopened */
+ out.append("</p>\n");
+ out.append("<p").append(getTextDirection(text, start, end)).append(">");
+ }
}
}
out.append("</p>\n");
}
- /* Returns true if the caller should close and reopen the paragraph. */
- private static boolean withinParagraph(StringBuilder out, Spanned text, int start, int end,
- int nl, boolean last) {
+ private static void withinParagraph(StringBuilder out, Spanned text, int start, int end) {
int next;
for (int i = start; i < end; i = next) {
next = text.nextSpanTransition(i, end, CharacterStyle.class);
@@ -494,16 +600,6 @@
}
}
}
-
- if (nl == 1) {
- out.append("<br>\n");
- return false;
- } else {
- for (int i = 2; i < nl; i++) {
- out.append("<br>");
- }
- return !last;
- }
}
private static void withinStyle(StringBuilder out, CharSequence text,
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index c5ed39a..3688d50 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -49,7 +49,7 @@
void resized(in Rect frame, in Rect overscanInsets, in Rect contentInsets,
in Rect visibleInsets, in Rect stableInsets, in Rect outsets, boolean reportDraw,
- in Configuration newConfig, in Rect backDropFrame);
+ in Configuration newConfig, in Rect backDropFrame, boolean forceLayout);
void moved(int newX, int newY);
void dispatchAppVisibility(boolean visible);
void dispatchGetNewSurface();
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 9f6d3e5..5b48e28 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -698,7 +698,7 @@
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropRect) {
+ Configuration newConfig, Rect backDropRect, boolean forceLayout) {
SurfaceView surfaceView = mSurfaceView.get();
if (surfaceView != null) {
if (DEBUG) Log.v(
@@ -711,7 +711,8 @@
surfaceView.mReportDrawNeeded = true;
surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
} else if (surfaceView.mWinFrame.width() != frame.width()
- || surfaceView.mWinFrame.height() != frame.height()) {
+ || surfaceView.mWinFrame.height() != frame.height()
+ || forceLayout) {
surfaceView.mUpdateWindowNeeded = true;
surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 5d41477..98e3289 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -263,6 +264,7 @@
boolean mNewSurfaceNeeded;
boolean mHasHadWindowFocus;
boolean mLastWasImTarget;
+ boolean mForceNextWindowRelayout;
CountDownLatch mWindowDrawCountDown;
boolean mIsDrawing;
@@ -1625,7 +1627,8 @@
final boolean isViewVisible = viewVisibility == View.VISIBLE;
if (mFirst || windowShouldResize || insetsChanged ||
- viewVisibilityChanged || params != null) {
+ viewVisibilityChanged || params != null || mForceNextWindowRelayout) {
+ mForceNextWindowRelayout = false;
if (isViewVisible) {
// If this window is giving internal insets to the window
@@ -2099,7 +2102,7 @@
boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;
- if (!cancelDraw && !newSurface) {
+ if (!cancelDraw) {
if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
for (int i = 0; i < mPendingTransitions.size(); ++i) {
mPendingTransitions.get(i).startChangingAnimations();
@@ -2148,6 +2151,7 @@
}
}
}
+
private void handleOutOfResourcesException(Surface.OutOfResourcesException e) {
Log.e(mTag, "OutOfResourcesException initializing HW surface", e);
try {
@@ -3365,7 +3369,8 @@
&& mPendingVisibleInsets.equals(args.arg3)
&& mPendingOutsets.equals(args.arg7)
&& mPendingBackDropFrame.equals(args.arg8)
- && args.arg4 == null) {
+ && args.arg4 == null
+ && args.argi1 == 0) {
break;
}
} // fall through...
@@ -3385,6 +3390,7 @@
mPendingVisibleInsets.set((Rect) args.arg3);
mPendingOutsets.set((Rect) args.arg7);
mPendingBackDropFrame.set((Rect) args.arg8);
+ mForceNextWindowRelayout = args.argi1 != 0;
args.recycle();
@@ -5829,7 +5835,7 @@
public void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropFrame) {
+ Configuration newConfig, Rect backDropFrame, boolean forceLayout) {
if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString()
+ " contentInsets=" + contentInsets.toShortString()
+ " visibleInsets=" + visibleInsets.toShortString()
@@ -5863,6 +5869,7 @@
args.arg6 = sameProcessCall ? new Rect(stableInsets) : stableInsets;
args.arg7 = sameProcessCall ? new Rect(outsets) : outsets;
args.arg8 = sameProcessCall ? new Rect(backDropFrame) : backDropFrame;
+ args.argi1 = forceLayout ? 1 : 0;
msg.obj = args;
mHandler.sendMessage(msg);
}
@@ -6878,11 +6885,12 @@
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropFrame) {
+ Configuration newConfig, Rect backDropFrame, boolean forceLayout) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
viewAncestor.dispatchResized(frame, overscanInsets, contentInsets,
- visibleInsets, stableInsets, outsets, reportDraw, newConfig, backDropFrame);
+ visibleInsets, stableInsets, outsets, reportDraw, newConfig, backDropFrame,
+ forceLayout);
}
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 9561f08..df84970 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1036,6 +1036,7 @@
mChoiceActionMode = startActionMode(mMultiChoiceModeCallback);
}
+ final boolean itemCheckChanged;
if (mChoiceMode == CHOICE_MODE_MULTIPLE || mChoiceMode == CHOICE_MODE_MULTIPLE_MODAL) {
boolean oldValue = mCheckStates.get(position);
mCheckStates.put(position, value);
@@ -1046,7 +1047,8 @@
mCheckedIdStates.delete(mAdapter.getItemId(position));
}
}
- if (oldValue != value) {
+ itemCheckChanged = oldValue != value;
+ if (itemCheckChanged) {
if (value) {
mCheckedItemCount++;
} else {
@@ -1062,6 +1064,7 @@
boolean updateIds = mCheckedIdStates != null && mAdapter.hasStableIds();
// Clear all values if we're checking something, or unchecking the currently
// selected item
+ itemCheckChanged = isItemChecked(position) != value;
if (value || isItemChecked(position)) {
mCheckStates.clear();
if (updateIds) {
@@ -1081,8 +1084,8 @@
}
}
- // Do not generate a data change while we are in the layout phase
- if (!mInLayout && !mBlockLayoutRequests) {
+ // Do not generate a data change while we are in the layout phase or data has not changed
+ if (!mInLayout && !mBlockLayoutRequests && itemCheckChanged) {
mDataChanged = true;
rememberSyncState();
requestLayout();
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index b7b7400..2733391 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -66,6 +66,7 @@
import android.widget.ListView;
import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import java.util.ArrayList;
import java.util.Collections;
@@ -209,7 +210,7 @@
super.onCreate(savedInstanceState, target, title, defaultTitleRes, initialIntents,
null, false);
- MetricsLogger.action(this, MetricsLogger.ACTION_ACTIVITY_CHOOSER_SHOWN);
+ MetricsLogger.action(this, MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN);
}
@Override
@@ -349,14 +350,14 @@
int value = which;
switch (mChooserListAdapter.getPositionTargetType(which)) {
case ChooserListAdapter.TARGET_CALLER:
- cat = MetricsLogger.ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET;
+ cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET;
break;
case ChooserListAdapter.TARGET_SERVICE:
- cat = MetricsLogger.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET;
+ cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET;
value -= mChooserListAdapter.getCallerTargetCount();
break;
case ChooserListAdapter.TARGET_STANDARD:
- cat = MetricsLogger.ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET;
+ cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET;
value -= mChooserListAdapter.getCallerTargetCount()
+ mChooserListAdapter.getServiceTargetCount();
break;
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 3b9b8db..ec53a2e 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -121,4 +121,7 @@
void setBatteryState(int status, int health, int plugType, int level, int temp, int volt);
long getAwakeTimeBattery();
long getAwakeTimePlugged();
+
+ void noteBleScanStarted(in WorkSource ws);
+ void noteBleScanStopped(in WorkSource ws);
}
diff --git a/core/java/com/android/internal/app/ISoundTriggerService.aidl b/core/java/com/android/internal/app/ISoundTriggerService.aidl
new file mode 100644
index 0000000..9de4a6c
--- /dev/null
+++ b/core/java/com/android/internal/app/ISoundTriggerService.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 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.internal.app;
+
+import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.os.ParcelUuid;
+
+/**
+ * Service interface for a generic sound recognition model.
+ * @hide
+ */
+interface ISoundTriggerService {
+
+
+ SoundTrigger.GenericSoundModel getSoundModel(in ParcelUuid soundModelId);
+
+ void updateSoundModel(in SoundTrigger.GenericSoundModel soundModel);
+
+ void deleteSoundModel(in ParcelUuid soundModelId);
+
+ void startRecognition(in ParcelUuid soundModelId, in IRecognitionStatusCallback callback);
+
+ /**
+ * Stops recognition.
+ */
+ void stopRecognition(in ParcelUuid soundModelId, in IRecognitionStatusCallback callback);
+}
diff --git a/core/java/com/android/internal/logging/MetricsConstants.java b/core/java/com/android/internal/logging/MetricsConstants.java
deleted file mode 100644
index 522732d..0000000
--- a/core/java/com/android/internal/logging/MetricsConstants.java
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.internal.logging;
-
-/**
- * Constants for mestrics logs.
- *
- * @hide
- */
-public interface MetricsConstants {
- // These constants must match those in the analytic pipeline, do not edit.
- // define metric categories in frameworks/base/core/proto/src/metrics_constants.proto.
- public static final int MAIN_SETTINGS = 1;
- public static final int ACCESSIBILITY = 2;
- public static final int ACCESSIBILITY_CAPTION_PROPERTIES = 3;
- public static final int ACCESSIBILITY_SERVICE = 4;
- public static final int ACCESSIBILITY_TOGGLE_DALTONIZER = 5;
- public static final int ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE = 6;
- public static final int ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION = 7;
- public static final int ACCOUNT = 8;
- public static final int ACCOUNTS_ACCOUNT_SYNC = 9;
- public static final int ACCOUNTS_CHOOSE_ACCOUNT_ACTIVITY = 10;
- public static final int ACCOUNTS_MANAGE_ACCOUNTS = 11;
- public static final int APN = 12;
- public static final int APN_EDITOR = 13;
- public static final int APP_OPS_DETAILS = 14;
- public static final int APP_OPS_SUMMARY = 15;
- public static final int APPLICATION = 16;
- public static final int APPLICATIONS_APP_LAUNCH = 17;
- public static final int APPLICATIONS_APP_PERMISSION = 18;
- public static final int APPLICATIONS_APP_STORAGE = 19;
- public static final int APPLICATIONS_INSTALLED_APP_DETAILS = 20;
- public static final int APPLICATIONS_PROCESS_STATS_DETAIL = 21;
- public static final int APPLICATIONS_PROCESS_STATS_MEM_DETAIL = 22;
- public static final int APPLICATIONS_PROCESS_STATS_UI = 23;
- public static final int BLUETOOTH = 24;
- public static final int BLUETOOTH_DEVICE_PICKER = 25;
- public static final int BLUETOOTH_DEVICE_PROFILES = 26;
- public static final int CHOOSE_LOCK_GENERIC = 27;
- public static final int CHOOSE_LOCK_PASSWORD = 28;
- public static final int CHOOSE_LOCK_PATTERN = 29;
- public static final int CONFIRM_LOCK_PASSWORD = 30;
- public static final int CONFIRM_LOCK_PATTERN = 31;
- public static final int CRYPT_KEEPER = 32;
- public static final int CRYPT_KEEPER_CONFIRM = 33;
- public static final int DASHBOARD_SEARCH_RESULTS = 34;
- public static final int DASHBOARD_SUMMARY = 35;
- public static final int DATA_USAGE = 36;
- public static final int DATA_USAGE_SUMMARY = 37;
- public static final int DATE_TIME = 38;
- public static final int DEVELOPMENT = 39;
- public static final int DEVICEINFO = 40;
- public static final int DEVICEINFO_IMEI_INFORMATION = 41;
- public static final int DEVICEINFO_STORAGE = 42;
- public static final int DEVICEINFO_SIM_STATUS = 43;
- public static final int DEVICEINFO_STATUS = 44;
- public static final int DEVICEINFO_USB = 45;
- public static final int DISPLAY = 46;
- public static final int DREAM = 47;
- public static final int ENCRYPTION = 48;
- public static final int FINGERPRINT = 49;
- public static final int FINGERPRINT_ENROLL = 50;
- public static final int FUELGAUGE_BATTERY_HISTORY_DETAIL = 51;
- public static final int FUELGAUGE_BATTERY_SAVER = 52;
- public static final int FUELGAUGE_POWER_USAGE_DETAIL = 53;
- public static final int FUELGAUGE_POWER_USAGE_SUMMARY = 54;
- public static final int HOME = 55;
- public static final int ICC_LOCK = 56;
- public static final int INPUTMETHOD_LANGUAGE = 57;
- public static final int INPUTMETHOD_KEYBOARD = 58;
- public static final int INPUTMETHOD_SPELL_CHECKERS = 59;
- public static final int INPUTMETHOD_SUBTYPE_ENABLER = 60;
- public static final int INPUTMETHOD_USER_DICTIONARY = 61;
- public static final int INPUTMETHOD_USER_DICTIONARY_ADD_WORD = 62;
- public static final int LOCATION = 63;
- public static final int LOCATION_MODE = 64;
- public static final int MANAGE_APPLICATIONS = 65;
- public static final int MASTER_CLEAR = 66;
- public static final int MASTER_CLEAR_CONFIRM = 67;
- public static final int NET_DATA_USAGE_METERED = 68;
- public static final int NFC_BEAM = 69;
- public static final int NFC_PAYMENT = 70;
- public static final int NOTIFICATION = 71;
- public static final int NOTIFICATION_APP_NOTIFICATION = 72;
- public static final int NOTIFICATION_OTHER_SOUND = 73;
- public static final int NOTIFICATION_REDACTION = 74;
- public static final int NOTIFICATION_STATION = 75;
- public static final int NOTIFICATION_ZEN_MODE = 76;
- public static final int OWNER_INFO = 77;
- public static final int PRINT_JOB_SETTINGS = 78;
- public static final int PRINT_SERVICE_SETTINGS = 79;
- public static final int PRINT_SETTINGS = 80;
- public static final int PRIVACY = 81;
- public static final int PROXY_SELECTOR = 82;
- public static final int RESET_NETWORK = 83;
- public static final int RESET_NETWORK_CONFIRM = 84;
- public static final int RUNNING_SERVICE_DETAILS = 85;
- public static final int SCREEN_PINNING = 86;
- public static final int SECURITY = 87;
- public static final int SIM = 88;
- public static final int TESTING = 89;
- public static final int TETHER = 90;
- public static final int TRUST_AGENT = 91;
- public static final int TRUSTED_CREDENTIALS = 92;
- public static final int TTS_ENGINE_SETTINGS = 93;
- public static final int TTS_TEXT_TO_SPEECH = 94;
- public static final int USAGE_ACCESS = 95;
- public static final int USER = 96;
- public static final int USERS_APP_RESTRICTIONS = 97;
- public static final int USER_DETAILS = 98;
- public static final int VOICE_INPUT = 99;
- public static final int VPN = 100;
- public static final int WALLPAPER_TYPE = 101;
- public static final int WFD_WIFI_DISPLAY = 102;
- public static final int WIFI = 103;
- public static final int WIFI_ADVANCED = 104;
- public static final int WIFI_CALLING = 105;
- public static final int WIFI_SAVED_ACCESS_POINTS = 106;
- public static final int WIFI_APITEST = 107;
- public static final int WIFI_INFO = 108;
- public static final int WIFI_P2P = 109;
- public static final int WIRELESS = 110;
- public static final int QS_AIRPLANEMODE = 112;
- public static final int QS_BLUETOOTH = 113;
- public static final int QS_CAST = 114;
- public static final int QS_CELLULAR = 115;
- public static final int QS_COLORINVERSION = 116;
- public static final int QS_DATAUSAGEDETAIL = 117;
- public static final int QS_DND = 118;
- public static final int QS_FLASHLIGHT = 119;
- public static final int QS_HOTSPOT = 120;
- public static final int QS_INTENT = 121;
- public static final int QS_LOCATION = 122;
- public static final int QS_ROTATIONLOCK = 123;
- public static final int QS_USERDETAILITE = 124;
- public static final int QS_USERDETAIL = 125;
- public static final int QS_WIFI = 126;
- public static final int NOTIFICATION_PANEL = 127;
- public static final int NOTIFICATION_ITEM = 128;
- public static final int NOTIFICATION_ITEM_ACTION = 129;
- public static final int APPLICATIONS_ADVANCED = 130;
- public static final int LOCATION_SCANNING = 131;
- public static final int MANAGE_APPLICATIONS_ALL = 132;
- public static final int MANAGE_APPLICATIONS_NOTIFICATIONS = 133;
- public static final int ACTION_WIFI_ADD_NETWORK = 134;
- public static final int ACTION_WIFI_CONNECT = 135;
- public static final int ACTION_WIFI_FORCE_SCAN = 136;
- public static final int ACTION_WIFI_FORGET = 137;
- public static final int ACTION_WIFI_OFF = 138;
- public static final int ACTION_WIFI_ON = 139;
- public static final int MANAGE_PERMISSIONS = 140;
- public static final int NOTIFICATION_ZEN_MODE_PRIORITY = 141;
- public static final int NOTIFICATION_ZEN_MODE_AUTOMATION = 142;
- public static final int MANAGE_DOMAIN_URLS = 143;
- public static final int NOTIFICATION_ZEN_MODE_SCHEDULE_RULE = 144;
- public static final int NOTIFICATION_ZEN_MODE_EXTERNAL_RULE = 145;
- public static final int NOTIFICATION_ZEN_MODE_EVENT_RULE = 146;
- public static final int ACTION_BAN_APP_NOTES = 147;
- public static final int ACTION_DISMISS_ALL_NOTES = 148;
- public static final int QS_DND_DETAILS = 149;
- public static final int QS_BLUETOOTH_DETAILS = 150;
- public static final int QS_CAST_DETAILS = 151;
- public static final int QS_WIFI_DETAILS = 152;
- public static final int QS_WIFI_TOGGLE = 153;
- public static final int QS_BLUETOOTH_TOGGLE = 154;
- public static final int QS_CELLULAR_TOGGLE = 155;
- public static final int QS_SWITCH_USER = 156;
- public static final int QS_CAST_SELECT = 157;
- public static final int QS_CAST_DISCONNECT = 158;
- public static final int ACTION_BLUETOOTH_TOGGLE = 159;
- public static final int ACTION_BLUETOOTH_SCAN = 160;
- public static final int ACTION_BLUETOOTH_RENAME = 161;
- public static final int ACTION_BLUETOOTH_FILES = 162;
- public static final int QS_DND_TIME = 163;
- public static final int QS_DND_CONDITION_SELECT = 164;
- public static final int QS_DND_ZEN_SELECT = 165;
- public static final int QS_DND_TOGGLE = 166;
- public static final int ACTION_ZEN_ALLOW_REMINDERS = 167;
- public static final int ACTION_ZEN_ALLOW_EVENTS = 168;
- public static final int ACTION_ZEN_ALLOW_MESSAGES = 169;
- public static final int ACTION_ZEN_ALLOW_CALLS = 170;
- public static final int ACTION_ZEN_ALLOW_REPEAT_CALLS = 171;
- public static final int ACTION_ZEN_ADD_RULE = 172;
- public static final int ACTION_ZEN_ADD_RULE_OK = 173;
- public static final int ACTION_ZEN_DELETE_RULE = 174;
- public static final int ACTION_ZEN_DELETE_RULE_OK = 175;
- public static final int ACTION_ZEN_ENABLE_RULE = 176;
- public static final int ACTION_AIRPLANE_TOGGLE = 177;
- public static final int ACTION_CELL_DATA_TOGGLE = 178;
- public static final int NOTIFICATION_ACCESS = 179;
- public static final int NOTIFICATION_ZEN_MODE_ACCESS = 180;
- public static final int APPLICATIONS_DEFAULT_APPS = 181;
- public static final int APPLICATIONS_STORAGE_APPS = 182;
- public static final int APPLICATIONS_USAGE_ACCESS_DETAIL = 183;
- public static final int APPLICATIONS_HIGH_POWER_APPS = 184;
- public static final int FUELGAUGE_HIGH_POWER_DETAILS = 185;
- public static final int ACTION_LS_UNLOCK = 186;
- public static final int ACTION_LS_SHADE = 187;
- public static final int ACTION_LS_HINT = 188;
- public static final int ACTION_LS_CAMERA = 189;
- public static final int ACTION_LS_DIALER = 190;
- public static final int ACTION_LS_LOCK = 191;
- public static final int ACTION_LS_NOTE = 192;
- public static final int ACTION_LS_QS = 193;
- public static final int ACTION_SHADE_QS_PULL = 194;
- public static final int ACTION_SHADE_QS_TAP = 195;
- public static final int LOCKSCREEN = 196;
- public static final int BOUNCER = 197;
- public static final int SCREEN = 198;
- public static final int NOTIFICATION_ALERT = 199;
- public static final int ACTION_EMERGENCY_CALL = 200;
- public static final int APPLICATIONS_MANAGE_ASSIST = 201;
- public static final int PROCESS_STATS_SUMMARY = 202;
- public static final int ACTION_ROTATION_LOCK = 203;
- public static final int ACTION_NOTE_CONTROLS = 204;
- public static final int ACTION_NOTE_INFO = 205;
- public static final int ACTION_APP_NOTE_SETTINGS = 206;
- public static final int VOLUME_DIALOG = 207;
- public static final int VOLUME_DIALOG_DETAILS = 208;
- public static final int ACTION_VOLUME_SLIDER = 209;
- public static final int ACTION_VOLUME_STREAM = 210;
- public static final int ACTION_VOLUME_KEY = 211;
- public static final int ACTION_VOLUME_ICON = 212;
- public static final int ACTION_RINGER_MODE = 213;
- public static final int ACTION_ACTIVITY_CHOOSER_SHOWN = 214;
- public static final int ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET = 215;
- public static final int ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET = 216;
- public static final int ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET = 217;
- public static final int ACTION_BRIGHTNESS = 218;
- public static final int ACTION_BRIGHTNESS_AUTO = 219;
- public static final int BRIGHTNESS_DIALOG = 220;
- public static final int SYSTEM_ALERT_WINDOW_APPS = 221;
- public static final int DREAMING = 222;
- public static final int DOZING = 223;
- public static final int OVERVIEW_ACTIVITY = 224;
- public static final int ABOUT_LEGAL_SETTINGS = 225;
- public static final int ACTION_SEARCH_RESULTS = 226;
- public static final int TUNER = 227;
- public static final int TUNER_QS = 228;
- public static final int TUNER_DEMO_MODE = 229;
- public static final int TUNER_QS_REORDER = 230;
- public static final int TUNER_QS_ADD = 231;
- public static final int TUNER_QS_REMOVE = 232;
- public static final int TUNER_STATUS_BAR_ENABLE = 233;
- public static final int TUNER_STATUS_BAR_DISABLE = 234;
- public static final int TUNER_DEMO_MODE_ENABLED = 235;
- public static final int TUNER_DEMO_MODE_ON = 236;
- public static final int TUNER_BATTERY_PERCENTAGE = 237;
- public static final int FUELGAUGE_INACTIVE_APPS = 238;
- public static final int ACTION_ASSIST_LONG_PRESS = 239;
- public static final int FINGERPRINT_ENROLLING = 240;
- public static final int FINGERPRINT_FIND_SENSOR = 241;
- public static final int FINGERPRINT_ENROLL_FINISH = 242;
- public static final int FINGERPRINT_ENROLL_INTRO = 243;
- public static final int FINGERPRINT_ENROLL_ONBOARD = 244;
- public static final int FINGERPRINT_ENROLL_SIDECAR = 245;
- public static final int FINGERPRINT_ENROLLING_SETUP = 246;
- public static final int FINGERPRINT_FIND_SENSOR_SETUP = 247;
- public static final int FINGERPRINT_ENROLL_FINISH_SETUP = 248;
- public static final int FINGERPRINT_ENROLL_INTRO_SETUP = 249;
- public static final int FINGERPRINT_ENROLL_ONBOARD_SETUP = 250;
- public static final int ACTION_FINGERPRINT_ENROLL = 251;
- public static final int ACTION_FINGERPRINT_AUTH = 252;
- public static final int ACTION_FINGERPRINT_DELETE = 253;
- public static final int ACTION_FINGERPRINT_RENAME = 254;
- public static final int ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE = 255;
- public static final int ACTION_WIGGLE_CAMERA_GESTURE = 256;
- public static final int QS_WORKMODE = 257;
- public static final int BACKGROUND_CHECK_SUMMARY = 258;
- public static final int QS_LOCK_TILE = 259;
- public static final int QS_USER_TILE = 260;
- public static final int QS_BATTERY_TILE = 261;
- public static final int NOTIFICATION_ZEN_MODE_VISUAL_INTERRUPTIONS = 262;
- public static final int ACTION_ZEN_ALLOW_PEEK = 263;
- public static final int ACTION_ZEN_ALLOW_LIGHTS = 264;
- public static final int NOTIFICATION_TOPIC_NOTIFICATION = 265;
- public static final int ACTION_DEFAULT_SMS_APP_CHANGED = 266;
- public static final int QS_COLOR_MATRIX = 267;
- public static final int QS_CUSTOM = 268;
- public static final int ACTION_ZEN_ALLOW_SCREEN_ON = 269;
-
- /**
- * Logged when the user docks a window from recents by longpressing a task and dragging it to
- * the dock area.
- */
- public static final int ACTION_WINDOW_DOCK_DRAG_DROP = 270;
-
- /**
- * Logged when the user docks a fullscreen window by long pressing recents which also opens
- * recents on the lower/right side.
- */
- public static final int ACTION_WINDOW_DOCK_LONGPRESS = 271;
-
- /**
- * Logged when the user docks a window by dragging from the navbar which also opens recents on
- * the lower/right side.
- */
- public static final int ACTION_WINDOW_DOCK_SWIPE = 272;
-
- /**
- * Logged when the user launches a profile-specific app and we intercept it with the confirm
- * credentials UI.
- */
- public static final int PROFILE_CHALLENGE = 273;
- public static final int QS_BATTERY_DETAIL = 274;
-
- /**
- * Logged when the user goes into the overview history.
- */
- public static final int OVERVIEW_HISTORY = 275;
-
- /**
- * Logged when the user pages through overview.
- */
- public static final int ACTION_OVERVIEW_PAGE = 276;
-
- /**
- * Logged when the user launches a task from overview.
- */
- public static final int ACTION_OVERVIEW_SELECT = 277;
-
- /** Logged when the user views the emergency info. */
- public static final int ACTION_VIEW_EMERGENCY_INFO = 278;
-
- /** Logged when the user views the edit emergency info activity. */
- public static final int ACTION_EDIT_EMERGENCY_INFO = 279;
-
- /** Logged when the user edits an emergency info field. */
- public static final int ACTION_EDIT_EMERGENCY_INFO_FIELD = 280;
-
- /** Logged when the user adds a new emergency contact. */
- public static final int ACTION_ADD_EMERGENCY_CONTACT = 281;
-
- /** Logged when the user deletes an emergency contact. */
- public static final int ACTION_DELETE_EMERGENCY_CONTACT = 282;
-
- /** Logged when the user calls an emergency contact. */
- public static final int ACTION_CALL_EMERGENCY_CONTACT = 283;
-}
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index 183d8d7..ef725da 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -26,8 +26,8 @@
*
* @hide
*/
-public class MetricsLogger implements com.android.internal.logging.MetricsConstants {
- // define metric categories in frameworks/base/core/proto/src/metrics_constants.proto.
+public class MetricsLogger {
+ // define metric categories in frameworks/base/proto/src/metrics_constants.proto.
public static final int VIEW_UNKNOWN = MetricsEvent.VIEW_UNKNOWN;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 57220b1..c71c131 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -41,6 +41,7 @@
import android.os.SystemProperties;
import android.os.WorkSource;
import android.telephony.DataConnectionRealTimeInfo;
+import android.telephony.ModemActivityInfo;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
@@ -106,7 +107,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 139 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 140 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -119,6 +120,12 @@
// in to one common name.
private static final int MAX_WAKELOCKS_PER_UID = 100;
+ // Number of transmit power states the Wifi controller can be in.
+ private static final int NUM_WIFI_TX_LEVELS = 1;
+
+ // Number of transmit power states the Bluetooth controller can be in.
+ private static final int NUM_BT_TX_LEVELS = 1;
+
private final JournaledFile mFile;
public final AtomicFile mCheckinFile;
public final AtomicFile mDailyFile;
@@ -379,11 +386,38 @@
final LongSamplingCounter[] mNetworkPacketActivityCounters =
new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
- final LongSamplingCounter[] mBluetoothActivityCounters =
- new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];
+ /**
+ * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
+ */
+ ControllerActivityCounterImpl mWifiActivity;
- final LongSamplingCounter[] mWifiActivityCounters =
- new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];
+ /**
+ * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
+ */
+ ControllerActivityCounterImpl mBluetoothActivity;
+
+ /**
+ * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
+ */
+ ControllerActivityCounterImpl mModemActivity;
+
+ /**
+ * Whether the device supports WiFi controller energy reporting. This is set to true on
+ * the first WiFi energy report. See {@link #mWifiActivity}.
+ */
+ boolean mHasWifiReporting = false;
+
+ /**
+ * Whether the device supports Bluetooth controller energy reporting. This is set to true on
+ * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
+ */
+ boolean mHasBluetoothReporting = false;
+
+ /**
+ * Whether the device supports Modem controller energy reporting. This is set to true on
+ * the first Modem energy report. See {@link #mModemActivity}.
+ */
+ boolean mHasModemReporting = false;
boolean mWifiOn;
StopwatchTimer mWifiOnTimer;
@@ -479,8 +513,6 @@
private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();
private PowerProfile mPowerProfile;
- private boolean mHasWifiEnergyReporting = false;
- private boolean mHasBluetoothEnergyReporting = false;
/*
* Holds a SamplingTimer associated with each kernel wakelock name being tracked.
@@ -1770,6 +1802,131 @@
public abstract T instantiateObject();
}
+ public static class ControllerActivityCounterImpl extends ControllerActivityCounter
+ implements Parcelable {
+ private final LongSamplingCounter mIdleTimeMillis;
+ private final LongSamplingCounter mRxTimeMillis;
+ private final LongSamplingCounter[] mTxTimeMillis;
+ private final LongSamplingCounter mPowerDrainMaMs;
+
+ public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) {
+ mIdleTimeMillis = new LongSamplingCounter(timeBase);
+ mRxTimeMillis = new LongSamplingCounter(timeBase);
+ mTxTimeMillis = new LongSamplingCounter[numTxStates];
+ for (int i = 0; i < numTxStates; i++) {
+ mTxTimeMillis[i] = new LongSamplingCounter(timeBase);
+ }
+ mPowerDrainMaMs = new LongSamplingCounter(timeBase);
+ }
+
+ public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) {
+ mIdleTimeMillis = new LongSamplingCounter(timeBase, in);
+ mRxTimeMillis = new LongSamplingCounter(timeBase, in);
+ final int recordedTxStates = in.readInt();
+ if (recordedTxStates != numTxStates) {
+ throw new ParcelFormatException("inconsistent tx state lengths");
+ }
+
+ mTxTimeMillis = new LongSamplingCounter[numTxStates];
+ for (int i = 0; i < numTxStates; i++) {
+ mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in);
+ }
+ mPowerDrainMaMs = new LongSamplingCounter(timeBase, in);
+ }
+
+ public void readSummaryFromParcel(Parcel in) {
+ mIdleTimeMillis.readSummaryFromParcelLocked(in);
+ mRxTimeMillis.readSummaryFromParcelLocked(in);
+ final int recordedTxStates = in.readInt();
+ if (recordedTxStates != mTxTimeMillis.length) {
+ throw new ParcelFormatException("inconsistent tx state lengths");
+ }
+ for (LongSamplingCounter counter : mTxTimeMillis) {
+ counter.readSummaryFromParcelLocked(in);
+ }
+ mPowerDrainMaMs.readSummaryFromParcelLocked(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeSummaryToParcel(Parcel dest) {
+ mIdleTimeMillis.writeSummaryFromParcelLocked(dest);
+ mRxTimeMillis.writeSummaryFromParcelLocked(dest);
+ dest.writeInt(mTxTimeMillis.length);
+ for (LongSamplingCounter counter : mTxTimeMillis) {
+ counter.writeSummaryFromParcelLocked(dest);
+ }
+ mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ mIdleTimeMillis.writeToParcel(dest);
+ mRxTimeMillis.writeToParcel(dest);
+ dest.writeInt(mTxTimeMillis.length);
+ for (LongSamplingCounter counter : mTxTimeMillis) {
+ counter.writeToParcel(dest);
+ }
+ mPowerDrainMaMs.writeToParcel(dest);
+ }
+
+ public void reset(boolean detachIfReset) {
+ mIdleTimeMillis.reset(detachIfReset);
+ mRxTimeMillis.reset(detachIfReset);
+ for (LongSamplingCounter counter : mTxTimeMillis) {
+ counter.reset(detachIfReset);
+ }
+ mPowerDrainMaMs.reset(detachIfReset);
+ }
+
+ public void detach() {
+ mIdleTimeMillis.detach();
+ mRxTimeMillis.detach();
+ for (LongSamplingCounter counter : mTxTimeMillis) {
+ counter.detach();
+ }
+ mPowerDrainMaMs.detach();
+ }
+
+ /**
+ * @return a LongSamplingCounter, measuring time spent in the idle state in
+ * milliseconds.
+ */
+ @Override
+ public LongSamplingCounter getIdleTimeCounter() {
+ return mRxTimeMillis;
+ }
+
+ /**
+ * @return a LongSamplingCounter, measuring time spent in the receive state in
+ * milliseconds.
+ */
+ @Override
+ public LongSamplingCounter getRxTimeCounter() {
+ return mRxTimeMillis;
+ }
+
+ /**
+ * @return a LongSamplingCounter[], measuring time spent in various transmit states in
+ * milliseconds.
+ */
+ @Override
+ public LongSamplingCounter[] getTxTimeCounters() {
+ return mTxTimeMillis;
+ }
+
+ /**
+ * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
+ */
+ @Override
+ public LongSamplingCounter getPowerCounter() {
+ return mPowerDrainMaMs;
+ }
+ }
+
/*
* Get the wakeup reason counter, and create a new one if one
* doesn't already exist.
@@ -3198,7 +3355,7 @@
mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
} else {
mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
- updateMobileRadioStateLocked(realElapsedRealtimeMs);
+ updateMobileRadioStateLocked(realElapsedRealtimeMs, null);
mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
}
}
@@ -4144,8 +4301,7 @@
// During device boot, qtaguid isn't enabled until after the inital
// loading of battery stats. Now that they're enabled, take our initial
// snapshot for future delta calculation.
- final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
- updateMobileRadioStateLocked(elapsedRealtimeMs);
+ updateMobileRadioStateLocked(SystemClock.elapsedRealtime(), null);
updateWifiStateLocked(null);
}
@@ -4328,26 +4484,34 @@
return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
}
- @Override public boolean hasBluetoothActivityReporting() {
- return mHasBluetoothEnergyReporting;
+ @Override
+ public ControllerActivityCounter getBluetoothControllerActivity() {
+ return mBluetoothActivity;
}
- @Override public long getBluetoothControllerActivity(int type, int which) {
- if (type >= 0 && type < mBluetoothActivityCounters.length) {
- return mBluetoothActivityCounters[type].getCountLocked(which);
- }
- return 0;
+ @Override
+ public ControllerActivityCounter getWifiControllerActivity() {
+ return mWifiActivity;
}
- @Override public boolean hasWifiActivityReporting() {
- return mHasWifiEnergyReporting;
+ @Override
+ public ControllerActivityCounter getModemControllerActivity() {
+ return mModemActivity;
}
- @Override public long getWifiControllerActivity(int type, int which) {
- if (type >= 0 && type < mWifiActivityCounters.length) {
- return mWifiActivityCounters[type].getCountLocked(which);
- }
- return 0;
+ @Override
+ public boolean hasBluetoothActivityReporting() {
+ return mHasBluetoothReporting;
+ }
+
+ @Override
+ public boolean hasWifiActivityReporting() {
+ return mHasWifiReporting;
+ }
+
+ @Override
+ public boolean hasModemActivityReporting() {
+ return mHasModemReporting;
}
@Override
@@ -4457,15 +4621,21 @@
/**
* The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
+ * Can be null if the UID has had no such activity.
*/
- LongSamplingCounter[] mWifiControllerTime =
- new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];
+ private ControllerActivityCounterImpl mWifiControllerActivity;
/**
* The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
+ * Can be null if the UID has had no such activity.
*/
- LongSamplingCounter[] mBluetoothControllerTime =
- new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];
+ private ControllerActivityCounterImpl mBluetoothControllerActivity;
+
+ /**
+ * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
+ * Can be null if the UID has had no such activity.
+ */
+ private ControllerActivityCounterImpl mModemControllerActivity;
/**
* The CPU times we had at the last history details update.
@@ -4684,18 +4854,43 @@
}
}
- public void noteWifiControllerActivityLocked(int type, long timeMs) {
- if (mWifiControllerTime[type] == null) {
- mWifiControllerTime[type] = new LongSamplingCounter(mOnBatteryTimeBase);
- }
- mWifiControllerTime[type].addCountLocked(timeMs);
+ @Override
+ public ControllerActivityCounter getWifiControllerActivity() {
+ return mWifiControllerActivity;
}
- public void noteBluetoothControllerActivityLocked(int type, long timeMs) {
- if (mBluetoothControllerTime[type] == null) {
- mBluetoothControllerTime[type] = new LongSamplingCounter(mOnBatteryTimeBase);
+ @Override
+ public ControllerActivityCounter getBluetoothControllerActivity() {
+ return mBluetoothControllerActivity;
+ }
+
+ @Override
+ public ControllerActivityCounter getModemControllerActivity() {
+ return mModemControllerActivity;
+ }
+
+ public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
+ if (mWifiControllerActivity == null) {
+ mWifiControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ NUM_BT_TX_LEVELS);
}
- mBluetoothControllerTime[type].addCountLocked(timeMs);
+ return mWifiControllerActivity;
+ }
+
+ public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
+ if (mBluetoothControllerActivity == null) {
+ mBluetoothControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ NUM_BT_TX_LEVELS);
+ }
+ return mBluetoothControllerActivity;
+ }
+
+ public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
+ if (mModemControllerActivity == null) {
+ mModemControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ ModemActivityInfo.TX_POWER_LEVELS);
+ }
+ return mModemControllerActivity;
}
public StopwatchTimer createAudioTurnedOnTimerLocked() {
@@ -5083,24 +5278,6 @@
return 0;
}
- @Override
- public long getWifiControllerActivity(int type, int which) {
- if (type >= 0 && type < NUM_CONTROLLER_ACTIVITY_TYPES &&
- mWifiControllerTime[type] != null) {
- return mWifiControllerTime[type].getCountLocked(which);
- }
- return 0;
- }
-
- @Override
- public long getBluetoothControllerActivity(int type, int which) {
- if (type >= 0 && type < NUM_CONTROLLER_ACTIVITY_TYPES &&
- mBluetoothControllerTime[type] != null) {
- return mBluetoothControllerTime[type].getCountLocked(which);
- }
- return 0;
- }
-
void initNetworkActivityLocked() {
mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
@@ -5190,14 +5367,16 @@
mMobileRadioActiveCount.reset(false);
}
- for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- if (mWifiControllerTime[i] != null) {
- mWifiControllerTime[i].reset(false);
- }
+ if (mWifiControllerActivity != null) {
+ mWifiControllerActivity.reset(false);
+ }
- if (mBluetoothControllerTime[i] != null) {
- mBluetoothControllerTime[i].reset(false);
- }
+ if (mBluetoothActivity != null) {
+ mBluetoothActivity.reset(false);
+ }
+
+ if (mModemActivity != null) {
+ mModemActivity.reset(false);
}
mUserCpuTime.reset(false);
@@ -5342,15 +5521,18 @@
}
}
- for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- if (mWifiControllerTime[i] != null) {
- mWifiControllerTime[i].detach();
- }
-
- if (mBluetoothControllerTime[i] != null) {
- mBluetoothControllerTime[i].detach();
- }
+ if (mWifiControllerActivity != null) {
+ mWifiControllerActivity.detach();
}
+
+ if (mBluetoothControllerActivity != null) {
+ mBluetoothControllerActivity.detach();
+ }
+
+ if (mModemControllerActivity != null) {
+ mModemControllerActivity.detach();
+ }
+
mPids.clear();
mUserCpuTime.detach();
@@ -5521,22 +5703,25 @@
out.writeInt(0);
}
- for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- if (mWifiControllerTime[i] != null) {
- out.writeInt(1);
- mWifiControllerTime[i].writeToParcel(out);
- } else {
- out.writeInt(0);
- }
+ if (mWifiControllerActivity != null) {
+ out.writeInt(1);
+ mWifiControllerActivity.writeToParcel(out, 0);
+ } else {
+ out.writeInt(0);
}
- for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- if (mBluetoothControllerTime[i] != null) {
- out.writeInt(1);
- mBluetoothControllerTime[i].writeToParcel(out);
- } else {
- out.writeInt(0);
- }
+ if (mBluetoothControllerActivity != null) {
+ out.writeInt(1);
+ mBluetoothControllerActivity.writeToParcel(out, 0);
+ } else {
+ out.writeInt(0);
+ }
+
+ if (mModemControllerActivity != null) {
+ out.writeInt(1);
+ mModemControllerActivity.writeToParcel(out, 0);
+ } else {
+ out.writeInt(0);
}
mUserCpuTime.writeToParcel(out);
@@ -5727,20 +5912,25 @@
mNetworkPacketActivityCounters = null;
}
- for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- if (in.readInt() != 0) {
- mWifiControllerTime[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
- } else {
- mWifiControllerTime[i] = null;
- }
+ if (in.readInt() != 0) {
+ mWifiControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ NUM_WIFI_TX_LEVELS, in);
+ } else {
+ mWifiControllerActivity = null;
}
- for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- if (in.readInt() != 0) {
- mBluetoothControllerTime[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
- } else {
- mBluetoothControllerTime[i] = null;
- }
+ if (in.readInt() != 0) {
+ mBluetoothControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ NUM_BT_TX_LEVELS, in);
+ } else {
+ mBluetoothControllerActivity = null;
+ }
+
+ if (in.readInt() != 0) {
+ mModemControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ ModemActivityInfo.TX_POWER_LEVELS, in);
+ } else {
+ mModemControllerActivity = null;
}
mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
@@ -6916,10 +7106,12 @@
mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
}
- for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- mBluetoothActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
- mWifiActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
- }
+ mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
+ mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ NUM_BT_TX_LEVELS);
+ mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ ModemActivityInfo.TX_POWER_LEVELS);
+
mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase);
mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase);
mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
@@ -7567,10 +7759,9 @@
for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
mWifiSignalStrengthsTimer[i].reset(false);
}
- for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- mBluetoothActivityCounters[i].reset(false);
- mWifiActivityCounters[i].reset(false);
- }
+ mWifiActivity.reset(false);
+ mBluetoothActivity.reset(false);
+ mModemActivity.reset(false);
mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
for (int i=0; i<mUidStats.size(); i++) {
@@ -7781,7 +7972,7 @@
}
if (info != null) {
- mHasWifiEnergyReporting = true;
+ mHasWifiReporting = true;
// Measured in mAms
final long txTimeMs = info.getControllerTxTimeMillis();
@@ -7861,8 +8052,11 @@
+ scanRxTimeSinceMarkMs + " ms Tx:"
+ scanTxTimeSinceMarkMs + " ms)");
}
- uid.noteWifiControllerActivityLocked(CONTROLLER_RX_TIME, scanRxTimeSinceMarkMs);
- uid.noteWifiControllerActivityLocked(CONTROLLER_TX_TIME, scanTxTimeSinceMarkMs);
+
+ ControllerActivityCounterImpl activityCounter =
+ uid.getOrCreateWifiControllerActivityLocked();
+ activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
+ activityCounter.getTxTimeCounters()[0].addCountLocked(scanTxTimeSinceMarkMs);
leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
}
@@ -7881,7 +8075,8 @@
Slog.d(TAG, " IdleTime for UID " + uid.getUid() + ": "
+ myIdleTimeMs + " ms");
}
- uid.noteWifiControllerActivityLocked(CONTROLLER_IDLE_TIME, myIdleTimeMs);
+ uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
+ .addCountLocked(myIdleTimeMs);
}
}
@@ -7898,7 +8093,8 @@
if (DEBUG_ENERGY) {
Slog.d(TAG, " TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
}
- uid.noteWifiControllerActivityLocked(CONTROLLER_TX_TIME, myTxTimeMs);
+ uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
+ .addCountLocked(myTxTimeMs);
}
// Distribute the remaining Rx power appropriately between all apps that received
@@ -7909,25 +8105,23 @@
if (DEBUG_ENERGY) {
Slog.d(TAG, " RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
}
- uid.noteWifiControllerActivityLocked(CONTROLLER_RX_TIME, myRxTimeMs);
+ uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
+ .addCountLocked(myRxTimeMs);
}
// Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
// Update WiFi controller stats.
- mWifiActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
- info.getControllerRxTimeMillis());
- mWifiActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
- info.getControllerTxTimeMillis());
- mWifiActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
- info.getControllerIdleTimeMillis());
+ mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
+ mWifiActivity.getTxTimeCounters()[0].addCountLocked(info.getControllerTxTimeMillis());
+ mWifiActivity.getIdleTimeCounter().addCountLocked(info.getControllerIdleTimeMillis());
// POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
final double opVolt = mPowerProfile.getAveragePower(
PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
if (opVolt != 0) {
// We store the power drain as mAms.
- mWifiActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked(
+ mWifiActivity.getPowerCounter().addCountLocked(
(long)(info.getControllerEnergyUsed() / opVolt));
}
}
@@ -7936,9 +8130,10 @@
/**
* Distribute Cell radio energy info and network traffic to apps.
*/
- public void updateMobileRadioStateLocked(final long elapsedRealtimeMs) {
+ public void updateMobileRadioStateLocked(final long elapsedRealtimeMs,
+ final ModemActivityInfo activityInfo) {
if (DEBUG_ENERGY) {
- Slog.d(TAG, "Updating mobile radio stats");
+ Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
}
NetworkStats delta = null;
@@ -7951,60 +8146,112 @@
return;
}
- if (delta == null || !mOnBatteryInternal) {
+ if (!mOnBatteryInternal) {
return;
}
long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000);
mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
- long totalPackets = delta.getTotalPackets();
- final int size = delta.size();
- for (int i = 0; i < size; i++) {
- final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
+ long totalRxPackets = 0;
+ long totalTxPackets = 0;
+ if (delta != null) {
+ final int size = delta.size();
+ for (int i = 0; i < size; i++) {
+ final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
+ if (entry.rxPackets == 0 || entry.txPackets == 0) {
+ continue;
+ }
- if (entry.rxBytes == 0 || entry.txBytes == 0) {
- continue;
+ if (DEBUG_ENERGY) {
+ Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
+ + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
+ + " txPackets=" + entry.txPackets);
+ }
+
+ totalRxPackets += entry.rxPackets;
+ totalTxPackets += entry.txPackets;
+
+ final Uid u = getUidStatsLocked(mapUid(entry.uid));
+ u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, entry.rxPackets);
+ u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, entry.txPackets);
+
+ mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
+ entry.rxBytes);
+ mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
+ entry.txBytes);
+ mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
+ entry.rxPackets);
+ mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
+ entry.txPackets);
}
- if (DEBUG_ENERGY) {
- Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
- + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
- + " txPackets=" + entry.txPackets);
- }
+ // Now distribute proportional blame to the apps that did networking.
+ long totalPackets = totalRxPackets + totalTxPackets;
+ if (totalPackets > 0) {
+ for (int i = 0; i < size; i++) {
+ final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
+ if (entry.rxPackets == 0 && entry.txPackets == 0) {
+ continue;
+ }
- final Uid u = getUidStatsLocked(mapUid(entry.uid));
- u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
- entry.rxPackets);
- u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
- entry.txPackets);
+ final Uid u = getUidStatsLocked(mapUid(entry.uid));
+
+ // Distribute total radio active time in to this app.
+ final long appPackets = entry.rxPackets + entry.txPackets;
+ final long appRadioTime = (radioTime * appPackets) / totalPackets;
+ u.noteMobileRadioActiveTimeLocked(appRadioTime);
+
+ // Remove this app from the totals, so that we don't lose any time
+ // due to rounding.
+ radioTime -= appRadioTime;
+ totalPackets -= appPackets;
+
+ if (activityInfo != null) {
+ ControllerActivityCounterImpl activityCounter =
+ u.getOrCreateModemControllerActivityLocked();
+ if (entry.rxPackets != 0) {
+ final long rxMs = (entry.rxPackets * activityInfo.getRxTimeMillis())
+ / totalRxPackets;
+ activityCounter.getRxTimeCounter().addCountLocked(rxMs);
+ }
+
+ if (entry.txPackets != 0) {
+ for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
+ long txMs = entry.txPackets * activityInfo.getTxTimeMillis()[lvl];
+ txMs /= totalTxPackets;
+ activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
+ }
+ }
+ }
+ }
+ }
if (radioTime > 0) {
- // Distribute total radio active time in to this app.
- long appPackets = entry.rxPackets + entry.txPackets;
- long appRadioTime = (radioTime*appPackets)/totalPackets;
- u.noteMobileRadioActiveTimeLocked(appRadioTime);
- // Remove this app from the totals, so that we don't lose any time
- // due to rounding.
- radioTime -= appRadioTime;
- totalPackets -= appPackets;
+ // Whoops, there is some radio time we can't blame on an app!
+ mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
+ mMobileRadioActiveUnknownCount.addCountLocked(1);
}
-
- mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
- entry.rxBytes);
- mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
- entry.txBytes);
- mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
- entry.rxPackets);
- mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
- entry.txPackets);
}
- if (radioTime > 0) {
- // Whoops, there is some radio time we can't blame on an app!
- mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
- mMobileRadioActiveUnknownCount.addCountLocked(1);
+ if (activityInfo != null) {
+ mHasModemReporting = true;
+ mModemActivity.getIdleTimeCounter().addCountLocked(activityInfo.getIdleTimeMillis());
+ mModemActivity.getRxTimeCounter().addCountLocked(activityInfo.getRxTimeMillis());
+ for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
+ mModemActivity.getTxTimeCounters()[lvl]
+ .addCountLocked(activityInfo.getTxTimeMillis()[lvl]);
+ }
+
+ // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
+ final double opVolt = mPowerProfile.getAveragePower(
+ PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
+ if (opVolt != 0) {
+ // We store the power drain as mAms.
+ mModemActivity.getPowerCounter().addCountLocked(
+ (long) (activityInfo.getEnergyUsed() / opVolt));
+ }
}
}
@@ -8018,12 +8265,12 @@
}
if (info != null && mOnBatteryInternal) {
- mHasBluetoothEnergyReporting = true;
- mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
+ mHasBluetoothReporting = true;
+ mBluetoothActivity.getRxTimeCounter().addCountLocked(
info.getControllerRxTimeMillis());
- mBluetoothActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
+ mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(
info.getControllerTxTimeMillis());
- mBluetoothActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
+ mBluetoothActivity.getIdleTimeCounter().addCountLocked(
info.getControllerIdleTimeMillis());
// POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
@@ -8031,7 +8278,7 @@
PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
if (opVolt != 0) {
// We store the power drain as mAms.
- mBluetoothActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked(
+ mBluetoothActivity.getPowerCounter().addCountLocked(
(long) (info.getControllerEnergyUsed() / opVolt));
}
@@ -9337,12 +9584,12 @@
for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
}
- for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- mBluetoothActivityCounters[i].readSummaryFromParcelLocked(in);
- }
- for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- mWifiActivityCounters[i].readSummaryFromParcelLocked(in);
- }
+ mWifiActivity.readSummaryFromParcel(in);
+ mBluetoothActivity.readSummaryFromParcel(in);
+ mModemActivity.readSummaryFromParcel(in);
+ mHasWifiReporting = in.readInt() != 0;
+ mHasBluetoothReporting = in.readInt() != 0;
+ mHasModemReporting = in.readInt() != 0;
mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
mFlashlightOnNesting = 0;
@@ -9671,12 +9918,13 @@
for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
}
- for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- mBluetoothActivityCounters[i].writeSummaryFromParcelLocked(out);
- }
- for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- mWifiActivityCounters[i].writeSummaryFromParcelLocked(out);
- }
+ mWifiActivity.writeSummaryToParcel(out);
+ mBluetoothActivity.writeSummaryToParcel(out);
+ mModemActivity.writeSummaryToParcel(out);
+ out.writeInt(mHasWifiReporting ? 1 : 0);
+ out.writeInt(mHasBluetoothReporting ? 1 : 0);
+ out.writeInt(mHasModemReporting ? 1 : 0);
+
out.writeInt(mNumConnectivityChange);
mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
@@ -10019,15 +10267,17 @@
mWifiSignalStrengthsTimer[i] = new StopwatchTimer(null, -800-i,
null, mOnBatteryTimeBase, in);
}
- for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- mBluetoothActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
- }
- for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- mWifiActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
- }
- mHasWifiEnergyReporting = in.readInt() != 0;
- mHasBluetoothEnergyReporting = in.readInt() != 0;
+ mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ NUM_WIFI_TX_LEVELS, in);
+ mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ NUM_BT_TX_LEVELS, in);
+ mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ ModemActivityInfo.TX_POWER_LEVELS, in);
+ mHasWifiReporting = in.readInt() != 0;
+ mHasBluetoothReporting = in.readInt() != 0;
+ mHasModemReporting = in.readInt() != 0;
+
mNumConnectivityChange = in.readInt();
mLoadedNumConnectivityChange = in.readInt();
mUnpluggedNumConnectivityChange = in.readInt();
@@ -10174,14 +10424,13 @@
for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
}
- for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- mBluetoothActivityCounters[i].writeToParcel(out);
- }
- for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
- mWifiActivityCounters[i].writeToParcel(out);
- }
- out.writeInt(mHasWifiEnergyReporting ? 1 : 0);
- out.writeInt(mHasBluetoothEnergyReporting ? 1 : 0);
+ mWifiActivity.writeToParcel(out, 0);
+ mBluetoothActivity.writeToParcel(out, 0);
+ mModemActivity.writeToParcel(out, 0);
+ out.writeInt(mHasWifiReporting ? 1 : 0);
+ out.writeInt(mHasBluetoothReporting ? 1 : 0);
+ out.writeInt(mHasModemReporting ? 1 : 0);
+
out.writeInt(mNumConnectivityChange);
out.writeInt(mLoadedNumConnectivityChange);
out.writeInt(mUnpluggedNumConnectivityChange);
diff --git a/core/java/com/android/internal/os/BluetoothPowerCalculator.java b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
index 1f59672..531d1fa 100644
--- a/core/java/com/android/internal/os/BluetoothPowerCalculator.java
+++ b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
@@ -40,15 +40,15 @@
@Override
public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
long rawUptimeUs, int statsType) {
- final long idleTimeMs = stats.getBluetoothControllerActivity(
- BatteryStats.CONTROLLER_IDLE_TIME, statsType);
- final long txTimeMs = stats.getBluetoothControllerActivity(
- BatteryStats.CONTROLLER_TX_TIME, statsType);
- final long rxTimeMs = stats.getBluetoothControllerActivity(
- BatteryStats.CONTROLLER_RX_TIME, statsType);
+ final BatteryStats.ControllerActivityCounter counter =
+ stats.getBluetoothControllerActivity();
+
+ final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
+ final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
+ final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;
- double powerMah = stats.getBluetoothControllerActivity(
- BatteryStats.CONTROLLER_POWER_DRAIN, statsType) / (double)(1000*60*60);
+ double powerMah = counter.getPowerCounter().getCountLocked(statsType)
+ / (double)(1000*60*60);
if (powerMah == 0) {
// Some devices do not report the power, so calculate it.
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index aaa9f73..14ebe22 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -93,6 +93,12 @@
public static final String POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE =
"bluetooth.controller.voltage";
+ public static final String POWER_MODEM_CONTROLLER_IDLE = "modem.controller.idle";
+ public static final String POWER_MODEM_CONTROLLER_RX = "modem.controller.rx";
+ public static final String POWER_MODEM_CONTROLLER_TX = "modem.controller.tx";
+ public static final String POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE =
+ "modem.controller.voltage";
+
/**
* Power consumption when GPS is on.
*/
@@ -100,17 +106,23 @@
/**
* Power consumption when Bluetooth driver is on.
+ * @deprecated
*/
+ @Deprecated
public static final String POWER_BLUETOOTH_ON = "bluetooth.on";
/**
* Power consumption when Bluetooth driver is transmitting/receiving.
+ * @deprecated
*/
+ @Deprecated
public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active";
/**
* Power consumption when Bluetooth driver gets an AT command.
+ * @deprecated
*/
+ @Deprecated
public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at";
diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java
index 146c0f8..2a27f70 100644
--- a/core/java/com/android/internal/os/WifiPowerCalculator.java
+++ b/core/java/com/android/internal/os/WifiPowerCalculator.java
@@ -39,10 +39,14 @@
@Override
public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
long rawUptimeUs, int statsType) {
- final long idleTime = u.getWifiControllerActivity(BatteryStats.CONTROLLER_IDLE_TIME,
- statsType);
- final long txTime = u.getWifiControllerActivity(BatteryStats.CONTROLLER_TX_TIME, statsType);
- final long rxTime = u.getWifiControllerActivity(BatteryStats.CONTROLLER_RX_TIME, statsType);
+ final BatteryStats.ControllerActivityCounter counter = u.getWifiControllerActivity();
+ if (counter == null) {
+ return;
+ }
+
+ final long idleTime = counter.getIdleTimeCounter().getCountLocked(statsType);
+ final long txTime = counter.getTxTimeCounters()[0].getCountLocked(statsType);
+ final long rxTime = counter.getRxTimeCounter().getCountLocked(statsType);
app.wifiRunningTimeMs = idleTime + rxTime + txTime;
app.wifiPowerMah =
((idleTime * mIdleCurrentMa) + (txTime * mTxCurrentMa) + (rxTime * mRxCurrentMa))
@@ -67,16 +71,15 @@
@Override
public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
long rawUptimeUs, int statsType) {
- final long idleTimeMs = stats.getWifiControllerActivity(BatteryStats.CONTROLLER_IDLE_TIME,
- statsType);
- final long rxTimeMs = stats.getWifiControllerActivity(BatteryStats.CONTROLLER_RX_TIME,
- statsType);
- final long txTimeMs = stats.getWifiControllerActivity(BatteryStats.CONTROLLER_TX_TIME,
- statsType);
+ final BatteryStats.ControllerActivityCounter counter = stats.getWifiControllerActivity();
+
+ final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
+ final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
+ final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
app.wifiRunningTimeMs = idleTimeMs + rxTimeMs + txTimeMs;
- double powerDrainMah = stats.getWifiControllerActivity(BatteryStats.CONTROLLER_POWER_DRAIN,
- statsType) / (double)(1000*60*60);
+ double powerDrainMah = counter.getPowerCounter().getCountLocked(statsType)
+ / (double)(1000*60*60);
if (powerDrainMah == 0) {
// Some controllers do not report power drain, so we can calculate it here.
powerDrainMah = ((idleTimeMs * mIdleCurrentMa) + (txTimeMs * mTxCurrentMa)
diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index a572486..a38139f 100644
--- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -139,7 +139,12 @@
}
public SnapTarget getClosestDismissTarget(int position) {
- if (position - mDismissStartTarget.position < mDismissEndTarget.position - position) {
+ if (position < mFirstSplitTarget.position) {
+ return mDismissStartTarget;
+ } else if (position > mLastSplitTarget.position) {
+ return mDismissEndTarget;
+ } else if (position - mDismissStartTarget.position
+ < mDismissEndTarget.position - position) {
return mDismissStartTarget;
} else {
return mDismissEndTarget;
diff --git a/core/java/com/android/internal/policy/DockedDividerUtils.java b/core/java/com/android/internal/policy/DockedDividerUtils.java
index f7f5f15..00c65bd 100644
--- a/core/java/com/android/internal/policy/DockedDividerUtils.java
+++ b/core/java/com/android/internal/policy/DockedDividerUtils.java
@@ -48,17 +48,21 @@
outRect.top = position + dividerSize;
break;
}
- if (outRect.left >= outRect.right) {
- outRect.left = outRect.right - 1;
+ sanitizeStackBounds(outRect);
+ }
+
+ public static void sanitizeStackBounds(Rect bounds) {
+ if (bounds.left >= bounds.right) {
+ bounds.left = bounds.right - 1;
}
- if (outRect.top >= outRect.bottom) {
- outRect.top = outRect.bottom - 1;
+ if (bounds.top >= bounds.bottom) {
+ bounds.top = bounds.bottom - 1;
}
- if (outRect.right <= outRect.left) {
- outRect.right = outRect.left + 1;
+ if (bounds.right <= bounds.left) {
+ bounds.right = bounds.left + 1;
}
- if (outRect.bottom <= outRect.top) {
- outRect.bottom = outRect.top + 1;
+ if (bounds.bottom <= bounds.top) {
+ bounds.bottom = bounds.top + 1;
}
}
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 7dfc15d..bcc310f 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -38,7 +38,7 @@
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets,
Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig,
- Rect backDropFrame) {
+ Rect backDropFrame, boolean forceLayout) {
if (reportDraw) {
try {
mSession.finishDrawing(this);
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 2e5cda0..a582492 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -23,6 +23,7 @@
#include <utils/Log.h>
#include <utils/Looper.h>
+#include <utils/Vector.h>
#include <gui/Sensor.h>
#include <gui/SensorManager.h>
@@ -45,6 +46,7 @@
struct SensorOffsets
{
+ jclass clazz;
jfieldID name;
jfieldID vendor;
jfieldID version;
@@ -60,8 +62,13 @@
jfieldID maxDelay;
jfieldID flags;
jmethodID setType;
+ jmethodID init;
} gSensorOffsets;
+struct ListOffsets {
+ jclass clazz;
+ jmethodID add;
+} gListOffsets;
/*
* The method below are not thread-safe and not intended to be
@@ -70,8 +77,10 @@
static void
nativeClassInit (JNIEnv *_env, jclass _this)
{
- jclass sensorClass = _env->FindClass("android/hardware/Sensor");
+ //android.hardware.Sensor
SensorOffsets& sensorOffsets = gSensorOffsets;
+ jclass sensorClass = (jclass) _env->NewGlobalRef(_env->FindClass("android/hardware/Sensor"));
+ sensorOffsets.clazz = sensorClass;
sensorOffsets.name = _env->GetFieldID(sensorClass, "mName", "Ljava/lang/String;");
sensorOffsets.vendor = _env->GetFieldID(sensorClass, "mVendor", "Ljava/lang/String;");
sensorOffsets.version = _env->GetFieldID(sensorClass, "mVersion", "I");
@@ -88,7 +97,15 @@
"Ljava/lang/String;");
sensorOffsets.maxDelay = _env->GetFieldID(sensorClass, "mMaxDelay", "I");
sensorOffsets.flags = _env->GetFieldID(sensorClass, "mFlags", "I");
+
sensorOffsets.setType = _env->GetMethodID(sensorClass, "setType", "(I)Z");
+ sensorOffsets.init = _env->GetMethodID(sensorClass, "<init>", "()V");
+
+ // java.util.List;
+ ListOffsets& listOffsets = gListOffsets;
+ jclass listClass = (jclass) _env->NewGlobalRef(_env->FindClass("java/util/List"));
+ listOffsets.clazz = listClass;
+ listOffsets.add = _env->GetMethodID(listClass, "add", "(Ljava/lang/Object;)Z");
}
/**
@@ -141,6 +158,46 @@
return (jlong) &SensorManager::getInstanceForPackage(String16(opPackageNameUtf.c_str()));
}
+static jobject
+translateNativeSensorToJavaSensor(JNIEnv *env, jobject sensor, const Sensor& nativeSensor) {
+ const SensorOffsets& sensorOffsets(gSensorOffsets);
+
+ if (sensor == NULL) {
+ // Sensor sensor = new Sensor();
+ sensor = env->NewObject(sensorOffsets.clazz, sensorOffsets.init, "");
+ }
+
+ if (sensor != NULL) {
+ jstring name = env->NewStringUTF(nativeSensor.getName().string());
+ jstring vendor = env->NewStringUTF(nativeSensor.getVendor().string());
+ jstring requiredPermission =
+ env->NewStringUTF(nativeSensor.getRequiredPermission().string());
+
+ env->SetObjectField(sensor, sensorOffsets.name, name);
+ env->SetObjectField(sensor, sensorOffsets.vendor, vendor);
+ env->SetIntField(sensor, sensorOffsets.version, nativeSensor.getVersion());
+ env->SetIntField(sensor, sensorOffsets.handle, nativeSensor.getHandle());
+ env->SetFloatField(sensor, sensorOffsets.range, nativeSensor.getMaxValue());
+ env->SetFloatField(sensor, sensorOffsets.resolution, nativeSensor.getResolution());
+ env->SetFloatField(sensor, sensorOffsets.power, nativeSensor.getPowerUsage());
+ env->SetIntField(sensor, sensorOffsets.minDelay, nativeSensor.getMinDelay());
+ env->SetIntField(sensor, sensorOffsets.fifoReservedEventCount,
+ nativeSensor.getFifoReservedEventCount());
+ env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount,
+ nativeSensor.getFifoMaxEventCount());
+ env->SetObjectField(sensor, sensorOffsets.requiredPermission,
+ requiredPermission);
+ env->SetIntField(sensor, sensorOffsets.maxDelay, nativeSensor.getMaxDelay());
+ env->SetIntField(sensor, sensorOffsets.flags, nativeSensor.getFlags());
+ if (env->CallBooleanMethod(sensor, sensorOffsets.setType, nativeSensor.getType())
+ == JNI_FALSE) {
+ jstring stringType = getInternedString(env, &nativeSensor.getStringType());
+ env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
+ }
+ }
+ return sensor;
+}
+
static jboolean
nativeGetSensorAtIndex(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensor, jint index)
{
@@ -180,6 +237,24 @@
return true;
}
+static void
+nativeGetDynamicSensors(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensorList) {
+
+ SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
+ const ListOffsets& listOffsets(gListOffsets);
+
+ Vector<Sensor> nativeList;
+
+ mgr->getDynamicSensorList(nativeList);
+
+ ALOGI("DYNS native SensorManager.getDynamicSensorList return %d sensors", nativeList.size());
+ for (size_t i = 0; i < nativeList.size(); ++i) {
+ jobject sensor = translateNativeSensorToJavaSensor(env, NULL, nativeList[i]);
+ // add to list
+ env->CallBooleanMethod(sensorList, listOffsets.add, sensor);
+ }
+}
+
static jboolean nativeIsDataInjectionEnabled(JNIEnv *_env, jclass _this, jlong sensorManager) {
SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
return mgr->isDataInjectionEnabled();
@@ -235,6 +310,11 @@
// step-counter returns a uint64, but the java API only deals with floats
float value = float(buffer[i].u64.step_counter);
env->SetFloatArrayRegion(mScratch, 0, 1, &value);
+ } else if (buffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META) {
+ float value[2];
+ value[0] = buffer[i].dynamic_sensor_meta.connected ? 1.f: 0.f;
+ value[1] = float(buffer[i].dynamic_sensor_meta.handle);
+ env->SetFloatArrayRegion(mScratch, 0, 2, value);
} else {
env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);
}
@@ -355,6 +435,10 @@
"(JLandroid/hardware/Sensor;I)Z",
(void*)nativeGetSensorAtIndex },
+ {"nativeGetDynamicSensors",
+ "(JLjava/util/List;)V",
+ (void*)nativeGetDynamicSensors },
+
{"nativeIsDataInjectionEnabled",
"(J)Z",
(void*)nativeIsDataInjectionEnabled},
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 56c3fc8..1c3db10 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -420,6 +420,8 @@
<protected-broadcast android:name="android.permission.GET_APP_GRANTED_URI_PERMISSIONS" />
<protected-broadcast android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS" />
+ <protected-broadcast android:name="android.intent.action.DYNAMIC_SENSOR_CHANGED" />
+
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
<!-- ====================================================================== -->
@@ -1407,6 +1409,13 @@
<permission android:name="android.permission.BIND_INCALL_SERVICE"
android:protectionLevel="signature|privileged" />
+ <!-- Must be required by a {@link android.telecom.CallScreeningService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature|privileged
+ -->
+ <permission android:name="android.permission.BIND_SCREENING_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
<!-- Must be required by a {@link android.telecom.ConnectionService},
to ensure that only the system can bind to it.
@deprecated {@link android.telecom.ConnectionService}s should require
@@ -2860,6 +2869,12 @@
<permission android:name="android.permission.RECEIVE_MEDIA_RESOURCE_USAGE"
android:protectionLevel="signature|privileged" />
+ <!-- Must be required by system/priv apps when accessing the sound trigger
+ APIs given by {@link SoundTriggerManager}.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.MANAGE_SOUND_TRIGGER"
+ android:protectionLevel="signature|privileged" />
+
<application android:process="system"
android:persistent="true"
android:hasCode="false"
diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml
index ddd0ca2..76b5fe1 100644
--- a/core/res/res/xml/power_profile.xml
+++ b/core/res/res/xml/power_profile.xml
@@ -39,15 +39,27 @@
<item name="dsp.video">0.1</item> <!-- ~50mA -->
<item name="camera.flashlight">0.1</item> <!-- Avg. power for camera flash, ~160mA -->
<item name="camera.avg">0.1</item> <!-- Avg. power use of camera in standard usecases, ~550mA -->
+ <item name="gps.on">0.1</item> <!-- ~50mA -->
+
+ <!-- Radio related values. For modems without energy reporting support in firmware, use
+ radio.active, radio.scanning, and radio.on. -->
<item name="radio.active">0.1</item> <!-- ~200mA -->
<item name="radio.scanning">0.1</item> <!-- cellular radio scanning for signal, ~10mA -->
- <item name="gps.on">0.1</item> <!-- ~50mA -->
<!-- Current consumed by the radio at different signal strengths, when paging -->
<array name="radio.on"> <!-- Strength 0 to BINS-1 -->
<value>0.2</value> <!-- ~2mA -->
<value>0.1</value> <!-- ~1mA -->
</array>
+
+ <!-- Radio related values. For modems WITH energy reporting support in firmware, use
+ modem.controller.idle, modem.controller.tx, modem.controller.rx, modem.controller.voltage.
+ -->
+ <item name="modem.controller.idle">0</item>
+ <item name="modem.controller.rx">0</item>
+ <item name="modem.controller.tx">0</item>
+ <item name="modem.controller.voltage">0</item>
+
<!-- A list of heterogeneous CPU clusters, where the value for each cluster represents the
number of CPU cores for that cluster.
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index efae628..c194711 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -224,7 +224,6 @@
public final static int FLAG_BYPASS_MUTE = 0x1 << 7;
/**
- * @hide
* Flag requesting a low latency path.
* When using this flag, the sample rate must match the native sample rate
* of the device. Effects processing is also unavailable.
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index bde3d19..000a56d 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -251,6 +251,10 @@
* @hide
* */
public static final int ENCODING_AAC_HE_V2 = 12;
+ /** Audio data format: compressed audio wrapped in PCM for HDMI
+ * or S/PDIF passthrough.
+ */
+ public static final int ENCODING_IEC61937 = 13;
/** Invalid audio channel configuration */
/** @deprecated Use {@link #CHANNEL_INVALID} instead. */
@@ -418,6 +422,7 @@
case ENCODING_PCM_8BIT:
return 1;
case ENCODING_PCM_16BIT:
+ case ENCODING_IEC61937:
case ENCODING_DEFAULT:
return 2;
case ENCODING_PCM_FLOAT:
@@ -443,6 +448,7 @@
case ENCODING_AAC_LC:
case ENCODING_AAC_HE_V1:
case ENCODING_AAC_HE_V2:
+ case ENCODING_IEC61937:
return true;
default:
return false;
@@ -460,6 +466,7 @@
case ENCODING_E_AC3:
case ENCODING_DTS:
case ENCODING_DTS_HD:
+ case ENCODING_IEC61937:
return true;
default:
return false;
@@ -483,6 +490,7 @@
case ENCODING_AAC_LC:
case ENCODING_AAC_HE_V1:
case ENCODING_AAC_HE_V2:
+ case ENCODING_IEC61937: // wrapped in PCM but compressed
return false;
case ENCODING_INVALID:
default:
@@ -490,6 +498,30 @@
}
}
+ /** @hide */
+ public static boolean isEncodingLinearFrames(int audioFormat)
+ {
+ switch (audioFormat) {
+ case ENCODING_PCM_8BIT:
+ case ENCODING_PCM_16BIT:
+ case ENCODING_PCM_FLOAT:
+ case ENCODING_IEC61937: // same size as stereo PCM
+ case ENCODING_DEFAULT:
+ return true;
+ case ENCODING_AC3:
+ case ENCODING_E_AC3:
+ case ENCODING_DTS:
+ case ENCODING_DTS_HD:
+ case ENCODING_MP3:
+ case ENCODING_AAC_LC:
+ case ENCODING_AAC_HE_V1:
+ case ENCODING_AAC_HE_V2:
+ return false;
+ case ENCODING_INVALID:
+ default:
+ throw new IllegalArgumentException("Bad audio format " + audioFormat);
+ }
+ }
/**
* Returns an array of public encoding values extracted from an array of
* encoding values.
@@ -715,6 +747,7 @@
case ENCODING_E_AC3:
case ENCODING_DTS:
case ENCODING_DTS_HD:
+ case ENCODING_IEC61937:
mEncoding = encoding;
break;
case ENCODING_INVALID:
@@ -859,7 +892,8 @@
ENCODING_AC3,
ENCODING_E_AC3,
ENCODING_DTS,
- ENCODING_DTS_HD
+ ENCODING_DTS_HD,
+ ENCODING_IEC61937
})
@Retention(RetentionPolicy.SOURCE)
public @interface Encoding {}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 4319840..3007d86 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1100,7 +1100,6 @@
* @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
* {@link #ERROR_INVALID_OPERATION}
* @throws IllegalStateException
- * @hide
*/
public int setBufferSizeInFrames(int bufferSizeInFrames) {
if (mDataLoadMode == MODE_STATIC || mState == STATE_UNINITIALIZED) {
@@ -1130,7 +1129,6 @@
* {@link AudioManager#PROPERTY_OUTPUT_FRAMES_PER_BUFFER}.
* @return maximum size in frames of the <code>AudioTrack</code> buffer.
* @throws IllegalStateException
- * @hide
*/
public int getBufferCapacityInFrames() {
return native_get_buffer_capacity_frames();
@@ -1204,7 +1202,6 @@
* This is a continuously advancing counter. It can wrap around to zero
* if there are too many underruns. If there were, for example, 68 underruns per
* second then the counter would wrap in 2 years.
- * @hide
*/
public int getUnderrunCount() {
return native_get_underrun_count();
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 0fba992..d9690f0 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -460,6 +460,11 @@
public static final String FEATURE_TunneledPlayback = "tunneled-playback";
/**
+ * <b>video encoder only</b>: codec supports intra refresh.
+ */
+ public static final String FEATURE_IntraRefresh = "intra-refresh";
+
+ /**
* Query codec feature capabilities.
* <p>
* These features are supported to be used by the codec. These
@@ -486,6 +491,10 @@
new Feature(FEATURE_TunneledPlayback, (1 << 2), false),
};
+ private static final Feature[] encoderFeatures = {
+ new Feature(FEATURE_IntraRefresh, (1 << 0), false),
+ };
+
/** @hide */
public String[] validFeatures() {
Feature[] features = getValidFeatures();
@@ -500,7 +509,7 @@
if (!isEncoder()) {
return decoderFeatures;
}
- return new Feature[] {};
+ return encoderFeatures;
}
private boolean checkFeature(String name, int flags) {
@@ -1726,7 +1735,7 @@
}
private void applyLevelLimits() {
- int maxBlocksPerSecond = 0;
+ long maxBlocksPerSecond = 0;
int maxBlocks = 0;
int maxBps = 0;
int maxDPBBlocks = 0;
@@ -2052,11 +2061,11 @@
16 /* blockWidth */, 16 /* blockHeight */,
1 /* widthAlignment */, 1 /* heightAlignment */);
mFrameRateRange = Range.create(1, maxRate);
- } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8) ||
- mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) {
- maxBlocks = maxBlocksPerSecond = Integer.MAX_VALUE;
+ } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8)) {
+ maxBlocks = Integer.MAX_VALUE;
+ maxBlocksPerSecond = Integer.MAX_VALUE;
- // TODO: set to 100Mbps for now, need a number for VPX
+ // TODO: set to 100Mbps for now, need a number for VP8
maxBps = 100000000;
// profile levels are not indicative for VPx, but verify
@@ -2084,11 +2093,80 @@
errors &= ~ERROR_NONE_SUPPORTED;
}
- final int blockSize =
- mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8) ? 16 : 8;
+ final int blockSize = 16;
applyMacroBlockLimits(Short.MAX_VALUE, Short.MAX_VALUE,
maxBlocks, maxBlocksPerSecond, blockSize, blockSize,
1 /* widthAlignment */, 1 /* heightAlignment */);
+ } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+ maxBlocksPerSecond = 829440;
+ maxBlocks = 36864;
+ maxBps = 200000;
+
+ for (CodecProfileLevel profileLevel: profileLevels) {
+ long SR = 0;
+ int FS = 0;
+ int BR = 0;
+ switch (profileLevel.level) {
+ case CodecProfileLevel.VP9Level1:
+ SR = 829440; FS = 36864; BR = 200; break;
+ case CodecProfileLevel.VP9Level11:
+ SR = 2764800; FS = 73728; BR = 800; break;
+ case CodecProfileLevel.VP9Level2:
+ SR = 4608000; FS = 122880; BR = 1800; break;
+ case CodecProfileLevel.VP9Level21:
+ SR = 9216000; FS = 245760; BR = 3600; break;
+ case CodecProfileLevel.VP9Level3:
+ SR = 20736000; FS = 552960; BR = 7200; break;
+ case CodecProfileLevel.VP9Level31:
+ SR = 36864000; FS = 983040; BR = 12000; break;
+ case CodecProfileLevel.VP9Level4:
+ SR = 83558400; FS = 2228224; BR = 18000; break;
+ case CodecProfileLevel.VP9Level41:
+ SR = 160432128; FS = 2228224; BR = 30000; break;
+ case CodecProfileLevel.VP9Level5:
+ SR = 311951360; FS = 8912896; BR = 60000; break;
+ case CodecProfileLevel.VP9Level51:
+ SR = 588251136; FS = 8912896; BR = 120000; break;
+ case CodecProfileLevel.VP9Level52:
+ SR = 1176502272; FS = 8912896; BR = 180000; break;
+ case CodecProfileLevel.VP9Level6:
+ SR = 1176502272; FS = 35651584; BR = 180000; break;
+ case CodecProfileLevel.VP9Level61:
+ SR = 2353004544L; FS = 35651584; BR = 240000; break;
+ case CodecProfileLevel.VP9Level62:
+ SR = 4706009088L; FS = 35651584; BR = 480000; break;
+ default:
+ Log.w(TAG, "Unrecognized level "
+ + profileLevel.level + " for " + mime);
+ errors |= ERROR_UNRECOGNIZED;
+ }
+ switch (profileLevel.profile) {
+ case CodecProfileLevel.VP9Profile0:
+ case CodecProfileLevel.VP9Profile1:
+ case CodecProfileLevel.VP9Profile2:
+ case CodecProfileLevel.VP9Profile3:
+ break;
+ default:
+ Log.w(TAG, "Unrecognized profile "
+ + profileLevel.profile + " for " + mime);
+ errors |= ERROR_UNRECOGNIZED;
+ }
+ errors &= ~ERROR_NONE_SUPPORTED;
+ maxBlocksPerSecond = Math.max(SR, maxBlocksPerSecond);
+ maxBlocks = Math.max(FS, maxBlocks);
+ maxBps = Math.max(BR * 1000, maxBps);
+ }
+
+ final int blockSize = 8;
+ int maxLengthInBlocks = Utils.divUp(maxBlocks, blockSize);
+ maxBlocks = Utils.divUp(maxBlocks, blockSize * blockSize);
+ maxBlocksPerSecond = Utils.divUp(maxBlocksPerSecond, blockSize * blockSize);
+
+ applyMacroBlockLimits(
+ maxLengthInBlocks, maxLengthInBlocks,
+ maxBlocks, maxBlocksPerSecond,
+ blockSize, blockSize,
+ 1 /* widthAlignment */, 1 /* heightAlignment */);
} else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
maxBlocks = 36864;
maxBlocksPerSecond = maxBlocks * 15;
@@ -2531,6 +2609,28 @@
// from OMX_VIDEO_VP8PROFILETYPE
public static final int VP8ProfileMain = 0x01;
+ // from OMX_VIDEO_VP9PROFILETYPE
+ public static final int VP9Profile0 = 0x00;
+ public static final int VP9Profile1 = 0x01;
+ public static final int VP9Profile2 = 0x02;
+ public static final int VP9Profile3 = 0x03;
+
+ // from OMX_VIDEO_VP9LEVELTYPE
+ public static final int VP9Level1 = 0x0;
+ public static final int VP9Level11 = 0x1;
+ public static final int VP9Level2 = 0x2;
+ public static final int VP9Level21 = 0x4;
+ public static final int VP9Level3 = 0x8;
+ public static final int VP9Level31 = 0x10;
+ public static final int VP9Level4 = 0x20;
+ public static final int VP9Level41 = 0x40;
+ public static final int VP9Level5 = 0x80;
+ public static final int VP9Level51 = 0x100;
+ public static final int VP9Level52 = 0x200;
+ public static final int VP9Level6 = 0x400;
+ public static final int VP9Level61 = 0x800;
+ public static final int VP9Level62 = 0x1000;
+
// from OMX_VIDEO_HEVCPROFILETYPE
public static final int HEVCProfileMain = 0x01;
public static final int HEVCProfileMain10 = 0x02;
@@ -2563,17 +2663,40 @@
public static final int HEVCMainTierLevel62 = 0x1000000;
public static final int HEVCHighTierLevel62 = 0x2000000;
+ // from OMX_VIDEO_DOLBYVISIONPROFILETYPE
+ public static final int DolbyVisionProfileDvavDer = 0x1;
+ public static final int DolbyVisionProfileDvavDen = 0x2;
+ public static final int DolbyVisionProfileDvheDer = 0x3;
+ public static final int DolbyVisionProfileDvheDen = 0x4;
+ public static final int DolbyVisionProfileDvheDtr = 0x5;
+ public static final int DolbyVisionProfileDvheStn = 0x6;
+
+ // from OMX_VIDEO_DOLBYVISIONLEVELTYPE
+ public static final int DolbyVisionLevelHd24 = 0x1;
+ public static final int DolbyVisionLevelHd30 = 0x2;
+ public static final int DolbyVisionLevelFhd24 = 0x4;
+ public static final int DolbyVisionLevelFhd30 = 0x8;
+ public static final int DolbyVisionLevelFhd60 = 0x10;
+ public static final int DolbyVisionLevelUhd24 = 0x20;
+ public static final int DolbyVisionLevelUhd30 = 0x40;
+ public static final int DolbyVisionLevelUhd48 = 0x80;
+ public static final int DolbyVisionLevelUhd60 = 0x100;
+
/**
* Defined in the OpenMAX IL specs, depending on the type of media
* this can be OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263PROFILETYPE,
- * OMX_VIDEO_MPEG4PROFILETYPE or OMX_VIDEO_VP8PROFILETYPE.
+ * OMX_VIDEO_MPEG4PROFILETYPE, OMX_VIDEO_VP8PROFILETYPE or OMX_VIDEO_VP9PROFILETYPE.
*/
public int profile;
/**
* Defined in the OpenMAX IL specs, depending on the type of media
* this can be OMX_VIDEO_AVCLEVELTYPE, OMX_VIDEO_H263LEVELTYPE
- * OMX_VIDEO_MPEG4LEVELTYPE or OMX_VIDEO_VP8LEVELTYPE.
+ * OMX_VIDEO_MPEG4LEVELTYPE, OMX_VIDEO_VP8LEVELTYPE or OMX_VIDEO_VP9LEVELTYPE.
+ *
+ * Note that VP9 decoder on platforms before {@link android.os.Build.VERSION_CODES#N} may
+ * not advertise a profile level support. For those VP9 decoders, please use
+ * {@link VideoCapabilities} to determine the codec capabilities.
*/
public int level;
};
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index abdf220..d06da97 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -44,7 +44,8 @@
* for encoders, readable in the output format of decoders</b></td></tr>
* <tr><td>{@link #KEY_FRAME_RATE}</td><td>Integer or Float</td><td><b>encoder-only</b></td></tr>
* <tr><td>{@link #KEY_CAPTURE_RATE}</td><td>Integer</td><td></td></tr>
-* <tr><td>{@link #KEY_I_FRAME_INTERVAL}</td><td>Integer</td><td><b>encoder-only</b></td></tr>
+ * <tr><td>{@link #KEY_I_FRAME_INTERVAL}</td><td>Integer</td><td><b>encoder-only</b></td></tr>
+ * <tr><td>{@link #KEY_INTRA_REFRESH_PERIOD}</td><td>Integer</td><td><b>encoder-only</b>, optional</td></tr>
* <tr><td>{@link #KEY_MAX_WIDTH}</td><td>Integer</td><td><b>decoder-only</b>, optional, max-resolution width</td></tr>
* <tr><td>{@link #KEY_MAX_HEIGHT}</td><td>Integer</td><td><b>decoder-only</b>, optional, max-resolution height</td></tr>
* <tr><td>{@link #KEY_REPEAT_PREVIOUS_FRAME_AFTER}</td><td>Long</td><td><b>video encoder in surface-mode only</b></td></tr>
@@ -218,6 +219,20 @@
public static final String KEY_I_FRAME_INTERVAL = "i-frame-interval";
/**
+ * An optional key describing the period of intra refresh in frames. This is an
+ * optional parameter that applies only to video encoders. If encoder supports it
+ * ({@link MediaCodecInfo.CodecCapabilities#FEATURE_IntraRefresh}), the whole
+ * frame is completely refreshed after the specified period. Also for each frame,
+ * a fix subset of macroblocks must be intra coded which leads to more constant bitrate
+ * than inserting a key frame. This key is recommended for video streaming applications
+ * as it provides low-delay and good error-resilience. This key is ignored if the
+ * video encoder does not support the intra refresh feature. Use the output format to
+ * verify that this feature was enabled.
+ * The associated value is an integer.
+ */
+ public static final String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
+
+ /**
* A key describing the temporal layering schema. This is an optional parameter
* that applies only to video encoders. Use {@link MediaCodec#getInputFormat}
* after {@link MediaCodec#configure configure} to query if the encoder supports
@@ -548,6 +563,66 @@
/** @hide */
public static final String KEY_IS_TIMED_TEXT = "is-timed-text";
+ // The following color aspect values must be in sync with the ones in HardwareAPI.h.
+ /*
+ * An optional key describing the color primaries, white point and
+ * luminance factors for video content.
+ *
+ * The associated value is an integer: 0 if unspecified, or one of the
+ * COLOR_STANDARD_ values.
+ */
+ public static final String KEY_COLOR_STANDARD = "color-standard";
+
+ /** BT.709 color chromacity coordinates with KR = 0.2126, KB = 0.0722. */
+ public static final int COLOR_STANDARD_BT709 = 1;
+
+ /** BT.601 625 color chromacity coordinates with KR = 0.299, KB = 0.114. */
+ public static final int COLOR_STANDARD_BT601_PAL = 2;
+
+ /** BT.601 525 color chromacity coordinates with KR = 0.299, KB = 0.114. */
+ public static final int COLOR_STANDARD_BT601_NTSC = 4;
+
+ /** BT.2020 color chromacity coordinates with KR = 0.2627, KB = 0.0593. */
+ public static final int COLOR_STANDARD_BT2020 = 6;
+
+ /**
+ * An optional key describing the opto-electronic transfer function used
+ * for the video content.
+ *
+ * The associated value is an integer: 0 if unspecified, or one of the
+ * COLOR_TRANSFER_ values.
+ */
+ public static final String KEY_COLOR_TRANSFER = "color-transfer";
+
+ /** Linear transfer characteristic curve. */
+ public static final int COLOR_TRANSFER_LINEAR = 1;
+
+ /** SMPTE 170M transfer characteristic curve used by BT.601/BT.709/BT.2020. This is the curve
+ * used by most non-HDR video content. */
+ public static final int COLOR_TRANSFER_SDR_VIDEO = 3;
+
+ /** SMPTE ST 2084 transfer function. This is used by some HDR video content. */
+ public static final int COLOR_TRANSFER_ST2084 = 6;
+
+ /** ARIB STD-B67 hybrid-log-gamma transfer function. This is used by some HDR video content. */
+ public static final int COLOR_TRANSFER_HLG = 7;
+
+ /**
+ * An optional key describing the range of the component values of the video content.
+ *
+ * The associated value is an integer: 0 if unspecified, or one of the
+ * COLOR_RANGE_ values.
+ */
+ public static final String KEY_COLOR_RANGE = "color-range";
+
+ /** Limited range. Y component values range from 16 to 235 for 8-bit content.
+ * Cr, Cy values range from 16 to 240 for 8-bit content.
+ * This is the default for video content. */
+ public static final int COLOR_RANGE_LIMITED = 2;
+
+ /** Full range. Y, Cr and Cb component values range from 0 to 255 for 8-bit content. */
+ public static final int COLOR_RANGE_FULL = 1;
+
/* package private */ MediaFormat(Map<String, Object> map) {
mMap = map;
}
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 9517387..f09f654 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -822,7 +822,6 @@
*
* @throws IllegalStateException if it is called before start() or after
* stop()
- * {@hide}
*/
public native void pause() throws IllegalStateException;
@@ -833,7 +832,6 @@
* @throws IllegalStateException if it is called before start() or after
* stop()
* @see android.media.MediaRecorder#pause
- * {@hide}
*/
public native void resume() throws IllegalStateException;
diff --git a/media/java/android/media/Utils.java b/media/java/android/media/Utils.java
index 2cd3c43..35b083e 100644
--- a/media/java/android/media/Utils.java
+++ b/media/java/android/media/Utils.java
@@ -174,7 +174,7 @@
return (num + den - 1) / den;
}
- private static long divUp(long num, long den) {
+ static long divUp(long num, long den) {
return (num + den - 1) / den;
}
diff --git a/media/java/android/media/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
new file mode 100644
index 0000000..ebba343
--- /dev/null
+++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
@@ -0,0 +1,180 @@
+/**
+ * Copyright (C) 2014 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.media.soundtrigger;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.os.Handler;
+import android.os.ParcelUuid;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.app.ISoundTriggerService;
+
+import java.io.PrintWriter;
+import java.util.UUID;
+
+/**
+ * A class that allows interaction with the actual sound trigger detection on the system.
+ * Sound trigger detection refers to a detectors that match generic sound patterns that are
+ * not voice-based. The voice-based recognition models should utilize the {@link
+ * VoiceInteractionService} instead. Access to this class is protected by a permission
+ * granted only to system or privileged apps.
+ *
+ * @hide
+ */
+public final class SoundTriggerDetector {
+ private static final boolean DBG = false;
+ private static final String TAG = "SoundTriggerDetector";
+
+ private final Object mLock = new Object();
+
+ private final ISoundTriggerService mSoundTriggerService;
+ private final UUID mSoundModelId;
+ private final Callback mCallback;
+ private final Handler mHandler;
+ private final RecognitionCallback mRecognitionCallback;
+
+ public abstract class Callback {
+ /**
+ * Called when the availability of the sound model changes.
+ */
+ public abstract void onAvailabilityChanged(int status);
+
+ /**
+ * Called when the sound model has triggered (such as when it matched a
+ * given sound pattern).
+ */
+ public abstract void onDetected();
+
+ /**
+ * Called when the detection fails due to an error.
+ */
+ public abstract void onError();
+
+ /**
+ * Called when the recognition is paused temporarily for some reason.
+ * This is an informational callback, and the clients shouldn't be doing anything here
+ * except showing an indication on their UI if they have to.
+ */
+ public abstract void onRecognitionPaused();
+
+ /**
+ * Called when the recognition is resumed after it was temporarily paused.
+ * This is an informational callback, and the clients shouldn't be doing anything here
+ * except showing an indication on their UI if they have to.
+ */
+ public abstract void onRecognitionResumed();
+ }
+
+ /**
+ * This class should be constructed by the {@link SoundTriggerManager}.
+ * @hide
+ */
+ SoundTriggerDetector(ISoundTriggerService soundTriggerService, UUID soundModelId,
+ @NonNull Callback callback, @Nullable Handler handler) {
+ mSoundTriggerService = soundTriggerService;
+ mSoundModelId = soundModelId;
+ mCallback = callback;
+ if (handler == null) {
+ mHandler = new Handler();
+ } else {
+ mHandler = handler;
+ }
+ mRecognitionCallback = new RecognitionCallback();
+ }
+
+ /**
+ * Starts recognition on the associated sound model. Result is indicated via the
+ * {@link Callback}.
+ * @return Indicates whether the call succeeded or not.
+ */
+ public boolean startRecognition() {
+ if (DBG) {
+ Slog.d(TAG, "startRecognition()");
+ }
+ try {
+ mSoundTriggerService.startRecognition(new ParcelUuid(mSoundModelId),
+ mRecognitionCallback);
+ } catch (RemoteException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Stops recognition for the associated model.
+ */
+ public boolean stopRecognition() {
+ try {
+ mSoundTriggerService.stopRecognition(new ParcelUuid(mSoundModelId),
+ mRecognitionCallback);
+ } catch (RemoteException e) {
+ return false;
+ }
+ return true;
+ }
+
+ public void dump(String prefix, PrintWriter pw) {
+ synchronized (mLock) {
+ // TODO: Dump useful debug information.
+ }
+ }
+
+ /**
+ * Callback that handles events from the lower sound trigger layer.
+ * @hide
+ */
+ private static class RecognitionCallback extends
+ IRecognitionStatusCallback.Stub {
+
+ /**
+ * @hide
+ */
+ @Override
+ public void onDetected(SoundTrigger.RecognitionEvent event) {
+ Slog.e(TAG, "onDetected()" + event);
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void onError(int status) {
+ Slog.e(TAG, "onError()" + status);
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void onRecognitionPaused() {
+ Slog.e(TAG, "onRecognitionPaused()");
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void onRecognitionResumed() {
+ Slog.e(TAG, "onRecognitionResumed()");
+ }
+ }
+}
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
new file mode 100644
index 0000000..4ae8e72
--- /dev/null
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -0,0 +1,172 @@
+/**
+ * Copyright (C) 2014 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.media.soundtrigger;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.os.Handler;
+import android.os.ParcelUuid;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.app.ISoundTriggerService;
+
+import java.util.HashMap;
+import java.util.UUID;
+
+/**
+ * This class provides management of non-voice (general sound trigger) based sound recognition
+ * models. Usage of this class is restricted to system or signature applications only. This allows
+ * OEMs to write apps that can manage non-voice based sound trigger models.
+ *
+ * @hide
+ * TODO: Mark this as a SystemApi and get approval.
+ */
+public final class SoundTriggerManager {
+ private static final boolean DBG = false;
+ private static final String TAG = "SoundTriggerManager";
+
+ private final Context mContext;
+ private final ISoundTriggerService mSoundTriggerService;
+
+ // Stores a mapping from the sound model UUID to the SoundTriggerInstance created by
+ // the createSoundTriggerDetector() call.
+ private final HashMap<UUID, SoundTriggerDetector> mReceiverInstanceMap;
+
+ /**
+ * @hide
+ */
+ public SoundTriggerManager(Context context, ISoundTriggerService soundTriggerService ) {
+ if (DBG) {
+ Slog.i(TAG, "SoundTriggerManager created.");
+ }
+ mSoundTriggerService = soundTriggerService;
+ mContext = context;
+ mReceiverInstanceMap = new HashMap<UUID, SoundTriggerDetector>();
+ }
+
+ /**
+ * Updates the given sound trigger model.
+ */
+ public void updateModel(Model model) {
+ try {
+ mSoundTriggerService.updateSoundModel(model.getGenericSoundModel());
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Returns the sound trigger model represented by the given UUID. An instance of {@link Model}
+ * is returned.
+ */
+ public Model getModel(UUID soundModelId) {
+ try {
+ return new Model(mSoundTriggerService.getSoundModel(
+ new ParcelUuid(soundModelId)));
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Deletes the sound model represented by the provided UUID.
+ */
+ public void deleteModel(UUID soundModelId) {
+ try {
+ mSoundTriggerService.deleteSoundModel(new ParcelUuid(soundModelId));
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Creates an instance of {@link SoundTriggerDetector} which can be used to start/stop
+ * recognition on the model and register for triggers from the model. Note that this call
+ * invalidates any previously returned instances for the same sound model Uuid.
+ *
+ * @param soundModelId UUID of the sound model to create the receiver object for.
+ * @param callback Instance of the {@link SoundTriggerDetector#Callback} object for the
+ * callbacks for the given sound model.
+ * @param handler The Handler to use for the callback operations. A null value will use the
+ * current thread's Looper.
+ * @return Instance of {@link SoundTriggerDetector} or null on error.
+ */
+ @Nullable
+ public SoundTriggerDetector createSoundTriggerDetector(UUID soundModelId,
+ @NonNull SoundTriggerDetector.Callback callback, @Nullable Handler handler) {
+ if (soundModelId == null) {
+ return null;
+ }
+
+ SoundTriggerDetector oldInstance = mReceiverInstanceMap.get(soundModelId);
+ if (oldInstance != null) {
+ // Shutdown old instance.
+ }
+ SoundTriggerDetector newInstance = new SoundTriggerDetector(mSoundTriggerService,
+ soundModelId, callback, handler);
+ mReceiverInstanceMap.put(soundModelId, newInstance);
+ return newInstance;
+ }
+
+ /**
+ * Class captures the data and fields that represent a non-keyphrase sound model. Use the
+ * factory constructor {@link Model#create()} to create an instance.
+ */
+ // We use encapsulation to expose the SoundTrigger.GenericSoundModel as a SystemApi. This
+ // prevents us from exposing SoundTrigger.GenericSoundModel as an Api.
+ public static class Model {
+
+ private SoundTrigger.GenericSoundModel mGenericSoundModel;
+
+ /**
+ * @hide
+ */
+ Model(SoundTrigger.GenericSoundModel soundTriggerModel) {
+ mGenericSoundModel = soundTriggerModel;
+ }
+
+ /**
+ * Factory constructor to create a SoundModel instance for use with methods in this
+ * class.
+ */
+ public static Model create(UUID modelUuid, UUID vendorUuid, byte[] data) {
+ return new Model(new SoundTrigger.GenericSoundModel(modelUuid,
+ vendorUuid, data));
+ }
+
+ public UUID getModelUuid() {
+ return mGenericSoundModel.uuid;
+ }
+
+ public UUID getVendorUuid() {
+ return mGenericSoundModel.vendorUuid;
+ }
+
+ public byte[] getModelData() {
+ return mGenericSoundModel.data;
+ }
+
+ /**
+ * @hide
+ */
+ SoundTrigger.GenericSoundModel getGenericSoundModel() {
+ return mGenericSoundModel;
+ }
+ }
+}
diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp
index a5d0303..5108eb5 100644
--- a/media/jni/android_media_Utils.cpp
+++ b/media/jni/android_media_Utils.cpp
@@ -80,8 +80,7 @@
}
bool GetExifFromRawImage(
- FileStream::FileStream* stream, const String8& filename,
- piex::PreviewImageData& image_data) {
+ FileStream* stream, const String8& filename, piex::PreviewImageData& image_data) {
memset(&image_data, 0, sizeof(image_data));
if (!stream->exists()) {
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 6beef44..c3452d5 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -78,6 +78,16 @@
</intent-filter>
</activity>
+ <activity
+ android:name=".OpenExternalDirectoryActivity"
+ android:theme="@android:style/Theme.Translucent.NoTitleBar">
+ <intent-filter>
+ <action android:name="android.intent.action.OPEN_EXTERNAL_DIRECTORY" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:scheme="file" />
+ </intent-filter>
+ </activity>
+
<provider
android:name=".RecentsProvider"
android:authorities="com.android.documentsui.recents"
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index 5a9bc16..aefdc67 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -65,13 +65,9 @@
<string name="menu_paste_from_clipboard">Paste</string>
<!-- Menu item that reveals internal storage built into the device [CHAR LIMIT=24] -->
- <string name="menu_advanced_show" product="nosdcard">Show internal storage</string>
- <!-- Menu item that reveals SD cards built into the device [CHAR LIMIT=24] -->
- <string name="menu_advanced_show" product="default">Show SD card</string>
+ <string name="menu_advanced_show">Show internal storage</string>
<!-- Menu item that hides internal storage built into the device [CHAR LIMIT=24] -->
- <string name="menu_advanced_hide" product="nosdcard">Hide internal storage</string>
- <!-- Menu item that hides SD cards built into the device [CHAR LIMIT=24] -->
- <string name="menu_advanced_hide" product="default">Hide SD card</string>
+ <string name="menu_advanced_hide">Hide internal storage</string>
<!-- Menu item that reveals the sizes of displayed files [CHAR LIMIT=24] -->
<string name="menu_file_size_show">Show file size</string>
@@ -196,4 +192,13 @@
<string name="menu_rename">Rename</string>
<!-- Toast shown when renaming document failed with an error [CHAR LIMIT=48] -->
<string name="rename_error">Failed to rename document</string>
+
+ <!-- DO NOT TRANSLATE - final phrase has not been decided yet (b/26750152) -->
+ <string name="open_external_dialog_request">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g>
+ access to <xliff:g id="directory" example="Pictures"><i>^2</i></xliff:g> folder on
+ <xliff:g id="storage" example="SD Card"><i>^3</i></xliff:g>?</string>
+ <!-- Text in the button asking user to allow access to a given directory. -->
+ <string name="allow">Allow</string>
+ <!-- Text in the button asking user to deny access to a given directory. -->
+ <string name="deny">Deny</string>
</resources>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index d14631d..f4dfd73 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -45,4 +45,8 @@
<item name="android:maxHeight">3dp</item>
</style>
+ <!-- TODO: use the proper dialog and/or inline if not overriding -->
+ <style name="AlertDialogTheme" parent="@style/Theme.AppCompat.Light.Dialog.Alert">
+ </style>
+
</resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
new file mode 100644
index 0000000..5dc4f57
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package com.android.documentsui;
+
+import static android.os.Environment.isStandardDirectory;
+import static com.android.documentsui.Shared.DEBUG;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.ContentProvider;
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
+import android.provider.DocumentsContract;
+import android.text.TextUtils;
+import android.util.Log;
+
+/**
+ * Activity responsible for handling {@link Intent#ACTION_OPEN_EXTERNAL_DOCUMENT}.
+ */
+public class OpenExternalDirectoryActivity extends Activity {
+ private static final String TAG = "OpenExternalDirectoryActivity";
+ private static final String FM_TAG = "open_external_directory";
+ private static final String EXTERNAL_STORAGE_AUTH = "com.android.externalstorage.documents";
+ private static final String EXTRA_FILE = "com.android.documentsui.FILE";
+ private static final String EXTRA_APP_LABEL = "com.android.documentsui.APP_LABEL";
+ private static final String EXTRA_VOLUME_LABEL = "com.android.documentsui.VOLUME_LABEL";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final Intent intent = getIntent();
+ if (intent == null || intent.getData() == null) {
+ Log.d(TAG, "missing intent or intent data: " + intent);
+ setResult(RESULT_CANCELED);
+ finish();
+ return;
+ }
+
+ final String path = intent.getData().getPath();
+ final int userId = UserHandle.myUserId();
+ if (!showFragment(this, userId, path)) {
+ setResult(RESULT_CANCELED);
+ finish();
+ return;
+ }
+ }
+
+ /**
+ * Validates the given {@code path} and display the appropriate dialog asking the user to grant
+ * access to it.
+ */
+ static boolean showFragment(Activity activity, int userId, String path) {
+ Log.d(TAG, "showFragment() for path " + path + " and user " + userId);
+ if (path == null) {
+ Log.e(TAG, "INTERNAL ERROR: showFragment() with null path");
+ return false;
+ }
+ File file;
+ try {
+ file = new File(new File(path).getCanonicalPath());
+ } catch (IOException e) {
+ Log.e(TAG, "Could not get canonical file from " + path);
+ return false;
+ }
+ final StorageManager sm =
+ (StorageManager) activity.getSystemService(Context.STORAGE_SERVICE);
+
+ final String root = file.getParent();
+ final String directory = file.getName();
+
+ // Verify directory is valid.
+ if (TextUtils.isEmpty(directory) || !isStandardDirectory(directory)) {
+ Log.d(TAG, "Directory '" + directory + "' is not standard (full path: '" + path + "')");
+ return false;
+ }
+
+ // Gets volume label and converted path
+ String volumeLabel = null;
+ final List<VolumeInfo> volumes = sm.getVolumes();
+ if (DEBUG) Log.d(TAG, "Number of volumes: " + volumes.size());
+ for (VolumeInfo volume : volumes) {
+ if (isRightVolume(volume, root, userId)) {
+ final File internalRoot = volume.getInternalPathForUser(userId);
+ // Must convert path before calling getDocIdForFileCreateNewDir()
+ if (DEBUG) Log.d(TAG, "Converting " + root + " to " + internalRoot);
+ file = new File(internalRoot, directory);
+ volumeLabel = sm.getBestVolumeDescription(volume);
+ break;
+ }
+ }
+ if (volumeLabel == null) {
+ Log.e(TAG, "Could not get volume for " + path);
+ return false;
+ }
+
+ // Gets the package label.
+ final String appLabel = getAppLabel(activity);
+ if (appLabel == null) {
+ return false;
+ }
+
+ // Sets args that will be retrieve on onCreate()
+ final Bundle args = new Bundle();
+ args.putString(EXTRA_FILE, file.getAbsolutePath());
+ args.putString(EXTRA_VOLUME_LABEL, volumeLabel);
+ args.putString(EXTRA_APP_LABEL, appLabel);
+
+ final FragmentManager fm = activity.getFragmentManager();
+ final FragmentTransaction ft = fm.beginTransaction();
+ final OpenExternalDirectoryDialogFragment fragment =
+ new OpenExternalDirectoryDialogFragment();
+ fragment.setArguments(args);
+ ft.add(fragment, FM_TAG);
+ ft.commitAllowingStateLoss();
+
+ return true;
+ }
+
+ private static String getAppLabel(Activity activity) {
+ final String packageName = activity.getCallingPackage();
+ final PackageManager pm = activity.getPackageManager();
+ try {
+ return pm.getApplicationLabel(pm.getApplicationInfo(packageName, 0)).toString();
+ } catch (NameNotFoundException e) {
+ Log.w(TAG, "Could not get label for package " + packageName);
+ return null;
+ }
+ }
+
+ private static boolean isRightVolume(VolumeInfo volume, String root, int userId) {
+ final File userPath = volume.getPathForUser(userId);
+ final String path = userPath == null ? null : volume.getPathForUser(userId).getPath();
+ final boolean isVisible = volume.isVisibleForWrite(userId);
+ if (DEBUG) {
+ Log.d(TAG, "Volume: " + volume + " userId: " + userId + " root: " + root
+ + " volumePath: " + volume.getPath().getPath()
+ + " pathForUser: " + path
+ + " internalPathForUser: " + volume.getInternalPath()
+ + " isVisible: " + isVisible);
+ }
+ return volume.isVisibleForWrite(userId) && root.equals(path);
+ }
+
+ private static Intent createGrantedUriPermissionsIntent(ContentProviderClient provider,
+ File file) {
+ // Calls ExternalStorageProvider to get the doc id for the file
+ final Bundle bundle;
+ try {
+ bundle = provider.call("getDocIdForFileCreateNewDir", file.getPath(), null);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Did not get doc id from External Storage provider for " + file, e);
+ return null;
+ }
+ final String docId = bundle == null ? null : bundle.getString("DOC_ID");
+ if (docId == null) {
+ Log.e(TAG, "Did not get doc id from External Storage provider for " + file);
+ return null;
+ }
+ Log.d(TAG, "doc id for " + file + ": " + docId);
+
+ final Uri uri = DocumentsContract.buildTreeDocumentUri(EXTERNAL_STORAGE_AUTH, docId);
+ if (uri == null) {
+ Log.e(TAG, "Could not get URI for doc id " + docId);
+ return null;
+ }
+
+ if (DEBUG) Log.d(TAG, "URI for " + file + ": " + uri);
+ final Intent intent = new Intent();
+ intent.setData(uri);
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
+ return intent;
+ }
+
+ private static class OpenExternalDirectoryDialogFragment extends DialogFragment {
+
+ private File mFile;
+ private String mVolumeLabel;
+ private String mAppLabel;
+ private ContentProviderClient mExternalStorageClient;
+ private ContentResolver mResolver;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final Bundle args = getArguments();
+ if (args != null) {
+ mFile = new File(args.getString(EXTRA_FILE));
+ mVolumeLabel = args.getString(EXTRA_VOLUME_LABEL);
+ mAppLabel = args.getString(EXTRA_APP_LABEL);
+ mResolver = getContext().getContentResolver();
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mExternalStorageClient != null) {
+ mExternalStorageClient.close();
+ }
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final String folder = mFile.getName();
+ final Activity activity = getActivity();
+ final OnClickListener listener = new OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Intent intent = null;
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ intent = createGrantedUriPermissionsIntent(getExternalStorageClient(),
+ mFile);
+ }
+ if (which == DialogInterface.BUTTON_NEGATIVE || intent == null) {
+ activity.setResult(RESULT_CANCELED);
+ } else {
+ activity.setResult(RESULT_OK, intent);
+ }
+ activity.finish();
+ }
+ };
+
+ final CharSequence message = TextUtils
+ .expandTemplate(
+ getText(R.string.open_external_dialog_request), mAppLabel, folder,
+ mVolumeLabel);
+ return new AlertDialog.Builder(activity, R.style.AlertDialogTheme)
+ .setMessage(message)
+ .setPositiveButton(R.string.allow, listener)
+ .setNegativeButton(R.string.deny, listener)
+ .create();
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ super.onCancel(dialog);
+ final Activity activity = getActivity();
+ activity.setResult(RESULT_CANCELED);
+ activity.finish();
+ }
+
+ private synchronized ContentProviderClient getExternalStorageClient() {
+ if (mExternalStorageClient == null) {
+ mExternalStorageClient =
+ mResolver.acquireContentProviderClient(EXTERNAL_STORAGE_AUTH);
+ }
+ return mExternalStorageClient;
+ }
+ }
+}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 43527a2..1bfc19c 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -25,6 +25,7 @@
import android.database.MatrixCursor.RowBuilder;
import android.graphics.Point;
import android.net.Uri;
+import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.FileObserver;
import android.os.FileUtils;
@@ -234,7 +235,13 @@
return projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION;
}
+
private String getDocIdForFile(File file) throws FileNotFoundException {
+ return getDocIdForFileMaybeCreate(file, false);
+ }
+
+ private String getDocIdForFileMaybeCreate(File file, boolean createNewDir)
+ throws FileNotFoundException {
String path = file.getAbsolutePath();
// Find the most-specific root path
@@ -266,6 +273,13 @@
path = path.substring(rootPath.length() + 1);
}
+ if (!file.exists() && createNewDir) {
+ Log.i(TAG, "Creating new directory " + file);
+ if (!file.mkdir()) {
+ Log.e(TAG, "Could not create directory " + file);
+ }
+ }
+
return mostSpecificId + ':' + path;
}
@@ -609,6 +623,34 @@
}
}
+ @Override
+ public Bundle call(String method, String arg, Bundle extras) {
+ Bundle bundle = super.call(method, arg, extras);
+ if (bundle == null && !TextUtils.isEmpty(method)) {
+ switch (method) {
+ case "getDocIdForFileCreateNewDir": {
+ getContext().enforceCallingPermission(
+ android.Manifest.permission.MANAGE_DOCUMENTS, null);
+ if (TextUtils.isEmpty(arg)) {
+ return null;
+ }
+ try {
+ final String docId = getDocIdForFileMaybeCreate(new File(arg), true);
+ bundle = new Bundle();
+ bundle.putString("DOC_ID", docId);
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "file '" + arg + "' not found");
+ return null;
+ }
+ break;
+ }
+ default:
+ Log.w(TAG, "unknown method passed to call(): " + method);
+ }
+ }
+ return bundle;
+ }
+
private static String getTypeForFile(File file) {
if (file.isDirectory()) {
return Document.MIME_TYPE_DIR;
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index cbf22c0..40c11cf 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -29,6 +29,7 @@
import android.widget.Button;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.widget.LockPatternUtils;
@@ -117,7 +118,7 @@
* Shows the emergency dialer or returns the user to the existing call.
*/
public void takeEmergencyCallAction() {
- MetricsLogger.action(mContext, MetricsLogger.ACTION_EMERGENCY_CALL);
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_EMERGENCY_CALL);
// TODO: implement a shorter timeout once new PowerManager API is ready.
// should be the equivalent to the old userActivity(EMERGENCY_CALL_TIMEOUT)
mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
diff --git a/packages/SystemUI/res/drawable/ic_history.xml b/packages/SystemUI/res/drawable/ic_history.xml
new file mode 100644
index 0000000..e936864
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_history.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89 .07 .14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7
+7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13
+21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54 .72 -1.21-3.5-2.08V8H12z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml
new file mode 100644
index 0000000..b4144a3
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright (C) 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="40.0"
+ android:viewportHeight="40.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M19.0,6.41L17.59,5.0 12.0,10.59 6.41,5.0 5.0,6.41 10.59,12.0 5.0,17.59 6.41,19.0 12.0,13.41 17.59,19.0 19.0,17.59 13.41,12.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml b/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml
new file mode 100644
index 0000000..4e2a024
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright (C) 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="17.0dp"
+ android:height="17.0dp"
+ android:viewportWidth="40.0"
+ android:viewportHeight="40.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M19.0,6.41L17.59,5.0 12.0,10.59 6.41,5.0 5.0,6.41 10.59,12.0 5.0,17.59 6.41,19.0 12.0,13.41 17.59,19.0 19.0,17.59 13.41,12.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/recents.xml b/packages/SystemUI/res/layout/recents.xml
index 16ff14c..186aaf6 100644
--- a/packages/SystemUI/res/layout/recents.xml
+++ b/packages/SystemUI/res/layout/recents.xml
@@ -17,14 +17,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
- <!-- Status Bar Scrim View -->
- <ImageView
- android:id="@+id/status_bar_scrim"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal|top"
- android:scaleType="fitXY"
- android:src="@drawable/recents_status_gradient" />
<!-- Recents View -->
<com.android.systemui.recents.views.RecentsView
@@ -33,12 +25,6 @@
android:layout_height="match_parent">
</com.android.systemui.recents.views.RecentsView>
- <!-- History View -->
- <ViewStub android:id="@+id/history_view_stub"
- android:layout="@layout/recents_history"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
<!-- Nav Bar Scrim View -->
<ImageView
android:id="@+id/nav_bar_scrim"
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index 4b68e77..b2c0331 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -24,5 +24,4 @@
android:textColor="#ffffffff"
android:text="@string/recents_empty_message"
android:fontFamily="sans-serif"
- android:background="#80000000"
android:visibility="gone" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_history.xml b/packages/SystemUI/res/layout/recents_history.xml
index b65a5c5..dc2da72 100644
--- a/packages/SystemUI/res/layout/recents_history.xml
+++ b/packages/SystemUI/res/layout/recents_history.xml
@@ -17,7 +17,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="#99000000"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
diff --git a/packages/SystemUI/res/layout/recents_history_button.xml b/packages/SystemUI/res/layout/recents_history_button.xml
index 8c96fc6..538bad1 100644
--- a/packages/SystemUI/res/layout/recents_history_button.xml
+++ b/packages/SystemUI/res/layout/recents_history_button.xml
@@ -15,15 +15,24 @@
-->
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:id="@+id/button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:gravity="start|center_vertical"
- android:text="@string/recents_show_history_button_label"
+ android:paddingStart="14dp"
+ android:paddingEnd="14dp"
+ android:paddingTop="12dp"
+ android:paddingBottom="12dp"
+ android:text="@string/recents_history_button_label"
android:textSize="14sp"
android:textColor="#FFFFFF"
android:textAllCaps="true"
+ android:drawableStart="@drawable/ic_history"
+ android:drawablePadding="6dp"
android:shadowColor="#99000000"
android:shadowDx="0"
android:shadowDy="2"
android:shadowRadius="5"
- android:fontFamily="sans-serif-medium" />
\ No newline at end of file
+ android:fontFamily="sans-serif-medium"
+ android:background="?android:selectableItemBackground"
+ android:visibility="invisible" />
diff --git a/packages/SystemUI/res/layout/recents_history_date.xml b/packages/SystemUI/res/layout/recents_history_date.xml
index 6d6a9ee..13c7dbe 100644
--- a/packages/SystemUI/res/layout/recents_history_date.xml
+++ b/packages/SystemUI/res/layout/recents_history_date.xml
@@ -15,10 +15,12 @@
-->
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:theme="@android:style/Theme.Material"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:padding="12dp"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:paddingTop="12dp"
+ android:paddingBottom="12dp"
android:gravity="start"
android:textSize="14sp"
android:textColor="#009688"
diff --git a/packages/SystemUI/res/layout/recents_history_task.xml b/packages/SystemUI/res/layout/recents_history_task.xml
index ae11006..e92c24a 100644
--- a/packages/SystemUI/res/layout/recents_history_task.xml
+++ b/packages/SystemUI/res/layout/recents_history_task.xml
@@ -15,7 +15,6 @@
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:theme="@android:style/Theme.Material"
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="horizontal"
@@ -27,7 +26,8 @@
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
- android:layout_marginStart="16dp" />
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="12dp" />
<TextView
android:id="@+id/description"
android:layout_width="0dp"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e245c24..8b0350a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -137,6 +137,8 @@
<dimen name="standard_notification_panel_width">416dp</dimen>
<dimen name="notification_panel_width">@dimen/match_parent</dimen>
+ <dimen name="volume_dialog_panel_width">@dimen/standard_notification_panel_width</dimen>
+
<!-- Gravity for the notification panel -->
<integer name="standard_notification_panel_layout_gravity">0x31</integer><!-- top|center_horizontal -->
<integer name="notification_panel_layout_gravity">0x37</integer><!-- fill_horizontal|top -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 02158ac..b096934 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -359,6 +359,9 @@
<!-- Content description of the data connection with no SIM for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_no_sim">No SIM.</string>
+ <!-- Content description of the cell data being disabled. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_cell_data_off">Cellular Data Off</string>
+
<!-- Content description of the bluetooth tethering icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_bluetooth_tether">Bluetooth tethering.</string>
@@ -712,9 +715,7 @@
<!-- Recents: Launch error string. [CHAR LIMIT=NONE] -->
<string name="recents_launch_error_message">Could not start <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
<!-- Recents: Show history string. [CHAR LIMIT=NONE] -->
- <string name="recents_show_history_button_label">More</string>
- <!-- Recents: A format string to set the number of availabe historical tasks in recents. [CHAR LIMIT=NONE] -->
- <string name="recents_history_label_format"><xliff:g id="number">%d</xliff:g> More</string>
+ <string name="recents_history_button_label">History</string>
<!-- Recents: MultiStack add stack split horizontal radio button. [CHAR LIMIT=NONE] -->
<string name="recents_multistack_add_stack_dialog_split_horizontal">Split Horizontal</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 4329f78..e40a0f4 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -20,7 +20,7 @@
<item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
</style>
- <style name="RecentsTheme" parent="@android:style/Theme.Material.Light">
+ <style name="RecentsTheme" parent="@android:style/Theme.Material">
<!-- NoTitle -->
<item name="android:windowNoTitle">true</item>
<!-- Misc -->
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 5b955a4..6b74652 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -67,6 +67,7 @@
private FalsingManager mFalsingManager;
private float mInitialTouchPos;
+ private float mPerpendicularInitialTouchPos;
private boolean mDragging;
private View mCurrView;
private View mCurrAnimView;
@@ -117,6 +118,10 @@
return mSwipeDirection == X ? ev.getX() : ev.getY();
}
+ private float getPerpendicularPos(MotionEvent ev) {
+ return mSwipeDirection == X ? ev.getY() : ev.getX();
+ }
+
private float getTranslation(View v) {
return mSwipeDirection == X ? v.getTranslationX() : v.getTranslationY();
}
@@ -240,6 +245,7 @@
mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView);
mVelocityTracker.addMovement(ev);
mInitialTouchPos = getPos(ev);
+ mPerpendicularInitialTouchPos = getPerpendicularPos(ev);
if (mLongPressListener != null) {
if (mWatchLongPress == null) {
@@ -271,8 +277,11 @@
if (mCurrView != null && !mLongPressSent) {
mVelocityTracker.addMovement(ev);
float pos = getPos(ev);
+ float perpendicularPos = getPerpendicularPos(ev);
float delta = pos - mInitialTouchPos;
- if (Math.abs(delta) > mPagingTouchSlop) {
+ float deltaPerpendicular = perpendicularPos - mPerpendicularInitialTouchPos;
+ if (Math.abs(delta) > mPagingTouchSlop
+ && Math.abs(delta) > Math.abs(deltaPerpendicular)) {
mCallback.onBeginDrag(mCurrView);
mDragging = true;
mInitialTouchPos = getPos(ev) - getTranslation(mCurrAnimView);
@@ -280,7 +289,6 @@
removeLongPressCallback();
}
}
-
break;
case MotionEvent.ACTION_UP:
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 72629a3..20e2fa4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -82,9 +82,8 @@
/**
* Declare the category of this tile.
*
- * Categories are defined in {@link com.android.internal.logging.MetricsLogger}
- * or if there is no relevant existing category you may define one in
- * {@link com.android.systemui.qs.QSTile}.
+ * Categories are defined in {@link com.android.internal.logging.MetricsProto.MetricsEvent}
+ * by editing frameworks/base/proto/src/metrics_constants.proto.
*/
abstract public int getMetricsCategory();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java
index ac4f05f..36bed0d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java
@@ -20,7 +20,9 @@
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.graphics.drawable.Drawable;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
@@ -84,6 +86,6 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_INTENT;
+ return MetricsEvent.QS_INTENT;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index d398b64..886531a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -31,7 +31,9 @@
import android.view.IWindowManager;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.phone.QSTileHost;
@@ -197,7 +199,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_CUSTOM;
+ return MetricsEvent.QS_CUSTOM;
}
public void startUnlockAndRun() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index c696f88..d78d6ff 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -24,6 +24,7 @@
import android.provider.Settings.Global;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.qs.GlobalSetting;
import com.android.systemui.qs.QSTile;
@@ -85,7 +86,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_AIRPLANEMODE;
+ return MetricsEvent.QS_AIRPLANEMODE;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index 60238fc3..fd8857d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -25,7 +25,7 @@
import android.widget.Checkable;
import android.widget.ImageView;
import android.widget.TextView;
-import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settingslib.BatteryInfo;
import com.android.systemui.BatteryMeterDrawable;
import com.android.systemui.R;
@@ -64,7 +64,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_BATTERY_TILE;
+ return MetricsEvent.QS_BATTERY_TILE;
}
@Override
@@ -199,7 +199,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_BATTERY_DETAIL;
+ return MetricsEvent.QS_BATTERY_DETAIL;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 3750290..6a07a07 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -24,7 +24,9 @@
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.systemui.R;
import com.android.systemui.qs.QSDetailItems;
@@ -127,7 +129,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_BLUETOOTH;
+ return MetricsEvent.QS_BLUETOOTH;
}
@Override
@@ -181,14 +183,14 @@
@Override
public void setToggleState(boolean state) {
- MetricsLogger.action(mContext, MetricsLogger.QS_BLUETOOTH_TOGGLE, state);
+ MetricsLogger.action(mContext, MetricsEvent.QS_BLUETOOTH_TOGGLE, state);
mController.setBluetoothEnabled(state);
showDetail(false);
}
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_BLUETOOTH_DETAILS;
+ return MetricsEvent.QS_BLUETOOTH_DETAILS;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index de4c21c..18eb7a1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -23,7 +23,9 @@
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
@@ -125,7 +127,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_CAST;
+ return MetricsEvent.QS_CAST;
}
@Override
@@ -181,7 +183,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_CAST_DETAILS;
+ return MetricsEvent.QS_CAST_DETAILS;
}
@Override
@@ -255,7 +257,7 @@
@Override
public void onDetailItemClick(Item item) {
if (item == null || item.tag == null) return;
- MetricsLogger.action(mContext, MetricsLogger.QS_CAST_SELECT);
+ MetricsLogger.action(mContext, MetricsEvent.QS_CAST_SELECT);
final CastDevice device = (CastDevice) item.tag;
mController.startCasting(device);
}
@@ -263,7 +265,7 @@
@Override
public void onDetailItemDisconnect(Item item) {
if (item == null || item.tag == null) return;
- MetricsLogger.action(mContext, MetricsLogger.QS_CAST_DISCONNECT);
+ MetricsLogger.action(mContext, MetricsEvent.QS_CAST_DISCONNECT);
final CastDevice device = (CastDevice) item.tag;
mController.stopCasting(device);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 1f8fae0..aacdbc9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -23,7 +23,9 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settingslib.net.DataUsageController;
import com.android.systemui.R;
import com.android.systemui.qs.QSIconView;
@@ -89,7 +91,7 @@
protected void handleSecondaryClick() {
boolean dataEnabled = mDataController.isMobileDataSupported()
&& mDataController.isMobileDataEnabled();
- MetricsLogger.action(mContext, MetricsLogger.QS_CELLULAR_TOGGLE, !dataEnabled);
+ MetricsLogger.action(mContext, MetricsEvent.QS_CELLULAR_TOGGLE, !dataEnabled);
mDataController.setMobileDataEnabled(!dataEnabled);
}
@@ -131,7 +133,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_CELLULAR;
+ return MetricsEvent.QS_CELLULAR;
}
// Remove the period from the network name
@@ -241,13 +243,13 @@
@Override
public void setToggleState(boolean state) {
- MetricsLogger.action(mContext, MetricsLogger.QS_CELLULAR_TOGGLE, state);
+ MetricsLogger.action(mContext, MetricsEvent.QS_CELLULAR_TOGGLE, state);
mDataController.setMobileDataEnabled(state);
}
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_DATAUSAGEDETAIL;
+ return MetricsEvent.QS_DATAUSAGEDETAIL;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 23a15b9..6e843e9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -17,7 +17,9 @@
package com.android.systemui.qs.tiles;
import android.provider.Settings.Secure;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.SecureSetting;
@@ -84,7 +86,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_COLORINVERSION;
+ return MetricsEvent.QS_COLORINVERSION;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 39eda6b..1f9f1c4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -30,7 +30,9 @@
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
import android.widget.Toast;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SysUIToast;
@@ -154,7 +156,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_DND;
+ return MetricsEvent.QS_DND;
}
@Override
@@ -229,7 +231,7 @@
@Override
public void setToggleState(boolean state) {
- MetricsLogger.action(mContext, MetricsLogger.QS_DND_TOGGLE, state);
+ MetricsLogger.action(mContext, MetricsEvent.QS_DND_TOGGLE, state);
if (!state) {
mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
showDetail(false);
@@ -238,7 +240,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_DND_DETAILS;
+ return MetricsEvent.QS_DND_DETAILS;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index 39d9da1..1d9f15b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -17,7 +17,9 @@
package com.android.systemui.qs.tiles;
import android.app.ActivityManager;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.FlashlightController;
@@ -92,7 +94,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_FLASHLIGHT;
+ return MetricsEvent.QS_FLASHLIGHT;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 55aa32b..db86047 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -17,6 +17,7 @@
package com.android.systemui.qs.tiles;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.HotspotController;
@@ -75,7 +76,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_HOTSPOT;
+ return MetricsEvent.QS_HOTSPOT;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 0883445..e1dc9f2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -30,6 +30,7 @@
import android.util.Log;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.qs.QSTile;
import java.util.Arrays;
@@ -155,7 +156,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_INTENT;
+ return MetricsEvent.QS_INTENT;
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index e79aabf..724659c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -17,6 +17,7 @@
package com.android.systemui.qs.tiles;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -99,7 +100,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_LOCATION;
+ return MetricsEvent.QS_LOCATION;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 79155b2..f920d48 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -18,7 +18,9 @@
import android.content.Context;
import android.content.res.Configuration;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.RotationLockController;
@@ -108,7 +110,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_ROTATIONLOCK;
+ return MetricsEvent.QS_ROTATIONLOCK;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index b44ef0b..2c8a478 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -24,6 +24,7 @@
import android.view.ViewGroup;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settingslib.RestrictedLockUtils;
import com.android.systemui.R;
import com.android.systemui.qs.PseudoGridView;
@@ -94,7 +95,7 @@
mContext, tag.enforcedAdmin);
mController.startActivity(intent);
} else {
- MetricsLogger.action(mContext, MetricsLogger.QS_SWITCH_USER);
+ MetricsLogger.action(mContext, MetricsEvent.QS_SWITCH_USER);
switchTo(tag);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
index d29cae4..6eb0646 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -18,7 +18,7 @@
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.Pair;
-import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -52,7 +52,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_USER_TILE;
+ return MetricsEvent.QS_USER_TILE;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 95ea3f8..42296f2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -24,7 +24,9 @@
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settingslib.wifi.AccessPoint;
import com.android.systemui.R;
import com.android.systemui.qs.QSDetailItems;
@@ -162,7 +164,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_WIFI;
+ return MetricsEvent.QS_WIFI;
}
@Override
@@ -256,14 +258,14 @@
@Override
public void setToggleState(boolean state) {
if (DEBUG) Log.d(TAG, "setToggleState " + state);
- MetricsLogger.action(mContext, MetricsLogger.QS_WIFI_TOGGLE, state);
+ MetricsLogger.action(mContext, MetricsEvent.QS_WIFI_TOGGLE, state);
mController.setWifiEnabled(state);
showDetail(false);
}
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_WIFI_DETAILS;
+ return MetricsEvent.QS_WIFI_DETAILS;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 34ed37b..508490f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -24,7 +24,9 @@
import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.os.UserManager;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
@@ -124,7 +126,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_WORKMODE;
+ return MetricsEvent.QS_WORKMODE;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 189e8d3..cd2c942 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -37,7 +37,9 @@
import android.view.ViewStub;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.AppWidgetProviderChangedEvent;
@@ -55,6 +57,7 @@
import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
import com.android.systemui.recents.events.activity.ShowHistoryEvent;
import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
+import com.android.systemui.recents.events.activity.ToggleHistoryEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
@@ -103,8 +106,6 @@
// Top level views
private RecentsView mRecentsView;
private SystemBarScrimViews mScrimViews;
- private ViewStub mHistoryViewStub;
- private RecentsHistoryView mHistoryView;
// Search AppWidget
private AppWidgetProviderInfo mSearchWidgetInfo;
@@ -125,12 +126,14 @@
* just finishing the activity since we don't know what is behind Recents in the task stack.
*/
class FinishRecentsRunnable implements Runnable {
+
Intent mLaunchIntent;
+ ActivityOptions mOpts;
/**
* Creates a finish runnable that starts the specified intent.
*/
- public FinishRecentsRunnable(Intent launchIntent) {
+ public FinishRecentsRunnable(Intent launchIntent, ActivityOptions opts) {
mLaunchIntent = launchIntent;
}
@@ -139,13 +142,16 @@
try {
RecentsActivityLaunchState launchState =
Recents.getConfiguration().getLaunchState();
- ActivityOptions opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this,
- launchState.launchedFromSearchHome ?
- R.anim.recents_to_search_launcher_enter :
- R.anim.recents_to_launcher_enter,
- launchState.launchedFromSearchHome ?
- R.anim.recents_to_search_launcher_exit :
- R.anim.recents_to_launcher_exit);
+ ActivityOptions opts = mOpts;
+ if (opts == null) {
+ opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this,
+ launchState.launchedFromSearchHome ?
+ R.anim.recents_to_search_launcher_enter :
+ R.anim.recents_to_launcher_enter,
+ launchState.launchedFromSearchHome ?
+ R.anim.recents_to_search_launcher_exit :
+ R.anim.recents_to_launcher_exit);
+ }
startActivityAsUser(mLaunchIntent, opts.toBundle(), UserHandle.CURRENT);
} catch (Exception e) {
Log.e(TAG, getString(R.string.recents_launch_error_message, "Home"), e);
@@ -203,12 +209,9 @@
int launchTaskIndexInStack = launchTarget != null
? stack.indexOfStackTask(launchTarget)
: 0;
- boolean hasStatusBarScrim = taskCount > 0;
- boolean animateStatusBarScrim = launchState.launchedFromHome;
boolean hasNavBarScrim = (taskCount > 0) && !config.hasTransposedNavBar;
boolean animateNavBarScrim = true;
- mScrimViews.prepareEnterRecentsAnimation(hasStatusBarScrim, animateStatusBarScrim,
- hasNavBarScrim, animateNavBarScrim);
+ mScrimViews.prepareEnterRecentsAnimation(hasNavBarScrim, animateNavBarScrim);
// Keep track of whether we launched from the nav bar button or via alt-tab
if (launchState.launchedWithAltTab) {
@@ -232,8 +235,7 @@
* Dismisses the history view back into the stack view.
*/
boolean dismissHistory() {
- // Try and hide the history view first
- if (mHistoryView != null && mHistoryView.isVisible()) {
+ if (mRecentsView.isHistoryVisible()) {
EventBus.getDefault().send(new HideHistoryEvent(true /* animate */));
return true;
}
@@ -285,9 +287,24 @@
* Dismisses Recents directly to Home without checking whether it is currently visible.
*/
void dismissRecentsToHome(boolean animateTaskViews) {
+ dismissRecentsToHome(animateTaskViews, null);
+ }
+
+ /**
+ * Dismisses Recents directly to Home without checking whether it is currently visible.
+ *
+ * @param overrideAnimation If not null, will override the default animation that is based on
+ * how Recents was launched.
+ */
+ void dismissRecentsToHome(boolean animateTaskViews, ActivityOptions overrideAnimation) {
DismissRecentsToHomeAnimationStarted dismissEvent =
new DismissRecentsToHomeAnimationStarted(animateTaskViews);
- dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
+ if (overrideAnimation != null) {
+ dismissEvent.addPostAnimationCallback(new FinishRecentsRunnable(
+ mFinishLaunchHomeRunnable.mLaunchIntent, overrideAnimation));
+ } else {
+ dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
+ }
dismissEvent.addPostAnimationCallback(new Runnable() {
@Override
public void run() {
@@ -340,7 +357,6 @@
mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
- mHistoryViewStub = (ViewStub) findViewById(R.id.history_view_stub);
mScrimViews = new SystemBarScrimViews(this);
getWindow().getAttributes().privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
@@ -358,7 +374,7 @@
homeIntent.addCategory(Intent.CATEGORY_HOME);
homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent);
+ mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent, null);
// Bind the search app widget when we first start up
if (RecentsDebugFlags.Static.EnableSearchBar) {
@@ -402,7 +418,7 @@
SystemServicesProxy ssp = Recents.getSystemServices();
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, true));
- MetricsLogger.visible(this, MetricsLogger.OVERVIEW_ACTIVITY);
+ MetricsLogger.visible(this, MetricsEvent.OVERVIEW_ACTIVITY);
mRecentsView.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@@ -439,7 +455,7 @@
// Reset some states
mIgnoreAltTabRelease = false;
- if (mHistoryView != null) {
+ if (mRecentsView.isHistoryVisible()) {
EventBus.getDefault().send(new HideHistoryEvent(false /* animate */));
}
@@ -460,7 +476,7 @@
launchState.launchedHasConfigurationChanged = false;
launchState.launchedViaDragGesture = false;
- MetricsLogger.hidden(this, MetricsLogger.OVERVIEW_ACTIVITY);
+ MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
}
@Override
@@ -501,8 +517,7 @@
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
- outState.putBoolean(KEY_SAVED_STATE_HISTORY_VISIBLE,
- (mHistoryView != null) && mHistoryView.isVisible());
+ outState.putBoolean(KEY_SAVED_STATE_HISTORY_VISIBLE, mRecentsView.isHistoryVisible());
}
@Override
@@ -633,7 +648,7 @@
// Focus the next task
EventBus.getDefault().send(new FocusNextTaskViewEvent(timerIndicatorDuration));
- MetricsLogger.action(this, MetricsLogger.ACTION_OVERVIEW_PAGE);
+ MetricsLogger.action(this, MetricsEvent.ACTION_OVERVIEW_PAGE);
}
}
@@ -649,15 +664,12 @@
}
} else if (event.triggeredFromHomeKey) {
// Otherwise, dismiss Recents to Home
- if (mHistoryView != null && mHistoryView.isVisible()) {
- HideHistoryEvent hideEvent = new HideHistoryEvent(true /* animate */);
- hideEvent.addPostAnimationCallback(new Runnable() {
- @Override
- public void run() {
- dismissRecentsToHome(true /* animateTaskViews */);
- }
- });
- EventBus.getDefault().send(hideEvent);
+ if (mRecentsView.isHistoryVisible()) {
+ // If the history view is visible, then just cross-fade home
+ ActivityOptions opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this,
+ R.anim.recents_to_launcher_enter,
+ R.anim.recents_to_launcher_exit);
+ dismissRecentsToHome(false /* animate */, opts);
} else {
dismissRecentsToHome(true /* animateTaskViews */);
@@ -793,21 +805,6 @@
mIgnoreAltTabRelease = true;
}
- public final void onBusEvent(ShowHistoryEvent event) {
- if (mHistoryView == null) {
- mHistoryView = (RecentsHistoryView) mHistoryViewStub.inflate();
- // Since this history view is inflated by a view stub after the insets have already
- // been applied, we have to set them ourselves initial from the insets that were last
- // provided.
- mHistoryView.setSystemInsets(mRecentsView.getSystemInsets());
- }
- mHistoryView.show(mRecentsView.getTaskStack(), event.getAnimationTrigger());
- }
-
- public final void onBusEvent(HideHistoryEvent event) {
- mHistoryView.hide(event.animate, event.getAnimationTrigger());
- }
-
private void refreshSearchWidgetView() {
if (mSearchWidgetInfo != null) {
SystemServicesProxy ssp = Recents.getSystemServices();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
index af3eeb0..bacf3bd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
@@ -21,7 +21,7 @@
/**
* This is sent when the history view will be closed.
*/
-public class HideHistoryEvent extends EventBus.AnimatedEvent {
+public class HideHistoryEvent extends EventBus.Event {
public final boolean animate;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryButtonEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryButtonEvent.java
index 7042537..ae803ea 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryButtonEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryButtonEvent.java
@@ -22,5 +22,11 @@
* This is sent when the history view button should be shown.
*/
public class ShowHistoryButtonEvent extends EventBus.Event {
- // Simple event
+
+ // Whether or not to translate the history button when showing it
+ public final boolean translate;
+
+ public ShowHistoryButtonEvent(boolean translate) {
+ this.translate = translate;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
index b39d645..469f336 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
@@ -21,7 +21,7 @@
/**
* This is sent when the history view button is clicked.
*/
-public class ShowHistoryEvent extends EventBus.AnimatedEvent {
+public class ShowHistoryEvent extends EventBus.Event {
// Simple event
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleHistoryEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleHistoryEvent.java
new file mode 100644
index 0000000..aaf77af
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleHistoryEvent.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package com.android.systemui.recents.events.activity;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when the history view button is clicked.
+ */
+public class ToggleHistoryEvent extends EventBus.AnimatedEvent {
+
+ // Simple event
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java
new file mode 100644
index 0000000..863f40b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package com.android.systemui.recents.events.ui;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent to reset the background scrim back to the initial state.
+ */
+public class ResetBackgroundScrimEvent extends EventBus.Event {
+ // Simple event
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java
new file mode 100644
index 0000000..fdd4c67
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package com.android.systemui.recents.events.ui;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent to request an update to the background scrim.
+ */
+public class UpdateBackgroundScrimEvent extends EventBus.Event {
+
+ public final float alpha;
+
+ public UpdateBackgroundScrimEvent(float alpha) {
+ this.alpha = alpha;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
index f6655c7..2c28c29 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
@@ -26,7 +26,9 @@
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.events.EventBus;
@@ -132,7 +134,7 @@
ssp.startActivityFromRecents(v.getContext(), task.key.id, task.title,
ActivityOptions.makeBasic());
- MetricsLogger.action(v.getContext(), MetricsLogger.ACTION_OVERVIEW_SELECT,
+ MetricsLogger.action(v.getContext(), MetricsEvent.ACTION_OVERVIEW_SELECT,
task.key.getComponent().toString());
}
@@ -164,14 +166,16 @@
final List<Task> tasksMostRecent = new ArrayList<>(stack.getHistoricalTasks());
Collections.reverse(tasksMostRecent);
int prevDateKey = -1;
+ int taskCount = tasksMostRecent.size();
mRows.clear();
mTaskRowCount.clear();
- for (Task task : tasksMostRecent) {
+ Calendar cal = Calendar.getInstance(l);
+ for (int i = 0; i < taskCount; i++) {
+ Task task = tasksMostRecent.get(i);
if (task.isFreeformTask()) {
continue;
}
- Calendar cal = Calendar.getInstance(l);
cal.setTimeInMillis(task.key.lastActiveTime);
int dateKey = Objects.hash(cal.get(Calendar.YEAR), cal.get(Calendar.DAY_OF_YEAR));
if (dateKey != prevDateKey) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
index 39bb6ca..6dd4b53 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
@@ -16,6 +16,7 @@
package com.android.systemui.recents.history;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
@@ -28,29 +29,38 @@
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivity;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.PackagesChangedEvent;
+import com.android.systemui.recents.events.ui.ResetBackgroundScrimEvent;
+import com.android.systemui.recents.events.ui.UpdateBackgroundScrimEvent;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.views.AnimateableViewBounds;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
/**
* A list of the recent tasks that are not in the stack.
*/
-public class RecentsHistoryView extends LinearLayout {
+public class RecentsHistoryView extends LinearLayout
+ implements ValueAnimator.AnimatorUpdateListener {
- private static final String TAG = "RecentsHistoryView";
- private static final boolean DEBUG = false;
+ private static final float TRANSLATION_Y_PCT = 0.25f;
+ private static final float BG_SCRIM_ALPHA = 0.625f;
private RecyclerView mRecyclerView;
private RecentsHistoryAdapter mAdapter;
private RecentsHistoryItemTouchCallbacks mItemTouchHandler;
+ private AnimateableViewBounds mViewBounds;
private boolean mIsVisible;
private Rect mSystemInsets = new Rect();
+ private int mHeaderHeight;
private Interpolator mFastOutSlowInInterpolator;
private Interpolator mFastOutLinearInInterpolator;
@@ -79,68 +89,74 @@
com.android.internal.R.interpolator.fast_out_slow_in);
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_linear_in);
+ mViewBounds = new AnimateableViewBounds(this, 0);
+ setOutlineProvider(mViewBounds);
}
/**
* Updates this history view with the recent tasks, and then shows it.
*/
- public void show(TaskStack stack, ReferenceCountedTrigger postHideAnimationTrigger) {
+ public void show(TaskStack stack, int stackHeight) {
setVisibility(View.VISIBLE);
setAlpha(0f);
- postHideAnimationTrigger.addLastDecrementRunnable(new Runnable() {
- @Override
- public void run() {
- animate()
- .alpha(1f)
- .setDuration(mHistoryTransitionDuration)
- .setInterpolator(mFastOutSlowInInterpolator)
- .withLayer()
- .start();
- }
- });
+ setTranslationY(-stackHeight * TRANSLATION_Y_PCT);
+ animate()
+ .alpha(1f)
+ .translationY(0f)
+ .setDuration(mHistoryTransitionDuration)
+ .setInterpolator(mFastOutSlowInInterpolator)
+ .setUpdateListener(this)
+ .withLayer()
+ .start();
mAdapter.updateTasks(getContext(), stack);
mIsVisible = true;
+ EventBus.getDefault().send(new UpdateBackgroundScrimEvent(BG_SCRIM_ALPHA));
- MetricsLogger.visible(mRecyclerView.getContext(), MetricsLogger.OVERVIEW_HISTORY);
+ MetricsLogger.visible(mRecyclerView.getContext(), MetricsEvent.OVERVIEW_HISTORY);
}
/**
* Hides this history view.
*/
- public void hide(boolean animate, final ReferenceCountedTrigger postAnimationTrigger) {
+ public void hide(boolean animate, int stackHeight) {
if (animate) {
animate()
.alpha(0f)
+ .translationY(-stackHeight * TRANSLATION_Y_PCT)
.setDuration(mHistoryTransitionDuration)
.setInterpolator(mFastOutLinearInInterpolator)
+ .setUpdateListener(this)
.withEndAction(new Runnable() {
@Override
public void run() {
setVisibility(View.INVISIBLE);
- if (postAnimationTrigger != null) {
- postAnimationTrigger.decrement();
- }
}
})
.withLayer()
.start();
- if (postAnimationTrigger != null) {
- postAnimationTrigger.increment();
- }
} else {
setAlpha(0f);
setVisibility(View.INVISIBLE);
}
mIsVisible = false;
+ EventBus.getDefault().send(new ResetBackgroundScrimEvent());
- MetricsLogger.hidden(mRecyclerView.getContext(), MetricsLogger.OVERVIEW_HISTORY);
+ MetricsLogger.hidden(mRecyclerView.getContext(), MetricsEvent.OVERVIEW_HISTORY);
}
/**
* Updates the system insets of this history view to the provided values.
*/
public void setSystemInsets(Rect systemInsets) {
- mSystemInsets.set(systemInsets.left, systemInsets.top, systemInsets.right, systemInsets.bottom);
+ mSystemInsets.set(systemInsets);
+ requestLayout();
+ }
+
+ /**
+ * Updates the header height to account for the history button bar.
+ */
+ public void setHeaderHeight(int height) {
+ mHeaderHeight = height;
requestLayout();
}
@@ -175,7 +191,7 @@
int stackHeightPadding = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_stack_top_padding);
mRecyclerView.setPadding(stackWidthPadding + mSystemInsets.left,
- stackHeightPadding + mSystemInsets.top,
+ stackHeightPadding + mSystemInsets.top + mHeaderHeight,
stackWidthPadding + mSystemInsets.right, mSystemInsets.bottom);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -199,6 +215,13 @@
return insets;
}
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ // Clip the top of the view by the header bar height
+ int top = Math.max(0, (int) -getTranslationY()) + mSystemInsets.top + mHeaderHeight;
+ mViewBounds.setClipTop(top);
+ }
+
/**** EventBus Events ****/
public final void onBusEvent(PackagesChangedEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index d15828a..3029acf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -37,6 +37,7 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Formatter;
import java.util.List;
@@ -130,6 +131,7 @@
SparseIntArray affiliatedTaskCounts = new SparseIntArray();
String dismissDescFormat = mContext.getString(
R.string.accessibility_recents_item_will_be_dismissed);
+ Formatter dismissDescFormatter = new Formatter();
long lastStackActiveTime = Prefs.getLong(mContext,
Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, 0);
if (RecentsDebugFlags.Static.EnableMockTasks) {
@@ -168,7 +170,8 @@
// Load the title, icon, and color
String title = loader.getAndUpdateActivityTitle(taskKey, t.taskDescription);
String contentDescription = loader.getAndUpdateContentDescription(taskKey, res);
- String dismissDescription = String.format(dismissDescFormat, contentDescription);
+ String dismissDescription = dismissDescFormatter.format(dismissDescFormat,
+ contentDescription).toString();
Drawable icon = isStackTask
? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false)
: null;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
index 5a72897..5842095 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
@@ -48,10 +48,16 @@
@Override
public void getOutline(View view, Outline outline) {
outline.setAlpha(mMinAlpha + mAlpha / (1f - mMinAlpha));
- outline.setRoundRect(mClipRect.left, mClipRect.top,
- mSourceView.getWidth() - mClipRect.right,
- mSourceView.getHeight() - mClipRect.bottom,
- mCornerRadius);
+ if (mCornerRadius > 0) {
+ outline.setRoundRect(mClipRect.left, mClipRect.top,
+ mSourceView.getWidth() - mClipRect.right,
+ mSourceView.getHeight() - mClipRect.bottom,
+ mCornerRadius);
+ } else {
+ outline.setRect(mClipRect.left, mClipRect.top,
+ mSourceView.getWidth() - mClipRect.right,
+ mSourceView.getHeight() - mClipRect.bottom);
+ }
}
/** Sets the view outline alpha. */
@@ -63,6 +69,17 @@
}
}
+ /** Sets the top clip. */
+ public void setClipTop(int top) {
+ mClipRect.top = top;
+ updateClipBounds();
+ }
+
+ /** Returns the top clip. */
+ public int getClipTop() {
+ return mClipRect.top;
+ }
+
/** Sets the bottom clip. */
public void setClipBottom(int bottom) {
mClipRect.bottom = bottom;
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 e448101..41739c4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -18,9 +18,13 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Outline;
import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.ArraySet;
@@ -28,13 +32,17 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewOutlineProvider;
import android.view.ViewPropertyAnimator;
+import android.view.ViewStub;
import android.view.WindowInsets;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.TextView;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivity;
@@ -43,20 +51,24 @@
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
+import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
import com.android.systemui.recents.events.activity.HideHistoryButtonEvent;
import com.android.systemui.recents.events.activity.HideHistoryEvent;
import com.android.systemui.recents.events.activity.LaunchTaskEvent;
import com.android.systemui.recents.events.activity.ShowHistoryButtonEvent;
import com.android.systemui.recents.events.activity.ShowHistoryEvent;
import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
+import com.android.systemui.recents.events.activity.ToggleHistoryEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
+import com.android.systemui.recents.events.ui.ResetBackgroundScrimEvent;
+import com.android.systemui.recents.events.ui.UpdateBackgroundScrimEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
+import com.android.systemui.recents.history.RecentsHistoryView;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
@@ -78,6 +90,8 @@
public class RecentsView extends FrameLayout {
private static final int DOCK_AREA_OVERLAY_TRANSITION_DURATION = 135;
+ private static final int DEFAULT_UPDATE_SCRIM_DURATION = 200;
+ private static final float DEFAULT_SCRIM_ALPHA = 0.33f;
private final Handler mHandler;
@@ -86,11 +100,16 @@
private RecentsAppWidgetHostView mSearchBar;
private TextView mHistoryButton;
private View mEmptyView;
+ private RecentsHistoryView mHistoryView;
+
private boolean mAwaitingFirstLayout = true;
private boolean mLastTaskLaunchedWasFreeform;
private Rect mSystemInsets = new Rect();
private int mDividerSize;
+ private ColorDrawable mBackgroundScrim = new ColorDrawable(Color.BLACK);
+ private Animator mBackgroundScrimAnimator;
+
private RecentsTransitionHelper mTransitionHelper;
private RecentsViewTouchHandler mTouchHandler;
@@ -125,17 +144,28 @@
mTouchHandler = new RecentsViewTouchHandler(this);
mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f);
+ final float cornerRadius = context.getResources().getDimensionPixelSize(
+ R.dimen.recents_task_view_rounded_corners_radius);
LayoutInflater inflater = LayoutInflater.from(context);
mHistoryButton = (TextView) inflater.inflate(R.layout.recents_history_button, this, false);
mHistoryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- EventBus.getDefault().send(new ShowHistoryEvent());
+ EventBus.getDefault().send(new ToggleHistoryEvent());
+ }
+ });
+ mHistoryButton.setClipToOutline(true);
+ mHistoryButton.setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), cornerRadius);
}
});
addView(mHistoryButton);
mEmptyView = inflater.inflate(R.layout.recents_empty, this, false);
addView(mEmptyView);
+
+ setBackground(mBackgroundScrim);
}
/** Set/get the bsp root node */
@@ -160,6 +190,15 @@
addView(mTaskStackView);
}
+ // If we are already occluded by the app, then just set the default background scrim now.
+ // Otherwise, defer until the enter animation completes to animate the scrim with the
+ // tasks for the home animation.
+ if (launchState.launchedFromAppWithThumbnail || mStack.getTaskCount() == 0) {
+ mBackgroundScrim.setAlpha((int) (DEFAULT_SCRIM_ALPHA * 255));
+ } else {
+ mBackgroundScrim.setAlpha(0);
+ }
+
// Update the top level view's visibilities
if (stack.getTaskCount() > 0) {
hideEmptyView();
@@ -179,6 +218,13 @@
}
/**
+ * Returns whether the history is visible or not.
+ */
+ public boolean isHistoryVisible() {
+ return mHistoryView != null && mHistoryView.isVisible();
+ }
+
+ /**
* Returns the currently set task stack.
*/
public TaskStack getTaskStack() {
@@ -302,13 +348,6 @@
mHistoryButton.bringToFront();
}
- /**
- * Returns the last known system insets.
- */
- public Rect getSystemInsets() {
- return mSystemInsets;
- }
-
@Override
protected void onAttachedToWindow() {
EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
@@ -350,17 +389,23 @@
mTaskStackView.measure(widthMeasureSpec, heightMeasureSpec);
}
- // Measure the empty view
- measureChild(mEmptyView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+ // Measure the empty view to the full size of the screen
+ if (mEmptyView.getVisibility() != GONE) {
+ measureChild(mEmptyView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+ }
- // Measure the history button with the full space above the stack, but width-constrained
- // to the stack
+ // Measure the history view
+ if (mHistoryView != null && mHistoryView.getVisibility() != GONE) {
+ measureChild(mHistoryView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+ }
+
+ // Measure the history button within the constraints of the space above the stack
Rect historyButtonRect = mTaskStackView.mLayoutAlgorithm.mHistoryButtonRect;
measureChild(mHistoryButton,
- MeasureSpec.makeMeasureSpec(historyButtonRect.width(), MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(historyButtonRect.height(),
- MeasureSpec.EXACTLY));
+ MeasureSpec.makeMeasureSpec(historyButtonRect.width(), MeasureSpec.AT_MOST),
+ MeasureSpec.makeMeasureSpec(historyButtonRect.height(), MeasureSpec.AT_MOST));
setMeasuredDimension(width, height);
}
@@ -387,13 +432,24 @@
}
// Layout the empty view
- mEmptyView.layout(left, top, right, bottom);
+ if (mEmptyView.getVisibility() != GONE) {
+ mEmptyView.layout(left, top, right, bottom);
+ }
- // Layout the history button left-aligned with the stack, but offset from the top of the
- // view
+ // Layout the history view
+ if (mHistoryView != null && mHistoryView.getVisibility() != GONE) {
+ mHistoryView.layout(left, top, right, bottom);
+ }
+
+ // Layout the history button such that its drawable is left-aligned with the stack,
+ // vertically centered in the available space above the stack
Rect historyButtonRect = mTaskStackView.mLayoutAlgorithm.mHistoryButtonRect;
- mHistoryButton.layout(historyButtonRect.left, historyButtonRect.top,
- historyButtonRect.right, historyButtonRect.bottom);
+ int historyLeft = historyButtonRect.left - mHistoryButton.getPaddingStart();
+ int historyTop = historyButtonRect.top +
+ (historyButtonRect.height() - mHistoryButton.getMeasuredHeight()) / 2;
+ mHistoryButton.layout(historyLeft, historyTop,
+ historyLeft + mHistoryButton.getMeasuredWidth(),
+ historyTop + mHistoryButton.getMeasuredHeight());
if (mAwaitingFirstLayout) {
mAwaitingFirstLayout = false;
@@ -462,10 +518,8 @@
// Hide the history button
int taskViewExitToHomeDuration = getResources().getInteger(
R.integer.recents_task_exit_to_home_duration);
- hideHistoryButton(taskViewExitToHomeDuration);
-
- // If we are going home, cancel the previous task's window transition
- EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(null));
+ hideHistoryButton(taskViewExitToHomeDuration, false /* translate */);
+ animateBackgroundScrim(0f, taskViewExitToHomeDuration);
}
public final void onBusEvent(DragStartEvent event) {
@@ -537,8 +591,7 @@
}
}));
- MetricsLogger.action(mContext,
- MetricsLogger.ACTION_WINDOW_DOCK_DRAG_DROP);
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_DRAG_DROP);
} else {
// Animate the overlay alpha back to 0
updateVisibleDockRegions(null, true /* isDefaultDockState */, -1,
@@ -571,57 +624,127 @@
animator.start();
}
- public final void onBusEvent(ShowHistoryEvent event) {
- // Hide the history button when the history view is shown
- hideHistoryButton(getResources().getInteger(R.integer.recents_history_transition_duration),
- event.getAnimationTrigger());
- event.addPostAnimationCallback(new Runnable() {
- @Override
- public void run() {
- setAlpha(0f);
- }
- });
- }
-
- public final void onBusEvent(HideHistoryEvent event) {
- // Show the history button when the history view is hidden
- setAlpha(1f);
- showHistoryButton(getResources().getInteger(R.integer.recents_history_transition_duration),
- event.getAnimationTrigger());
- }
-
- public final void onBusEvent(ShowHistoryButtonEvent event) {
- showHistoryButton(150);
- }
-
- public final void onBusEvent(HideHistoryButtonEvent event) {
- hideHistoryButton(100);
- }
-
public final void onBusEvent(TaskStackUpdatedEvent event) {
mStack.setTasks(event.stack.computeAllTasksList(), true /* notifyStackChanges */);
mStack.createAffiliatedGroupings(getContext());
}
+ public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
+ RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+ if (!launchState.launchedFromAppWithThumbnail && mStack.getTaskCount() > 0) {
+ int taskViewEnterFromHomeDuration = getResources().getInteger(
+ R.integer.recents_task_enter_from_home_duration);
+ animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, taskViewEnterFromHomeDuration);
+ }
+ }
+
+ public final void onBusEvent(UpdateBackgroundScrimEvent event) {
+ animateBackgroundScrim(event.alpha, DEFAULT_UPDATE_SCRIM_DURATION);
+ }
+
+ public final void onBusEvent(ResetBackgroundScrimEvent event) {
+ animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION);
+ }
+
+ public final void onBusEvent(RecentsVisibilityChangedEvent event) {
+ if (!event.visible) {
+ // Reset the view state
+ mAwaitingFirstLayout = true;
+ mLastTaskLaunchedWasFreeform = false;
+ hideHistoryButton(0, false /* translate */);
+ }
+ }
+
+ public final void onBusEvent(ToggleHistoryEvent event) {
+ if (mHistoryView != null && mHistoryView.isVisible()) {
+ EventBus.getDefault().send(new HideHistoryEvent(true /* animate */));
+ } else {
+ EventBus.getDefault().send(new ShowHistoryEvent());
+ }
+ }
+
+ public final void onBusEvent(ShowHistoryEvent event) {
+ if (mHistoryView == null) {
+ mHistoryView = (RecentsHistoryView) LayoutInflater.from(getContext()).inflate(
+ R.layout.recents_history, this, false);
+ addView(mHistoryView);
+
+ // Since this history view is inflated by a view stub after the insets have already
+ // been applied, we have to set them ourselves initial from the insets that were last
+ // provided.
+ mHistoryView.setSystemInsets(mSystemInsets);
+ mHistoryView.setHeaderHeight(mHistoryButton.getMeasuredHeight());
+ mHistoryButton.bringToFront();
+ }
+
+ // Animate the empty view in parallel with the history view (the task view animations are
+ // handled in TaskStackView)
+ Rect stackRect = mTaskStackView.mLayoutAlgorithm.mStackRect;
+ if (mEmptyView.getVisibility() == View.VISIBLE) {
+ int historyTransitionDuration = getResources().getInteger(
+ R.integer.recents_history_transition_duration);
+ mEmptyView.animate()
+ .alpha(0f)
+ .translationY(stackRect.bottom)
+ .setDuration(historyTransitionDuration)
+ .setInterpolator(mFastOutSlowInInterpolator)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mEmptyView.setVisibility(View.INVISIBLE);
+ }
+ })
+ .start();
+ }
+
+ mHistoryView.show(mStack, stackRect.height());
+ }
+
+ public final void onBusEvent(HideHistoryEvent event) {
+ // Animate the empty view in parallel with the history view (the task view animations are
+ // handled in TaskStackView)
+ Rect stackRect = mTaskStackView.mLayoutAlgorithm.mStackRect;
+ if (mStack.getTaskCount() == 0) {
+ int historyTransitionDuration = getResources().getInteger(
+ R.integer.recents_history_transition_duration);
+ mEmptyView.setVisibility(View.VISIBLE);
+ mEmptyView.animate()
+ .alpha(1f)
+ .translationY(0)
+ .setDuration(historyTransitionDuration)
+ .setInterpolator(mFastOutSlowInInterpolator)
+ .start();
+ }
+
+ mHistoryView.hide(event.animate, stackRect.height());
+ }
+
+ public final void onBusEvent(ShowHistoryButtonEvent event) {
+ showHistoryButton(150, event.translate);
+ }
+
+ public final void onBusEvent(HideHistoryButtonEvent event) {
+ hideHistoryButton(100, true /* translate */);
+ }
+
/**
* Shows the history button.
*/
- private void showHistoryButton(final int duration) {
- ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
- showHistoryButton(duration, postAnimationTrigger);
- postAnimationTrigger.flushLastDecrementRunnables();
- }
-
- private void showHistoryButton(final int duration,
- final ReferenceCountedTrigger postHideHistoryAnimationTrigger) {
- mHistoryButton.setText(getContext().getString(R.string.recents_history_label_format,
- mStack.getHistoricalTasks().size()));
+ private void showHistoryButton(final int duration, final boolean translate) {
+ final ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
if (mHistoryButton.getVisibility() == View.INVISIBLE) {
mHistoryButton.setVisibility(View.VISIBLE);
mHistoryButton.setAlpha(0f);
- postHideHistoryAnimationTrigger.addLastDecrementRunnable(new Runnable() {
+ if (translate) {
+ mHistoryButton.setTranslationY(-mHistoryButton.getMeasuredHeight() * 0.25f);
+ }
+ postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
@Override
public void run() {
+ if (translate) {
+ mHistoryButton.animate()
+ .translationY(0f);
+ }
mHistoryButton.animate()
.alpha(1f)
.setDuration(duration)
@@ -631,34 +754,42 @@
}
});
}
+ postAnimationTrigger.flushLastDecrementRunnables();
}
/**
* Hides the history button.
*/
- private void hideHistoryButton(int duration) {
- ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
- hideHistoryButton(duration, postAnimationTrigger);
+ private void hideHistoryButton(int duration, boolean translate) {
+ final ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
+ hideHistoryButton(duration, translate, postAnimationTrigger);
postAnimationTrigger.flushLastDecrementRunnables();
}
- private void hideHistoryButton(int duration,
- final ReferenceCountedTrigger postHideStackAnimationTrigger) {
+ /**
+ * Hides the history button.
+ */
+ private void hideHistoryButton(int duration, boolean translate,
+ final ReferenceCountedTrigger postAnimationTrigger) {
if (mHistoryButton.getVisibility() == View.VISIBLE) {
+ if (translate) {
+ mHistoryButton.animate()
+ .translationY(-mHistoryButton.getMeasuredHeight() * 0.25f);
+ }
mHistoryButton.animate()
.alpha(0f)
.setDuration(duration)
- .setInterpolator(mFastOutLinearInInterpolator)
+ .setInterpolator(mFastOutSlowInInterpolator)
.withEndAction(new Runnable() {
@Override
public void run() {
mHistoryButton.setVisibility(View.INVISIBLE);
- postHideStackAnimationTrigger.decrement();
+ postAnimationTrigger.decrement();
}
})
.withLayer()
.start();
- postHideStackAnimationTrigger.increment();
+ postAnimationTrigger.increment();
}
}
@@ -695,11 +826,18 @@
}
}
- public final void onBusEvent(RecentsVisibilityChangedEvent event) {
- if (!event.visible) {
- // Reset the view state
- mAwaitingFirstLayout = true;
- mLastTaskLaunchedWasFreeform = false;
- }
+ /**
+ * Animates the background scrim to the given {@param alpha}.
+ */
+ private void animateBackgroundScrim(float alpha, int duration) {
+ Utilities.cancelAnimationWithoutCallbacks(mBackgroundScrimAnimator);
+ int alphaInt = (int) (alpha * 255);
+ mBackgroundScrimAnimator = ObjectAnimator.ofInt(mBackgroundScrim, Utilities.DRAWABLE_ALPHA,
+ mBackgroundScrim.getAlpha(), alphaInt);
+ mBackgroundScrimAnimator.setDuration(duration);
+ mBackgroundScrimAnimator.setInterpolator(alphaInt > mBackgroundScrim.getAlpha()
+ ? PhoneStatusBar.ALPHA_OUT
+ : PhoneStatusBar.ALPHA_IN);
+ mBackgroundScrimAnimator.start();
}
}
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 9618f212d..2254dfc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -30,12 +30,9 @@
Context mContext;
- View mStatusBarScrimView;
View mNavBarScrimView;
boolean mHasNavBarScrim;
- boolean mShouldAnimateStatusBarScrim;
- boolean mHasStatusBarScrim;
boolean mShouldAnimateNavBarScrim;
int mNavBarScrimEnterDuration;
@@ -45,7 +42,6 @@
public SystemBarScrimViews(Activity activity) {
mContext = activity;
- mStatusBarScrimView = activity.findViewById(R.id.status_bar_scrim);
mNavBarScrimView = activity.findViewById(R.id.nav_bar_scrim);
mNavBarScrimEnterDuration = activity.getResources().getInteger(
R.integer.recents_nav_bar_scrim_enter_duration);
@@ -59,17 +55,12 @@
* Prepares the scrim views for animating when entering Recents. This will be called before
* the first draw.
*/
- public void prepareEnterRecentsAnimation(boolean hasStatusBarScrim, boolean animateStatusBarScrim,
- boolean hasNavBarScrim, boolean animateNavBarScrim) {
- mHasNavBarScrim = hasStatusBarScrim;
- mShouldAnimateStatusBarScrim = animateStatusBarScrim;
- mHasStatusBarScrim = hasNavBarScrim;
+ public void prepareEnterRecentsAnimation(boolean hasNavBarScrim, boolean animateNavBarScrim) {
+ mHasNavBarScrim = hasNavBarScrim;
mShouldAnimateNavBarScrim = animateNavBarScrim;
mNavBarScrimView.setVisibility(mHasNavBarScrim && !mShouldAnimateNavBarScrim ?
View.VISIBLE : View.INVISIBLE);
- mStatusBarScrimView.setVisibility(mHasStatusBarScrim && !mShouldAnimateStatusBarScrim ?
- View.VISIBLE : View.INVISIBLE);
}
/**** EventBus events ****/
@@ -78,20 +69,6 @@
* Starts animating the scrim views when entering Recents.
*/
public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
- if (mHasStatusBarScrim && mShouldAnimateStatusBarScrim) {
- mStatusBarScrimView.setTranslationY(-mStatusBarScrimView.getMeasuredHeight());
- mStatusBarScrimView.animate()
- .translationY(0)
- .setDuration(mNavBarScrimEnterDuration)
- .setInterpolator(mQuintOutInterpolator)
- .withStartAction(new Runnable() {
- @Override
- public void run() {
- mStatusBarScrimView.setVisibility(View.VISIBLE);
- }
- })
- .start();
- }
if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
mNavBarScrimView.animate()
@@ -115,14 +92,6 @@
public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
int taskViewExitToAppDuration = mContext.getResources().getInteger(
R.integer.recents_task_exit_to_app_duration);
- if (mHasStatusBarScrim && mShouldAnimateStatusBarScrim) {
- mStatusBarScrimView.animate()
- .translationY(-mStatusBarScrimView.getMeasuredHeight())
- .setStartDelay(0)
- .setDuration(taskViewExitToAppDuration)
- .setInterpolator(mFastOutSlowInInterpolator)
- .start();
- }
if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
mNavBarScrimView.animate()
.translationY(mNavBarScrimView.getMeasuredHeight())
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 ccbb329..d550d83 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -138,7 +138,7 @@
} else if (launchState.launchedFromHome) {
// Move the task view off screen (below) so we can animate it in
RectF bounds = new RectF(mTmpTransform.rect);
- bounds.offset(0, offscreenY);
+ bounds.offsetTo(bounds.left, offscreenY);
tv.setLeftTopRightBottom((int) bounds.left, (int) bounds.top, (int) bounds.right,
(int) bounds.bottom);
}
@@ -259,7 +259,7 @@
stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
null);
- mTmpTransform.rect.offset(0, offscreenY);
+ mTmpTransform.rect.offsetTo(mTmpTransform.rect.left, offscreenY);
mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
}
}
@@ -346,61 +346,58 @@
}
/**
- * Starts the animation to hide the {@link TaskView}s when the history is shown. The history
- * view's animation will be deferred until all the {@link TaskView}s are finished animating.
+ * Starts the animation to hide the {@link TaskView}s when the history is shown.
*/
public void startShowHistoryAnimation(ReferenceCountedTrigger postAnimationTrigger) {
Resources res = mStackView.getResources();
TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
TaskStackViewScroller stackScroller = mStackView.getScroller();
+ int offscreenY = stackLayout.mStackRect.bottom;
int historyTransitionDuration = res.getInteger(
R.integer.recents_history_transition_duration);
+ int startDelayIncr = 16;
List<TaskView> taskViews = mStackView.getTaskViews();
int taskViewCount = taskViews.size();
for (int i = taskViewCount - 1; i >= 0; i--) {
TaskView tv = taskViews.get(i);
Task task = tv.getTask();
- TaskViewAnimation taskAnimation = new TaskViewAnimation(
- historyTransitionDuration, PhoneStatusBar.ALPHA_OUT,
+ TaskViewAnimation taskAnimation = new TaskViewAnimation(startDelayIncr * i,
+ historyTransitionDuration, mFastOutSlowInInterpolator,
postAnimationTrigger.decrementOnAnimationEnd());
postAnimationTrigger.increment();
stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
null);
mTmpTransform.alpha = 0f;
+ mTmpTransform.rect.offsetTo(mTmpTransform.rect.left, offscreenY);
mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
}
}
/**
- * Starts the animation to show the {@link TaskView}s when the history is hidden. The
- * {@link TaskView} animations will be deferred until the history view has been animated away.
+ * Starts the animation to show the {@link TaskView}s when the history is hidden.
*/
- public void startHideHistoryAnimation(final ReferenceCountedTrigger postAnimationTrigger) {
- final Resources res = mStackView.getResources();
- final TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
- final TaskStackViewScroller stackScroller = mStackView.getScroller();
+ public void startHideHistoryAnimation() {
+ Resources res = mStackView.getResources();
+ TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
+ TaskStackViewScroller stackScroller = mStackView.getScroller();
- final int historyTransitionDuration = res.getInteger(
+ int historyTransitionDuration = res.getInteger(
R.integer.recents_history_transition_duration);
+ int startDelayIncr = 16;
List<TaskView> taskViews = mStackView.getTaskViews();
int taskViewCount = taskViews.size();
for (int i = taskViewCount - 1; i >= 0; i--) {
- final TaskView tv = taskViews.get(i);
- postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
- @Override
- public void run() {
- TaskViewAnimation taskAnimation = new TaskViewAnimation(
- historyTransitionDuration, PhoneStatusBar.ALPHA_IN);
- stackLayout.getStackTransform(tv.getTask(), stackScroller.getStackScroll(),
- mTmpTransform, null);
- mTmpTransform.alpha = 1f;
- mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
- }
- });
+ TaskView tv = taskViews.get(i);
+ TaskViewAnimation taskAnimation = new TaskViewAnimation(startDelayIncr * i,
+ historyTransitionDuration, mFastOutSlowInInterpolator);
+ stackLayout.getStackTransform(tv.getTask(), stackScroller.getStackScroll(),
+ mTmpTransform, null);
+ mTmpTransform.alpha = 1f;
+ mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
}
}
}
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 93849dc..bb37c04 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -354,6 +354,7 @@
mStackBottomOffset = mSystemInsets.bottom + heightPadding;
state.computeRects(mFreeformRect, mStackRect, taskStackBounds, widthPadding, heightPadding,
mStackBottomOffset);
+ // The history button will take the full un-padded header space above the stack
mHistoryButtonRect.set(mStackRect.left, mStackRect.top - heightPadding,
mStackRect.right, mStackRect.top + mFocusedPeekHeight);
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 7423b78..1c545c8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -64,6 +64,7 @@
import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
+import com.android.systemui.recents.events.ui.UpdateBackgroundScrimEvent;
import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
import com.android.systemui.recents.events.ui.UserInteractionEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
@@ -74,11 +75,13 @@
import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
import com.android.systemui.recents.misc.DozeTrigger;
+import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
+import java.lang.ref.Reference;
import java.util.ArrayList;
import java.util.List;
@@ -1117,12 +1120,19 @@
// We can get spurious measure passes with the old bounds when docking, and since we are
// using the current stack bounds during drag and drop, don't overwrite them until we
// actually get new bounds
+ boolean requiresLayout = false;
if (!taskStackBounds.equals(mStableStackBounds)) {
mStableStackBounds.set(taskStackBounds);
mStackBounds.set(taskStackBounds);
+ requiresLayout = true;
}
- mLayoutAlgorithm.setSystemInsets(systemInsets);
- requestLayout();
+ if (!systemInsets.equals(mLayoutAlgorithm.mSystemInsets)) {
+ mLayoutAlgorithm.setSystemInsets(systemInsets);
+ requiresLayout = true;
+ }
+ if (requiresLayout) {
+ requestLayout();
+ }
}
/**
@@ -1235,7 +1245,7 @@
// Update the history button visibility
if (shouldShowHistoryButton() &&
mStackScroller.getStackScroll() < SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
- EventBus.getDefault().send(new ShowHistoryButtonEvent());
+ EventBus.getDefault().send(new ShowHistoryButtonEvent(false /* translate */));
} else {
EventBus.getDefault().send(new HideHistoryButtonEvent());
}
@@ -1468,13 +1478,15 @@
relayoutTaskViewsOnNextFrame(animation);
}
- if (shouldShowHistoryButton() &&
- prevScroll > SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD &&
- curScroll <= SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
- EventBus.getDefault().send(new ShowHistoryButtonEvent());
- } else if (prevScroll < HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD &&
- curScroll >= HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD) {
- EventBus.getDefault().send(new HideHistoryButtonEvent());
+ if (mEnterAnimationComplete) {
+ if (shouldShowHistoryButton() &&
+ prevScroll > SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD &&
+ curScroll <= SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
+ EventBus.getDefault().send(new ShowHistoryButtonEvent(true /* translate */));
+ } else if (prevScroll < HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD &&
+ curScroll >= HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD) {
+ EventBus.getDefault().send(new HideHistoryButtonEvent());
+ }
}
}
@@ -1753,11 +1765,19 @@
}
public final void onBusEvent(ShowHistoryEvent event) {
- mAnimationHelper.startShowHistoryAnimation(event.getAnimationTrigger());
+ ReferenceCountedTrigger postAnimTrigger = new ReferenceCountedTrigger();
+ postAnimTrigger.addLastDecrementRunnable(new Runnable() {
+ @Override
+ public void run() {
+ setVisibility(View.INVISIBLE);
+ }
+ });
+ mAnimationHelper.startShowHistoryAnimation(postAnimTrigger);
}
public final void onBusEvent(HideHistoryEvent event) {
- mAnimationHelper.startHideHistoryAnimation(event.getAnimationTrigger());
+ setVisibility(View.VISIBLE);
+ mAnimationHelper.startHideHistoryAnimation();
}
/**
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 e9f6f39..7019444 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -215,8 +215,11 @@
case MotionEvent.ACTION_MOVE: {
int activePointerIndex = ev.findPointerIndex(mActivePointerId);
int y = (int) ev.getY(activePointerIndex);
+ int x = (int) ev.getX(activePointerIndex);
if (!mIsScrolling) {
- if (Math.abs(y - mDownY) > mScrollTouchSlop) {
+ int yDiff = Math.abs(y - mDownY);
+ int xDiff = Math.abs(x - mDownX);
+ if (Math.abs(y - mDownY) > mScrollTouchSlop && yDiff > xDiff) {
mIsScrolling = true;
// Disallow parents from intercepting touch events
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAnimation.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAnimation.java
index 363ad66..74b16d0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAnimation.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAnimation.java
@@ -45,6 +45,10 @@
this(0 /* startDelay */, duration, interpolator, listener);
}
+ public TaskViewAnimation(int startDelay, int duration, Interpolator interpolator) {
+ this(startDelay, duration, interpolator, null);
+ }
+
public TaskViewAnimation(int startDelay, int duration, Interpolator interpolator,
Animator.AnimatorListener listener) {
this.startDelay = startDelay;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 77c27fa..d5131be 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -31,6 +31,7 @@
import android.widget.ImageView;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import java.util.ArrayList;
@@ -205,7 +206,7 @@
if (!mAutomatic) {
final int val = value + mMinimumBacklight;
if (stopTracking) {
- MetricsLogger.action(mContext, MetricsLogger.ACTION_BRIGHTNESS, val);
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS, val);
}
setBrightness(val);
if (!tracking) {
@@ -220,7 +221,7 @@
} else {
final float adj = value / (BRIGHTNESS_ADJ_RESOLUTION / 2f) - 1;
if (stopTracking) {
- MetricsLogger.action(mContext, MetricsLogger.ACTION_BRIGHTNESS_AUTO, value);
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS_AUTO, value);
}
setBrightnessAdj(adj);
if (!tracking) {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
index cef4d34..4952234 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
@@ -25,6 +25,7 @@
import android.widget.ImageView;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
/** A dialog that provides controls for adjusting the screen brightness. */
@@ -53,13 +54,13 @@
protected void onStart() {
super.onStart();
mBrightnessController.registerCallbacks();
- MetricsLogger.visible(this, MetricsLogger.BRIGHTNESS_DIALOG);
+ MetricsLogger.visible(this, MetricsEvent.BRIGHTNESS_DIALOG);
}
@Override
protected void onStop() {
super.onStop();
- MetricsLogger.hidden(this, MetricsLogger.BRIGHTNESS_DIALOG);
+ MetricsLogger.hidden(this, MetricsEvent.BRIGHTNESS_DIALOG);
mBrightnessController.unregisterCallbacks();
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index c0e1e44..dca7fd9 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -73,8 +73,6 @@
private static final String TAG = "DividerView";
private static final int TASK_POSITION_SAME = Integer.MAX_VALUE;
- private static final float DIM_START_FRACTION = 0.5f;
- private static final float DIM_DAMP_FACTOR = 1.7f;
/**
* Fraction of the divider position between two snap targets to switch to the full-screen
@@ -90,6 +88,8 @@
private static final PathInterpolator SLOWDOWN_INTERPOLATOR =
new PathInterpolator(0.5f, 1f, 0.5f, 1f);
+ private static final PathInterpolator DIM_INTERPOLATOR =
+ new PathInterpolator(.23f, .87f, .52f, -0.11f);
private DividerHandleView mHandle;
private View mBackground;
@@ -497,8 +497,8 @@
mWindowManagerProxy.resizeDockedStack(mDockedRect, null, null, null, null);
}
float fraction = mSnapAlgorithm.calculateDismissingFraction(position);
- fraction = Math.max(0,
- Math.min((fraction / DIM_START_FRACTION - 1f) / DIM_DAMP_FACTOR, 1f));
+ fraction = Math.max(0, Math.min(fraction, 1f));
+ fraction = DIM_INTERPOLATOR.getInterpolation(fraction);
mWindowManagerProxy.setResizeDimLayer(fraction != 0f,
getStackIdForDismissTarget(mSnapAlgorithm.getClosestDismissTarget(position)),
fraction);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index efa56bc..5359dd2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -81,7 +81,9 @@
import android.widget.RemoteViews;
import android.widget.TextView;
import android.widget.Toast;
+
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.NotificationColorUtil;
@@ -947,7 +949,7 @@
final int appUidF = appUid;
settingsButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
- MetricsLogger.action(mContext, MetricsLogger.ACTION_NOTE_INFO);
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_INFO);
startAppNotificationSettingsActivity(pkg, appUidF);
}
});
@@ -994,7 +996,7 @@
return false;
}
- MetricsLogger.action(mContext, MetricsLogger.ACTION_NOTE_CONTROLS);
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_CONTROLS);
// ensure that it's layouted but not visible until actually laid out
guts.setVisibility(View.INVISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
index 4e3ecb1..dba7130 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
@@ -170,12 +170,13 @@
invalidate();
return;
}
- area.left = Math.max(area.left, 0);
- area.top = Math.max(area.top, 0);
- area.right = Math.min(area.right, getWidth());
- area.bottom = Math.min(area.bottom, getHeight());
- mExcludedRect.set(area);
- mHasExcludedArea = area.left < area.right && area.top < area.bottom;
+
+ int left = Math.max(area.left, 0);
+ int top = Math.max(area.top, 0);
+ int right = Math.min(area.right, getWidth());
+ int bottom = Math.min(area.bottom, getHeight());
+ mExcludedRect.set(left, top, right, bottom);
+ mHasExcludedArea = left < right && top < bottom;
invalidate();
}
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 92288a3..786e64d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -27,6 +27,7 @@
import android.view.ViewConfiguration;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.stackdivider.Divider;
@@ -218,8 +219,7 @@
mDivider.getView().startDragging(false /* animate */, true /* touching*/);
}
mDockWindowTouchSlopExceeded = true;
- MetricsLogger.action(mContext,
- MetricsLogger.ACTION_WINDOW_DOCK_SWIPE);
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_SWIPE);
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 7395a33..ba08ee7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -14,6 +14,7 @@
package com.android.systemui.statusbar.phone;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -37,20 +38,20 @@
public static final String NAV_BAR_VIEWS = "sysui_nav_bar";
- private static final String MENU_IME = "menu_ime";
- private static final String BACK = "back";
- private static final String HOME = "home";
- private static final String RECENT = "recent";
- private static final String NAVSPACE = "space";
+ protected static final String MENU_IME = "menu_ime";
+ protected static final String BACK = "back";
+ protected static final String HOME = "home";
+ protected static final String RECENT = "recent";
+ protected static final String NAVSPACE = "space";
public static final String GRAVITY_SEPARATOR = ";";
public static final String BUTTON_SEPARATOR = ",";
- private final LayoutInflater mLayoutInflater;
- private final LayoutInflater mLandscapeInflater;
+ protected final LayoutInflater mLayoutInflater;
+ protected final LayoutInflater mLandscapeInflater;
- private FrameLayout mRot0;
- private FrameLayout mRot90;
+ protected FrameLayout mRot0;
+ protected FrameLayout mRot90;
private SparseArray<ButtonDispatcher> mButtonDispatchers;
private String mCurrentLayout;
@@ -72,7 +73,7 @@
inflateLayout(getDefaultLayout());
}
- private String getDefaultLayout() {
+ protected String getDefaultLayout() {
return mContext.getString(R.string.config_navBarLayout);
}
@@ -128,9 +129,9 @@
}
}
- private void inflateLayout(String newLayout) {
+ protected void inflateLayout(String newLayout) {
mCurrentLayout = newLayout;
- String[] sets = newLayout.split(GRAVITY_SEPARATOR);
+ String[] sets = newLayout.split(GRAVITY_SEPARATOR, 3);
String[] start = sets[0].split(BUTTON_SEPARATOR);
String[] center = sets[1].split(BUTTON_SEPARATOR);
String[] end = sets[2].split(BUTTON_SEPARATOR);
@@ -165,6 +166,8 @@
}
private void copyToLightsout(View view, ViewGroup lightsOutParent) {
+ if (view == null) return;
+
if (view instanceof FrameLayout) {
// The only ViewGroup we support in here is a FrameLayout, so copy those manually.
FrameLayout original = (FrameLayout) view;
@@ -202,35 +205,33 @@
return new LayoutParams(layoutParams.width, layoutParams.height);
}
- private View inflateButton(String button, ViewGroup parent, boolean landscape) {
- View v = null;
+ @Nullable
+ protected View inflateButton(String button, ViewGroup parent, boolean landscape) {
+ View v;
+ LayoutInflater inflater = landscape ? mLandscapeInflater : mLayoutInflater;
if (HOME.equals(button)) {
- v = (landscape ? mLandscapeInflater : mLayoutInflater)
- .inflate(R.layout.home, parent, false);
+ v = inflater.inflate(R.layout.home, parent, false);
if (landscape && isSw600Dp()) {
setupLandButton(v);
}
} else if (BACK.equals(button)) {
- v = (landscape ? mLandscapeInflater : mLayoutInflater)
- .inflate(R.layout.back, parent, false);
+ v = inflater.inflate(R.layout.back, parent, false);
if (landscape && isSw600Dp()) {
setupLandButton(v);
}
} else if (RECENT.equals(button)) {
- v = (landscape ? mLandscapeInflater : mLayoutInflater)
- .inflate(R.layout.recent_apps, parent, false);
+ v = inflater.inflate(R.layout.recent_apps, parent, false);
if (landscape && isSw600Dp()) {
setupLandButton(v);
}
} else if (MENU_IME.equals(button)) {
- v = (landscape ? mLandscapeInflater : mLayoutInflater)
- .inflate(R.layout.menu_ime, parent, false);
+ v = inflater.inflate(R.layout.menu_ime, parent, false);
} else if (NAVSPACE.equals(button)) {
- v = (landscape ? mLandscapeInflater : mLayoutInflater)
- .inflate(R.layout.nav_key_space, parent, false);
+ v = inflater.inflate(R.layout.nav_key_space, parent, false);
} else {
- throw new IllegalArgumentException("Unknown button " + button);
+ return null;
}
+
parent.addView(v);
addToDispatchers(v);
return v;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 6fa1f5df..f2dea3c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -94,6 +94,7 @@
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.keyguard.KeyguardHostView.OnDismissAction;
@@ -752,7 +753,7 @@
mDismissView.setOnButtonClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- MetricsLogger.action(mContext, MetricsLogger.ACTION_DISMISS_ALL_NOTES);
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_DISMISS_ALL_NOTES);
clearAllNotifications();
}
});
@@ -1122,8 +1123,7 @@
ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
initialBounds);
if (docked) {
- MetricsLogger.action(mContext,
- MetricsLogger.ACTION_WINDOW_DOCK_LONGPRESS);
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS);
return true;
}
}
@@ -1138,7 +1138,7 @@
if (shouldDisableNavbarGestures()) {
return false;
}
- MetricsLogger.action(mContext, MetricsLogger.ACTION_ASSIST_LONG_PRESS);
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_ASSIST_LONG_PRESS);
mAssistManager.startAssist(new Bundle() /* args */);
awakenDreams();
if (mNavigationBarView != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
index 4f33d82..fd3c96e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
@@ -174,6 +174,7 @@
float halfW = getWidth() / 2f;
float halfH = getHeight() / 2f;
float halfSW = Math.min(halfH, halfW);
+ updateDrawableIfDisabled();
if (mBitmap != null && mScale > 0) {
int saveCount = canvas.getSaveCount();
canvas.save();
@@ -249,22 +250,25 @@
return;
}
mIsDisabled = disabled;
+ invalidate();
+ }
+
+ private void updateDrawableIfDisabled() {
int disabledColor = getContext().getColor(R.color.qs_tile_disabled_color);
PorterDuffColorFilter filter = new PorterDuffColorFilter(disabledColor,
PorterDuff.Mode.SRC_ATOP);
if (mBitmap != null) {
- if (disabled) {
+ if (mIsDisabled) {
mBitmapPaint.setColorFilter(filter);
} else {
mBitmapPaint.setColorFilter(null);
}
} else if (mDrawable != null) {
- if (disabled) {
+ if (mIsDisabled) {
mDrawable.setColorFilter(filter);
} else {
mDrawable.setColorFilter(null);
}
}
- invalidate();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index ad8e3bd..8fd4d9c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -206,7 +206,8 @@
// Show icon in QS when we are connected or need to show roaming.
boolean showDataIcon = mCurrentState.dataConnected
- || mCurrentState.iconGroup == TelephonyIcons.ROAMING;
+ || mCurrentState.iconGroup == TelephonyIcons.ROAMING
+ || mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED;
IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
getCurrentIconId(), contentDescription);
@@ -227,7 +228,8 @@
&& !mCurrentState.carrierNetworkChangeMode
&& mCurrentState.activityOut;
showDataIcon &= mCurrentState.isDefault
- || mCurrentState.iconGroup == TelephonyIcons.ROAMING;
+ || mCurrentState.iconGroup == TelephonyIcons.ROAMING
+ || mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED;
int typeIcon = showDataIcon ? icons.mDataType : 0;
mCallbackHandler.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
@@ -385,6 +387,8 @@
mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
} else if (isRoaming()) {
mCurrentState.iconGroup = TelephonyIcons.ROAMING;
+ } else if (isDataDisabled()) {
+ mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
}
if (isEmergencyOnly() != mCurrentState.isEmergency) {
mCurrentState.isEmergency = isEmergencyOnly();
@@ -399,6 +403,10 @@
notifyListenersIfNecessary();
}
+ private boolean isDataDisabled() {
+ return !mPhone.getDataEnabled(mSubscriptionInfo.getSubscriptionId());
+ }
+
@VisibleForTesting
void setActivity(int activity) {
mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 83e0446..6ff8f77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -208,6 +208,8 @@
static final int ICON_CARRIER_NETWORK_CHANGE =
R.drawable.stat_sys_signal_carrier_network_change_animation;
+ static final int ICON_DATA_DISABLED = R.drawable.stat_sys_data_disabled;
+
static final int QS_ICON_LTE = R.drawable.ic_qs_signal_lte;
static final int QS_ICON_3G = R.drawable.ic_qs_signal_3g;
static final int QS_ICON_4G = R.drawable.ic_qs_signal_4g;
@@ -215,6 +217,8 @@
static final int QS_ICON_CARRIER_NETWORK_CHANGE =
R.drawable.ic_qs_signal_carrier_network_change_animation;
+ static final int QS_ICON_DATA_DISABLED = R.drawable.ic_qs_data_disabled;
+
static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup(
"CARRIER_NETWORK_CHANGE",
TelephonyIcons.TELEPHONY_CARRIER_NETWORK_CHANGE,
@@ -373,5 +377,20 @@
false,
TelephonyIcons.QS_DATA_R
);
+
+ static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
+ "DataDisabled",
+ TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+ TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ TelephonyIcons.TELEPHONY_NO_NETWORK,
+ TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.accessibility_cell_data_off,
+ TelephonyIcons.ICON_DATA_DISABLED,
+ false,
+ TelephonyIcons.QS_ICON_DATA_DISABLED
+ );
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 05d9626..e4ded67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -49,7 +49,7 @@
import android.view.ViewGroup;
import android.widget.BaseAdapter;
-import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.util.UserIcons;
import com.android.settingslib.RestrictedLockUtils;
import com.android.systemui.BitmapHelper;
@@ -724,7 +724,7 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_USERDETAIL;
+ return MetricsEvent.QS_USERDETAIL;
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index d5b57ac..60dca99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -1649,8 +1649,8 @@
bottom = Math.min(bottom, getHeight());
}
}
- mBackgroundBounds.top = top;
- mBackgroundBounds.bottom = bottom;
+ mBackgroundBounds.top = Math.max(0, top);
+ mBackgroundBounds.bottom = Math.min(getHeight(), bottom);
}
private ActivatableNotificationView getFirstPinnedHeadsUp() {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java b/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java
index 1fd2352..3206882 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java
@@ -17,7 +17,7 @@
import android.app.ActivityManager;
import android.provider.Settings;
-import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import libcore.util.Objects;
@@ -102,6 +102,6 @@
@Override
public int getMetricsCategory() {
- return MetricsLogger.QS_COLOR_MATRIX;
+ return MetricsEvent.QS_COLOR_MATRIX;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
index f1de234..f801963 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
@@ -31,6 +31,7 @@
import android.view.MenuItem;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.DemoMode;
import com.android.systemui.R;
@@ -94,13 +95,13 @@
@Override
public void onResume() {
super.onResume();
- MetricsLogger.visibility(getContext(), MetricsLogger.TUNER_DEMO_MODE, true);
+ MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_DEMO_MODE, true);
}
@Override
public void onPause() {
super.onPause();
- MetricsLogger.visibility(getContext(), MetricsLogger.TUNER_DEMO_MODE, false);
+ MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_DEMO_MODE, false);
}
@Override
@@ -131,10 +132,10 @@
mOnSwitch.setChecked(false);
stopDemoMode();
}
- MetricsLogger.action(getContext(), MetricsLogger.TUNER_DEMO_MODE_ENABLED, enabled);
+ MetricsLogger.action(getContext(), MetricsEvent.TUNER_DEMO_MODE_ENABLED, enabled);
setGlobal(DemoMode.DEMO_MODE_ALLOWED, enabled ? 1 : 0);
} else if (preference == mOnSwitch) {
- MetricsLogger.action(getContext(), MetricsLogger.TUNER_DEMO_MODE_ON, enabled);
+ MetricsLogger.action(getContext(), MetricsEvent.TUNER_DEMO_MODE_ON, enabled);
if (enabled) {
startDemoMode();
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
index 920ec75..f2f0382 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
@@ -24,6 +24,7 @@
import android.util.AttributeSet;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -63,14 +64,14 @@
if (!value) {
// If not enabled add to blacklist.
if (!mBlacklist.contains(getKey())) {
- MetricsLogger.action(getContext(), MetricsLogger.TUNER_STATUS_BAR_DISABLE,
+ MetricsLogger.action(getContext(), MetricsEvent.TUNER_STATUS_BAR_DISABLE,
getKey());
mBlacklist.add(getKey());
setList(mBlacklist);
}
} else {
if (mBlacklist.remove(getKey())) {
- MetricsLogger.action(getContext(), MetricsLogger.TUNER_STATUS_BAR_ENABLE, getKey());
+ MetricsLogger.action(getContext(), MetricsEvent.TUNER_STATUS_BAR_ENABLE, getKey());
setList(mBlacklist);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index a3fe6bb..427b5e8 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -36,6 +36,7 @@
import android.view.MenuItem;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING;
@@ -84,7 +85,7 @@
getContext().getContentResolver().registerContentObserver(
System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
- MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, true);
+ MetricsLogger.visibility(getContext(), MetricsEvent.TUNER, true);
}
@Override
@@ -92,7 +93,7 @@
super.onPause();
getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
- MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, false);
+ MetricsLogger.visibility(getContext(), MetricsEvent.TUNER, false);
}
@Override
@@ -141,7 +142,7 @@
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean v = (Boolean) newValue;
- MetricsLogger.action(getContext(), MetricsLogger.TUNER_BATTERY_PERCENTAGE, v);
+ MetricsLogger.action(getContext(), MetricsEvent.TUNER_BATTERY_PERCENTAGE, v);
System.putInt(getContext().getContentResolver(), SHOW_PERCENT_SETTING, v ? 1 : 0);
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Events.java b/packages/SystemUI/src/com/android/systemui/volume/Events.java
index 893c939..8e0f9b8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/Events.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/Events.java
@@ -23,6 +23,7 @@
import android.util.Log;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.volume.VolumeDialogController.State;
import java.util.Arrays;
@@ -111,33 +112,33 @@
sb.append(" ");
switch (tag) {
case EVENT_SHOW_DIALOG:
- MetricsLogger.visible(context, MetricsLogger.VOLUME_DIALOG);
+ MetricsLogger.visible(context, MetricsEvent.VOLUME_DIALOG);
MetricsLogger.histogram(context, "volume_from_keyguard",
(Boolean) list[1] ? 1 : 0);
sb.append(SHOW_REASONS[(Integer) list[0]]).append(" keyguard=").append(list[1]);
break;
case EVENT_EXPAND:
- MetricsLogger.visibility(context, MetricsLogger.VOLUME_DIALOG_DETAILS,
+ MetricsLogger.visibility(context, MetricsEvent.VOLUME_DIALOG_DETAILS,
(Boolean) list[0]);
sb.append(list[0]);
break;
case EVENT_DISMISS_DIALOG:
- MetricsLogger.hidden(context, MetricsLogger.VOLUME_DIALOG);
+ MetricsLogger.hidden(context, MetricsEvent.VOLUME_DIALOG);
sb.append(DISMISS_REASONS[(Integer) list[0]]);
break;
case EVENT_ACTIVE_STREAM_CHANGED:
- MetricsLogger.action(context, MetricsLogger.ACTION_VOLUME_STREAM,
+ MetricsLogger.action(context, MetricsEvent.ACTION_VOLUME_STREAM,
(Integer) list[0]);
sb.append(AudioSystem.streamToString((Integer) list[0]));
break;
case EVENT_ICON_CLICK:
- MetricsLogger.action(context, MetricsLogger.ACTION_VOLUME_ICON,
+ MetricsLogger.action(context, MetricsEvent.ACTION_VOLUME_ICON,
(Integer) list[1]);
sb.append(AudioSystem.streamToString((Integer) list[0])).append(' ')
.append(iconStateToString((Integer) list[1]));
break;
case EVENT_TOUCH_LEVEL_DONE:
- MetricsLogger.action(context, MetricsLogger.ACTION_VOLUME_SLIDER,
+ MetricsLogger.action(context, MetricsEvent.ACTION_VOLUME_SLIDER,
(Integer) list[1]);
// fall through
case EVENT_TOUCH_LEVEL_CHANGED:
@@ -147,13 +148,13 @@
.append(list[1]);
break;
case EVENT_KEY:
- MetricsLogger.action(context, MetricsLogger.ACTION_VOLUME_KEY,
+ MetricsLogger.action(context, MetricsEvent.ACTION_VOLUME_KEY,
(Integer) list[1]);
sb.append(AudioSystem.streamToString((Integer) list[0])).append(' ')
.append(list[1]);
break;
case EVENT_EXTERNAL_RINGER_MODE_CHANGED:
- MetricsLogger.action(context, MetricsLogger.ACTION_RINGER_MODE,
+ MetricsLogger.action(context, MetricsEvent.ACTION_RINGER_MODE,
(Integer) list[0]);
// fall through
case EVENT_INTERNAL_RINGER_MODE_CHANGED:
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index b005a2b..5dc468b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -254,7 +254,7 @@
if (D.BUG) Log.d(TAG, "updateWindowWidth dm.w=" + dm.widthPixels);
int w = dm.widthPixels;
final int max = mContext.getResources()
- .getDimensionPixelSize(R.dimen.standard_notification_panel_width);
+ .getDimensionPixelSize(R.dimen.volume_dialog_panel_width);
if (w > max) {
w = max;
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index f73ba6f..e9594a3 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -51,6 +51,7 @@
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -620,7 +621,7 @@
if (childTag == null || childTag == tag) continue;
childTag.rb.setChecked(false);
}
- MetricsLogger.action(mContext, MetricsLogger.QS_DND_CONDITION_SELECT);
+ MetricsLogger.action(mContext, MetricsEvent.QS_DND_CONDITION_SELECT);
select(tag.condition);
announceConditionSelection(tag);
}
@@ -725,7 +726,7 @@
}
private void onClickTimeButton(View row, ConditionTag tag, boolean up, int rowId) {
- MetricsLogger.action(mContext, MetricsLogger.QS_DND_TIME, up);
+ MetricsLogger.action(mContext, MetricsEvent.QS_DND_TIME, up);
Condition newCondition = null;
final int N = MINUTE_BUCKETS.length;
if (mBucketIndex == -1) {
@@ -928,7 +929,7 @@
if (value != null && mZenButtons.isShown() && isAttachedToWindow()) {
final int zen = (Integer) value;
if (fromClick) {
- MetricsLogger.action(mContext, MetricsLogger.QS_DND_ZEN_SELECT, zen);
+ MetricsLogger.action(mContext, MetricsEvent.QS_DND_ZEN_SELECT, zen);
}
if (DEBUG) Log.d(mTag, "mZenButtonsCallback selected=" + zen);
final Uri realConditionId = getRealConditionId(mSessionExitCondition);
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index a71ba636..8c78a3a 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -55,12 +55,16 @@
**/
public class Allocation extends BaseObj {
+ private static final int MAX_NUMBER_IO_INPUT_ALLOC = 16;
+
Type mType;
Bitmap mBitmap;
int mUsage;
Allocation mAdaptedAllocation;
int mSize;
+ MipmapControl mMipmapControl;
+ long mTimeStamp = -1;
boolean mReadAllowed = true;
boolean mWriteAllowed = true;
boolean mAutoPadding = false;
@@ -278,6 +282,17 @@
}
/**
+ * @hide
+ * Get the Mipmap control flag of the Allocation.
+ *
+ * @return the Mipmap control flag of the Allocation
+ *
+ */
+ public MipmapControl getMipmap() {
+ return mMipmapControl;
+ }
+
+ /**
* Enable/Disable AutoPadding for Vec3 elements.
* By default: Diabled.
*
@@ -359,6 +374,11 @@
}
}
+ Allocation(long id, RenderScript rs, Type t, int usage, MipmapControl mips) {
+ this(id, rs, t, usage);
+ mMipmapControl = mips;
+ }
+
protected void finalize() throws Throwable {
RenderScript.registerNativeFree.invoke(RenderScript.sRuntime, mSize);
super.finalize();
@@ -521,7 +541,7 @@
"Can only receive if IO_INPUT usage specified.");
}
mRS.validate();
- mRS.nAllocationIoReceive(getID(mRS));
+ mTimeStamp = mRS.nAllocationIoReceive(getID(mRS));
} finally {
Trace.traceEnd(RenderScript.TRACE_TAG);
}
@@ -1890,7 +1910,7 @@
if (id == 0) {
throw new RSRuntimeException("Allocation creation failed.");
}
- return new Allocation(id, rs, type, usage);
+ return new Allocation(id, rs, type, usage, mips);
} finally {
Trace.traceEnd(RenderScript.TRACE_TAG);
}
@@ -1948,7 +1968,7 @@
if (id == 0) {
throw new RSRuntimeException("Allocation creation failed.");
}
- return new Allocation(id, rs, t, usage);
+ return new Allocation(id, rs, t, usage, MipmapControl.MIPMAP_NONE);
} finally {
Trace.traceEnd(RenderScript.TRACE_TAG);
}
@@ -2037,7 +2057,7 @@
}
// keep a reference to the Bitmap around to prevent GC
- Allocation alloc = new Allocation(id, rs, t, usage);
+ Allocation alloc = new Allocation(id, rs, t, usage, mips);
alloc.setBitmap(b);
return alloc;
}
@@ -2047,14 +2067,13 @@
if (id == 0) {
throw new RSRuntimeException("Load failed.");
}
- return new Allocation(id, rs, t, usage);
+ return new Allocation(id, rs, t, usage, mips);
} finally {
Trace.traceEnd(RenderScript.TRACE_TAG);
}
}
/**
- * @hide
* Gets or creates a ByteBuffer that contains the raw data of the current Allocation.
* If the Allocation is created with USAGE_IO_INPUT, the returned ByteBuffer
* would contain the up-to-date data as READ ONLY.
@@ -2089,7 +2108,107 @@
}
/**
- * @hide
+ * Creates a new Allocation Array with the given {@link
+ * android.renderscript.Type}, and usage flags.
+ * Note: If the input allocation is of usage: USAGE_IO_INPUT,
+ * the created Allocation will be sharing the same BufferQueue.
+ *
+ * @param rs RenderScript context
+ * @param t RenderScript type describing data layout
+ * @param usage bit field specifying how the Allocation is
+ * utilized
+ * @param numAlloc Number of Allocations in the array.
+ * @return Allocation[]
+ */
+ public static Allocation[] createAllocations(RenderScript rs, Type t, int usage, int numAlloc) {
+ try {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "createAllocations");
+ rs.validate();
+ if (t.getID(rs) == 0) {
+ throw new RSInvalidStateException("Bad Type");
+ }
+
+ Allocation[] mAllocationArray = new Allocation[numAlloc];
+ mAllocationArray[0] = createTyped(rs, t, usage);
+ if ((usage & USAGE_IO_INPUT) != 0) {
+ if (numAlloc > MAX_NUMBER_IO_INPUT_ALLOC) {
+ throw new RSIllegalArgumentException("Exceeds the max number of Allocations allowed: " +
+ MAX_NUMBER_IO_INPUT_ALLOC);
+ }
+ mAllocationArray[0].setupBufferQueue(numAlloc);;
+ }
+
+ for (int i=1; i<numAlloc; i++) {
+ mAllocationArray[i] = createFromAllcation(rs, mAllocationArray[0]);
+ }
+ return mAllocationArray;
+ } finally {
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+ }
+
+ /**
+ * Creates a new Allocation with the given {@link
+ * android.renderscript.Allocation}. The same data layout of
+ * the input Allocation will be applied.
+ * If the input allocation is of usage: USAGE_IO_INPUT, the created
+ * Allocation will be sharing the same BufferQueue.
+ *
+ * @param rs Context to which the allocation will belong.
+ * @param alloc RenderScript Allocation describing data layout.
+ * @return Allocation sharing the same data structure.
+ */
+ static Allocation createFromAllcation(RenderScript rs, Allocation alloc) {
+ try {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "createFromAllcation");
+ rs.validate();
+ if (alloc.getID(rs) == 0) {
+ throw new RSInvalidStateException("Bad input Allocation");
+ }
+
+ Type type = alloc.getType();
+ int usage = alloc.getUsage();
+ MipmapControl mips = alloc.getMipmap();
+ long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
+ if (id == 0) {
+ throw new RSRuntimeException("Allocation creation failed.");
+ }
+ Allocation outAlloc = new Allocation(id, rs, type, usage, mips);
+ if ((usage & USAGE_IO_INPUT) != 0) {
+ outAlloc.shareBufferQueue(alloc);
+ }
+ return outAlloc;
+ } finally {
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+ }
+
+ /**
+ * Initialize BufferQueue with specified max number of buffers.
+ */
+ void setupBufferQueue(int numAlloc) {
+ mRS.validate();
+ if ((mUsage & USAGE_IO_INPUT) == 0) {
+ throw new RSInvalidStateException("Allocation is not USAGE_IO_INPUT.");
+ }
+ mRS.nAllocationSetupBufferQueue(getID(mRS), numAlloc);
+ }
+
+ /**
+ * Share the BufferQueue with another {@link #USAGE_IO_INPUT} Allocation.
+ *
+ * @param alloc Allocation to associate with allocation
+ */
+ void shareBufferQueue(Allocation alloc) {
+ mRS.validate();
+ if ((mUsage & USAGE_IO_INPUT) == 0) {
+ throw new RSInvalidStateException("Allocation is not USAGE_IO_INPUT.");
+ }
+ mGetSurfaceSurface = alloc.getSurface();
+ mRS.nAllocationShareBufferQueue(getID(mRS), alloc.getID(mRS));
+ }
+
+ /**
* Gets the stride of the Allocation.
* For a 2D or 3D Allocation, the raw data maybe padded so that each row of
* the Allocation has certain alignment. The size of each row including such
@@ -2107,6 +2226,26 @@
}
/**
+ * Get the timestamp for the most recent buffer held by this Allocation.
+ * The timestamp is guaranteed to be unique and monotonically increasing.
+ * Default value: -1. The timestamp will be updated after each {@link
+ * #ioReceive ioReceive()} call.
+ *
+ * It can be used to identify the images by comparing the unique timestamps
+ * when used with {@link android.hardware.camera2} APIs.
+ * Example steps:
+ * 1. Save {@link android.hardware.camera2.TotalCaptureResult} when the
+ * capture is completed.
+ * 2. Get the timestamp after {@link #ioReceive ioReceive()} call.
+ * 3. Comparing totalCaptureResult.get(CaptureResult.SENSOR_TIMESTAMP) with
+ * alloc.getTimeStamp().
+ * @return long Timestamp associated with the buffer held by the Allocation.
+ */
+ public long getTimeStamp() {
+ return mTimeStamp;
+ }
+
+ /**
* Returns the handle to a raw buffer that is being managed by the screen
* compositor. This operation is only valid for Allocations with {@link
* #USAGE_IO_INPUT}.
@@ -2210,7 +2349,7 @@
if(id == 0) {
throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
}
- return new Allocation(id, rs, t, usage);
+ return new Allocation(id, rs, t, usage, mips);
}
/**
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 4788223..51fc7dd 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -484,7 +484,6 @@
rsnAllocationCopyToBitmap(mContext, alloc, bmp);
}
-
native void rsnAllocationSyncAll(long con, long alloc, int src);
synchronized void nAllocationSyncAll(long alloc, int src) {
validate();
@@ -497,6 +496,16 @@
return rsnAllocationGetByteBuffer(mContext, alloc, stride, xBytesSize, dimY, dimZ);
}
+ native void rsnAllocationSetupBufferQueue(long con, long alloc, int numAlloc);
+ synchronized void nAllocationSetupBufferQueue(long alloc, int numAlloc) {
+ validate();
+ rsnAllocationSetupBufferQueue(mContext, alloc, numAlloc);
+ }
+ native void rsnAllocationShareBufferQueue(long con, long alloc1, long alloc2);
+ synchronized void nAllocationShareBufferQueue(long alloc1, long alloc2) {
+ validate();
+ rsnAllocationShareBufferQueue(mContext, alloc1, alloc2);
+ }
native Surface rsnAllocationGetSurface(long con, long alloc);
synchronized Surface nAllocationGetSurface(long alloc) {
validate();
@@ -512,13 +521,12 @@
validate();
rsnAllocationIoSend(mContext, alloc);
}
- native void rsnAllocationIoReceive(long con, long alloc);
- synchronized void nAllocationIoReceive(long alloc) {
+ native long rsnAllocationIoReceive(long con, long alloc);
+ synchronized long nAllocationIoReceive(long alloc) {
validate();
- rsnAllocationIoReceive(mContext, alloc);
+ return rsnAllocationIoReceive(mContext, alloc);
}
-
native void rsnAllocationGenerateMipmaps(long con, long alloc);
synchronized void nAllocationGenerateMipmaps(long alloc) {
validate();
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 398d89b..3dff37b 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1223,6 +1223,27 @@
rsAllocationSyncAll((RsContext)con, (RsAllocation)a, (RsAllocationUsageType)bits);
}
+static void
+nAllocationSetupBufferQueue(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint numAlloc)
+{
+ if (kLogApi) {
+ ALOGD("nAllocationSetupBufferQueue, con(%p), alloc(%p), numAlloc(%d)", (RsContext)con,
+ (RsAllocation)alloc, numAlloc);
+ }
+ rsAllocationSetupBufferQueue((RsContext)con, (RsAllocation)alloc, (uint32_t)numAlloc);
+}
+
+static void
+nAllocationShareBufferQueue(JNIEnv *_env, jobject _this, jlong con, jlong alloc1, jlong alloc2)
+{
+ if (kLogApi) {
+ ALOGD("nAllocationShareBufferQueue, con(%p), alloc1(%p), alloc2(%p)", (RsContext)con,
+ (RsAllocation)alloc1, (RsAllocation)alloc2);
+ }
+
+ rsAllocationShareBufferQueue((RsContext)con, (RsAllocation)alloc1, (RsAllocation)alloc2);
+}
+
static jobject
nAllocationGetSurface(JNIEnv *_env, jobject _this, jlong con, jlong a)
{
@@ -1265,16 +1286,15 @@
rsAllocationIoSend((RsContext)con, (RsAllocation)alloc);
}
-static void
+static jlong
nAllocationIoReceive(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
{
if (kLogApi) {
ALOGD("nAllocationIoReceive, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc);
}
- rsAllocationIoReceive((RsContext)con, (RsAllocation)alloc);
+ return (jlong) rsAllocationIoReceive((RsContext)con, (RsAllocation)alloc);
}
-
static void
nAllocationGenerateMipmaps(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
{
@@ -2856,10 +2876,12 @@
{"rsnAllocationCopyToBitmap", "(JJLandroid/graphics/Bitmap;)V", (void*)nAllocationCopyToBitmap },
{"rsnAllocationSyncAll", "(JJI)V", (void*)nAllocationSyncAll },
+{"rsnAllocationSetupBufferQueue", "(JJI)V", (void*)nAllocationSetupBufferQueue },
+{"rsnAllocationShareBufferQueue", "(JJJ)V", (void*)nAllocationShareBufferQueue },
{"rsnAllocationGetSurface", "(JJ)Landroid/view/Surface;", (void*)nAllocationGetSurface },
{"rsnAllocationSetSurface", "(JJLandroid/view/Surface;)V", (void*)nAllocationSetSurface },
{"rsnAllocationIoSend", "(JJ)V", (void*)nAllocationIoSend },
-{"rsnAllocationIoReceive", "(JJ)V", (void*)nAllocationIoReceive },
+{"rsnAllocationIoReceive", "(JJ)J", (void*)nAllocationIoReceive },
{"rsnAllocationData1D", "(JJIIILjava/lang/Object;IIIZ)V", (void*)nAllocationData1D },
{"rsnAllocationElementData", "(JJIIIII[BI)V", (void*)nAllocationElementData },
{"rsnAllocationData2D", "(JJIIIIIILjava/lang/Object;IIIZ)V", (void*)nAllocationData2D },
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 3c13630..c3c3e3f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -745,7 +745,7 @@
mTestMode = SystemProperties.get("cm.test.mode").equals("true")
&& SystemProperties.get("ro.build.type").equals("eng");
- mTethering = new Tethering(mContext, mNetd, statsService, mHandler.getLooper());
+ mTethering = new Tethering(mContext, mNetd, statsService);
mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index 2aa0390..d6575e8 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -38,6 +38,7 @@
import android.view.KeyEvent;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.server.statusbar.StatusBarManagerInternal;
/**
@@ -270,7 +271,7 @@
launched = handleCameraLaunchGesture(false /* useWakelock */,
StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
if (launched) {
- MetricsLogger.action(mContext, MetricsLogger.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE,
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE,
(int) doubleTapInterval);
}
}
@@ -341,7 +342,7 @@
}
if (handleCameraLaunchGesture(true /* useWakelock */,
StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE)) {
- MetricsLogger.action(mContext, MetricsLogger.ACTION_WIGGLE_CAMERA_GESTURE);
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_WIGGLE_CAMERA_GESTURE);
trackCameraLaunchEvent(event);
}
return;
diff --git a/services/core/java/com/android/server/SensorNotificationService.java b/services/core/java/com/android/server/SensorNotificationService.java
new file mode 100644
index 0000000..0610464
--- /dev/null
+++ b/services/core/java/com/android/server/SensorNotificationService.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package com.android.server;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
+
+public class SensorNotificationService extends SystemService implements SensorEventListener {
+ //TODO: set DBG to false or remove Slog before release
+ private static final boolean DBG = true;
+ private static final String TAG = "SensorNotificationService";
+ private Context mContext;
+
+ private SensorManager mSensorManager;
+ private Sensor mMetaSensor;
+
+ public SensorNotificationService(Context context) {
+ super(context);
+ mContext = context;
+ }
+
+ public void onStart() {
+ LocalServices.addService(SensorNotificationService.class, this);
+ }
+
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+ // start
+ mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+ mMetaSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_DYNAMIC_SENSOR_META);
+ if (mMetaSensor == null) {
+ if (DBG) Slog.d(TAG, "Cannot obtain dynamic meta sensor, not supported.");
+ } else {
+ mSensorManager.registerListener(this, mMetaSensor,
+ SensorManager.SENSOR_DELAY_FASTEST);
+ }
+ }
+ }
+
+ private void broadcastDynamicSensorChanged() {
+ Intent i = new Intent(Intent.ACTION_DYNAMIC_SENSOR_CHANGED);
+ i.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); // avoid waking up manifest receivers
+ mContext.sendBroadcastAsUser(i, UserHandle.ALL);
+ if (DBG) Slog.d(TAG, "DYNS sent dynamic sensor broadcast");
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ if (event.sensor == mMetaSensor) {
+ broadcastDynamicSensorChanged();
+ }
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+
+ }
+}
+
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index d0006aa..143015f 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -4342,6 +4342,7 @@
String opPackageName) {
List<String> permissionsToCheck = new ArrayList<String>(2);
permissionsToCheck.add(Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
+ long id = Binder.clearCallingIdentity();
try {
ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
opPackageName, 0 /* flags */);
@@ -4363,6 +4364,8 @@
} catch (NameNotFoundException e) {
// No application associated with the specified package.
Log.w(TAG, "No application associated with package: " + opPackageName);
+ } finally {
+ Binder.restoreCallingIdentity(id);
}
boolean isPermitted = isPermitted(opPackageName, callingUid, permissionsToCheck);
return getTypesForCaller(callingUid, userId, isPermitted);
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 82862e8..97ef10b 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -40,6 +40,7 @@
import android.os.UserHandle;
import android.os.WorkSource;
import android.telephony.DataConnectionRealTimeInfo;
+import android.telephony.ModemActivityInfo;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.util.IntArray;
@@ -51,6 +52,7 @@
import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.PowerProfile;
+import com.android.internal.telephony.ITelephony;
import com.android.server.FgThread;
import com.android.server.LocalServices;
@@ -855,6 +857,18 @@
}
}
+ @Override
+ public void noteBleScanStarted(WorkSource ws) {
+ enforceCallingPermission();
+ Slog.d(TAG, "BLE scan started for " + ws);
+ }
+
+ @Override
+ public void noteBleScanStopped(WorkSource ws) {
+ enforceCallingPermission();
+ Slog.d(TAG, "BLE scan stopped for " + ws);
+ }
+
public boolean isOnBattery() {
return mStats.isOnBattery();
}
@@ -1317,6 +1331,24 @@
return null;
}
+ @GuardedBy("mExternalStatsLock")
+ private ModemActivityInfo pullModemActivityInfoLocked() {
+ ITelephony tm = ITelephony.Stub.asInterface(ServiceManager.getService(
+ Context.TELEPHONY_SERVICE));
+ try {
+ if (tm != null) {
+ ModemActivityInfo info = tm.getModemActivityInfo();
+ if (info == null || info.isValid()) {
+ return info;
+ }
+ Slog.wtf(TAG, "Modem activity info is invalid: " + info);
+ }
+ } catch (RemoteException e) {
+ // Nothing to do.
+ }
+ return null;
+ }
+
/**
* Fetches data from external sources (WiFi controller, bluetooth chipset) and updates
* batterystats with that information.
@@ -1346,6 +1378,11 @@
wifiEnergyInfo = pullWifiEnergyInfoLocked();
}
+ ModemActivityInfo modemActivityInfo = null;
+ if ((updateFlags & UPDATE_RADIO) != 0) {
+ modemActivityInfo = pullModemActivityInfoLocked();
+ }
+
BluetoothActivityEnergyInfo bluetoothEnergyInfo = null;
if ((updateFlags & UPDATE_BT) != 0) {
// We only pull bluetooth stats when we have to, as we are not distributing its
@@ -1367,7 +1404,7 @@
}
if ((updateFlags & UPDATE_RADIO) != 0) {
- mStats.updateMobileRadioStateLocked(elapsedRealtime);
+ mStats.updateMobileRadioStateLocked(elapsedRealtime, modemActivityInfo);
}
if ((updateFlags & UPDATE_WIFI) != 0) {
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 6648efd..a73a67a 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -153,11 +153,10 @@
// when RNDIS is enabled
public Tethering(Context context, INetworkManagementService nmService,
- INetworkStatsService statsService, Looper looper) {
+ INetworkStatsService statsService) {
mContext = context;
mNMService = nmService;
mStatsService = statsService;
- mLooper = looper;
mPublicSync = new Object();
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index 206cc8a..a633996 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -17,6 +17,7 @@
package com.android.server.dreams;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import android.content.ComponentName;
import android.content.Context;
@@ -131,7 +132,7 @@
mDreamStartTime = SystemClock.elapsedRealtime();
MetricsLogger.visible(mContext,
- mCurrentDream.mCanDoze ? MetricsLogger.DOZING : MetricsLogger.DREAMING);
+ mCurrentDream.mCanDoze ? MetricsEvent.DOZING : MetricsEvent.DREAMING);
try {
mIWindowManager.addWindowToken(token, WindowManager.LayoutParams.TYPE_DREAM);
@@ -196,7 +197,7 @@
+ ", isTest=" + oldDream.mIsTest + ", canDoze=" + oldDream.mCanDoze
+ ", userId=" + oldDream.mUserId);
MetricsLogger.hidden(mContext,
- oldDream.mCanDoze ? MetricsLogger.DOZING : MetricsLogger.DREAMING);
+ oldDream.mCanDoze ? MetricsEvent.DOZING : MetricsEvent.DREAMING);
MetricsLogger.histogram(mContext,
oldDream.mCanDoze ? "dozing_minutes" : "dreaming_minutes" ,
(int) ((SystemClock.elapsedRealtime() - mDreamStartTime) / (1000L * 60L)));
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index e74d636..13e7648 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -48,6 +48,7 @@
import android.util.Slog;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.server.SystemService;
import org.json.JSONArray;
@@ -686,7 +687,7 @@
private boolean sendEnrollResult(int fpId, int groupId, int remaining) {
if (receiver == null) return true; // client not listening
FingerprintUtils.vibrateFingerprintSuccess(getContext());
- MetricsLogger.action(mContext, MetricsLogger.ACTION_FINGERPRINT_ENROLL);
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_FINGERPRINT_ENROLL);
try {
receiver.onEnrollResult(mHalDeviceId, fpId, groupId, remaining);
return remaining == 0;
@@ -704,7 +705,7 @@
boolean authenticated = fpId != 0;
if (receiver != null) {
try {
- MetricsLogger.action(mContext, MetricsLogger.ACTION_FINGERPRINT_AUTH,
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_FINGERPRINT_AUTH,
authenticated);
if (!authenticated) {
receiver.onAuthenticationFailed(mHalDeviceId);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 7f783ec..b54efcc 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -16,6 +16,7 @@
package com.android.server.notification;
+import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
import static android.service.notification.NotificationAssistantService.REASON_APP_CANCEL;
import static android.service.notification.NotificationAssistantService.REASON_APP_CANCEL_ALL;
import static android.service.notification.NotificationAssistantService.REASON_DELEGATE_CANCEL;
@@ -28,6 +29,7 @@
import static android.service.notification.NotificationAssistantService.REASON_LISTENER_CANCEL_ALL;
import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_BANNED;
import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_CHANGED;
+import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_SUSPENDED;
import static android.service.notification.NotificationAssistantService.REASON_TOPIC_BANNED;
import static android.service.notification.NotificationAssistantService.REASON_USER_STOPPED;
import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
@@ -456,7 +458,7 @@
/** Use this to check if a package can post a notification or toast. */
private boolean checkNotificationOp(String pkg, int uid) {
return mAppOps.checkOp(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg)
- == AppOpsManager.MODE_ALLOWED;
+ == AppOpsManager.MODE_ALLOWED && !isApplicationSuspended(pkg, uid);
}
private static final class ToastRecord
@@ -691,13 +693,15 @@
boolean queryRemove = false;
boolean packageChanged = false;
boolean cancelNotifications = true;
+ int reason = REASON_PACKAGE_CHANGED;
if (action.equals(Intent.ACTION_PACKAGE_ADDED)
|| (queryRemove=action.equals(Intent.ACTION_PACKAGE_REMOVED))
|| action.equals(Intent.ACTION_PACKAGE_RESTARTED)
|| (packageChanged=action.equals(Intent.ACTION_PACKAGE_CHANGED))
|| (queryRestart=action.equals(Intent.ACTION_QUERY_PACKAGE_RESTART))
- || action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
+ || action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)
+ || action.equals(Intent.ACTION_PACKAGES_SUSPENDED)) {
int changeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
UserHandle.USER_ALL);
String pkgList[] = null;
@@ -706,6 +710,9 @@
if (DBG) Slog.i(TAG, "action=" + action + " queryReplace=" + queryReplace);
if (action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ } else if (action.equals(Intent.ACTION_PACKAGES_SUSPENDED)) {
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ reason = REASON_PACKAGE_SUSPENDED;
} else if (queryRestart) {
pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
} else {
@@ -745,7 +752,7 @@
for (String pkgName : pkgList) {
if (cancelNotifications) {
cancelAllNotificationsInt(MY_UID, MY_PID, pkgName, 0, 0, !queryRestart,
- changeUserId, REASON_PACKAGE_CHANGED, null, null);
+ changeUserId, reason, null, null);
}
}
}
@@ -989,6 +996,11 @@
getContext().registerReceiverAsUser(mPackageIntentReceiver, UserHandle.ALL, pkgFilter, null,
null);
+ IntentFilter suspendedPkgFilter = new IntentFilter();
+ suspendedPkgFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
+ getContext().registerReceiverAsUser(mPackageIntentReceiver, UserHandle.ALL,
+ suspendedPkgFilter, null, null);
+
IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
getContext().registerReceiverAsUser(mPackageIntentReceiver, UserHandle.ALL, sdFilter, null,
null);
@@ -1104,10 +1116,16 @@
}
final boolean isSystemToast = isCallerSystem() || ("android".equals(pkg));
+ final boolean isApplicationSuspended =
+ isApplicationSuspended(pkg, Binder.getCallingUid());
- if (ENABLE_BLOCKED_TOASTS && !noteNotificationOp(pkg, Binder.getCallingUid())) {
+ if (ENABLE_BLOCKED_TOASTS && (!noteNotificationOp(pkg, Binder.getCallingUid())
+ || isApplicationSuspended)) {
if (!isSystemToast) {
- Slog.e(TAG, "Suppressing toast from package " + pkg + " by user request.");
+ Slog.e(TAG, "Suppressing toast from package " + pkg
+ + (isApplicationSuspended
+ ? " due to package suspended by administrator."
+ : " by user request."));
return;
}
}
@@ -1232,7 +1250,7 @@
public boolean areNotificationsEnabledForPackage(String pkg, int uid) {
checkCallerIsSystem();
return (mAppOps.checkOpNoThrow(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg)
- == AppOpsManager.MODE_ALLOWED);
+ == AppOpsManager.MODE_ALLOWED) && !isApplicationSuspended(pkg, uid);
}
@Override
@@ -2325,14 +2343,20 @@
// why is this here?
savePolicyFile();
+ final boolean isApplicationSuspended = isApplicationSuspended(pkg, callingUid);
// blocked apps/topics
if (r.getImportance() == NotificationListenerService.Ranking.IMPORTANCE_NONE
- || !noteNotificationOp(pkg, callingUid)) {
+ || !noteNotificationOp(pkg, callingUid) || isApplicationSuspended) {
if (!isSystemNotification) {
- Slog.e(TAG, "Suppressing notification from package " + pkg
- + " by user request.");
- mUsageStats.registerBlocked(r);
+ if (isApplicationSuspended) {
+ Slog.e(TAG, "Suppressing notification from package due to package "
+ + "suspended by administrator.");
+ mUsageStats.registerSuspendedByAdmin(r);
+ } else {
+ Slog.e(TAG, "Suppressing notification from package by user request.");
+ mUsageStats.registerBlocked(r);
+ }
return;
}
}
@@ -3423,6 +3447,24 @@
return true;
}
+ private boolean isApplicationSuspended(String pkg, int uid) {
+ int userId = UserHandle.getUserId(uid);
+ ApplicationInfo ai;
+ try {
+ // TODO: it might be faster to return a boolean from package manager rather than the
+ // whole application info. Revisit and make the API change.
+ ai = AppGlobals.getPackageManager().getApplicationInfo(pkg, 0, userId);
+ if (ai == null) {
+ Slog.w(TAG, "No application info for package " + pkg + " and user " + userId);
+ return false;
+ }
+ } catch (RemoteException re) {
+ throw new SecurityException("Could not talk to package manager service");
+ }
+
+ return ((ai.flags & FLAG_SUSPENDED) != 0);
+ }
+
private class TrimCache {
StatusBarNotification heavy;
StatusBarNotification sbnClone;
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index e75324f..0272850 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -198,6 +198,14 @@
releaseAggregatedStatsLocked(aggregatedStatsArray);
}
+ public synchronized void registerSuspendedByAdmin(NotificationRecord notification) {
+ AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(notification);
+ for (AggregatedStats stats : aggregatedStatsArray) {
+ stats.numSuspendedByAdmin++;
+ }
+ releaseAggregatedStatsLocked(aggregatedStatsArray);
+ }
+
// Locked by this.
private AggregatedStats[] getAggregatedStatsLocked(NotificationRecord record) {
if (!ENABLE_AGGREGATED_IN_MEMORY_STATS) {
@@ -298,6 +306,7 @@
public int numWithStaredPeople;
public int numWithValidPeople;
public int numBlocked;
+ public int numSuspendedByAdmin;
public int numWithActions;
public int numPrivate;
public int numSecret;
@@ -414,6 +423,7 @@
maybeCount("people_cache_hit", (numPeopleCacheHit - mPrevious.numPeopleCacheHit));
maybeCount("people_cache_miss", (numPeopleCacheMiss - mPrevious.numPeopleCacheMiss));
maybeCount("note_blocked", (numBlocked - mPrevious.numBlocked));
+ maybeCount("note_suspended", (numSuspendedByAdmin - mPrevious.numSuspendedByAdmin));
maybeCount("note_with_actions", (numWithActions - mPrevious.numWithActions));
maybeCount("note_private", (numPrivate - mPrevious.numPrivate));
maybeCount("note_secret", (numSecret - mPrevious.numSecret));
@@ -442,6 +452,7 @@
mPrevious.numWithStaredPeople = numWithStaredPeople;
mPrevious.numWithValidPeople = numWithValidPeople;
mPrevious.numBlocked = numBlocked;
+ mPrevious.numSuspendedByAdmin = numSuspendedByAdmin;
mPrevious.numWithActions = numWithActions;
mPrevious.numPrivate = numPrivate;
mPrevious.numSecret = numSecret;
@@ -501,6 +512,8 @@
output.append(indentPlusTwo);
output.append("numBlocked=").append(numBlocked).append(",\n");
output.append(indentPlusTwo);
+ output.append("numSuspendedByAdmin=").append(numSuspendedByAdmin).append(",\n");
+ output.append(indentPlusTwo);
output.append("numWithActions=").append(numWithActions).append(",\n");
output.append(indentPlusTwo);
output.append("numPrivate=").append(numPrivate).append(",\n");
@@ -551,6 +564,7 @@
maybePut(dump, "numWithStaredPeople", numWithStaredPeople);
maybePut(dump, "numWithValidPeople", numWithValidPeople);
maybePut(dump, "numBlocked", numBlocked);
+ maybePut(dump, "numSuspendedByAdmin", numSuspendedByAdmin);
maybePut(dump, "numWithActions", numWithActions);
maybePut(dump, "numPrivate", numPrivate);
maybePut(dump, "numSecret", numSecret);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index fc79849..0f614ca 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -25,9 +25,11 @@
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.IStopUserCallback;
+import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -302,6 +304,12 @@
private final LockPatternUtils mLockPatternUtils;
+ /**
+ * Whether all users should be created ephemeral.
+ */
+ @GuardedBy("mUsersLock")
+ private boolean mForceEphemeralUsers;
+
private static UserManagerService sInstance;
public static UserManagerService getInstance() {
@@ -1836,23 +1844,25 @@
}
}
- // Add ephemeral flag to guests if required. Also inherit it from parent.
+ userId = getNextAvailableId();
+ Environment.getUserSystemDirectory(userId).mkdirs();
boolean ephemeralGuests = Resources.getSystem()
.getBoolean(com.android.internal.R.bool.config_guestUserEphemeral);
- if ((isGuest && ephemeralGuests)
- || (parent != null && parent.info.isEphemeral())) {
- flags |= UserInfo.FLAG_EPHEMERAL;
- }
- userId = getNextAvailableId();
- userInfo = new UserInfo(userId, name, null, flags);
- userInfo.serialNumber = mNextSerialNumber++;
- long now = System.currentTimeMillis();
- userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0;
- userInfo.partial = true;
- userData = new UserData();
- userData.info = userInfo;
- Environment.getUserSystemDirectory(userInfo.id).mkdirs();
+
synchronized (mUsersLock) {
+ // Add ephemeral flag to guests/users if required. Also inherit it from parent.
+ if ((isGuest && ephemeralGuests) || mForceEphemeralUsers
+ || (parent != null && parent.info.isEphemeral())) {
+ flags |= UserInfo.FLAG_EPHEMERAL;
+ }
+
+ userInfo = new UserInfo(userId, name, null, flags);
+ userInfo.serialNumber = mNextSerialNumber++;
+ long now = System.currentTimeMillis();
+ userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0;
+ userInfo.partial = true;
+ userData = new UserData();
+ userData.info = userInfo;
mUsers.put(userId, userData);
}
writeUserListLP();
@@ -2914,6 +2924,61 @@
Binder.restoreCallingIdentity(ident);
}
}
+
+ @Override
+ public void setForceEphemeralUsers(boolean forceEphemeralUsers) {
+ synchronized (mUsersLock) {
+ mForceEphemeralUsers = forceEphemeralUsers;
+ }
+ }
+
+ @Override
+ public void removeAllUsers() {
+ if (UserHandle.USER_SYSTEM == ActivityManager.getCurrentUser()) {
+ // Remove the non-system users straight away.
+ removeNonSystemUsers();
+ } else {
+ // Switch to the system user first and then remove the other users.
+ BroadcastReceiver userSwitchedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int userId =
+ intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+ if (userId != UserHandle.USER_SYSTEM) {
+ return;
+ }
+ mContext.unregisterReceiver(this);
+ removeNonSystemUsers();
+ }
+ };
+ IntentFilter userSwitchedFilter = new IntentFilter();
+ userSwitchedFilter.addAction(Intent.ACTION_USER_SWITCHED);
+ mContext.registerReceiver(
+ userSwitchedReceiver, userSwitchedFilter, null, mHandler);
+
+ // Switch to the system user.
+ ActivityManager am =
+ (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ am.switchUser(UserHandle.USER_SYSTEM);
+ }
+ }
+ }
+
+ /* Remove all the users except of the system one. */
+ private void removeNonSystemUsers() {
+ ArrayList<UserInfo> usersToRemove = new ArrayList<>();
+ synchronized (mUsersLock) {
+ final int userSize = mUsers.size();
+ for (int i = 0; i < userSize; i++) {
+ UserInfo ui = mUsers.valueAt(i).info;
+ if (ui.id != UserHandle.USER_SYSTEM) {
+ usersToRemove.add(ui);
+ }
+ }
+ }
+ for (UserInfo ui: usersToRemove) {
+ removeUser(ui.id);
+ }
}
private class Shell extends ShellCommand {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 290019c..a1f24f7 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -131,6 +131,7 @@
private static final int WAKE_LOCK_STAY_AWAKE = 1 << 5; // only set if already awake
private static final int WAKE_LOCK_DOZE = 1 << 6;
private static final int WAKE_LOCK_DRAW = 1 << 7;
+ private static final int WAKE_LOCK_SUSTAINED_PERFORMANCE = 1 << 8;
// Summarizes the user activity state.
private static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;
@@ -149,6 +150,7 @@
// Power hints defined in hardware/libhardware/include/hardware/power.h.
private static final int POWER_HINT_LOW_POWER = 5;
+ private static final int POWER_HINT_SUSTAINED_PERFORMANCE = 6;
// Power features defined in hardware/libhardware/include/hardware/power.h.
private static final int POWER_FEATURE_DOUBLE_TAP_TO_WAKE = 1;
@@ -444,6 +446,9 @@
// True if we are currently in light device idle mode.
private boolean mLightDeviceIdleMode;
+ // True if we are currently in sustained performance mode.
+ private boolean mSustainedPerformanceMode;
+
// Set of app ids that we will always respect the wake locks for.
int[] mDeviceIdleWhitelist = new int[0];
@@ -452,6 +457,8 @@
private final SparseIntArray mUidState = new SparseIntArray();
+ private final SparseIntArray mSustainedPerformanceUid = new SparseIntArray();
+
// True if theater mode is enabled
private boolean mTheaterModeEnabled;
@@ -811,6 +818,12 @@
throw new IllegalArgumentException("Wake lock is already dead.");
}
mWakeLocks.add(wakeLock);
+
+ if ((flags & PowerManager.WAKE_LOCK_LEVEL_MASK)
+ == PowerManager.SUSTAINED_PERFORMANCE_WAKE_LOCK) {
+ int numberWakelock = mSustainedPerformanceUid.get(uid);
+ mSustainedPerformanceUid.put(uid, numberWakelock + 1);
+ }
setWakeLockDisabledStateLocked(wakeLock);
notifyAcquire = true;
}
@@ -879,6 +892,17 @@
mRequestWaitForNegativeProximity = true;
}
+
+ if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
+ == PowerManager.SUSTAINED_PERFORMANCE_WAKE_LOCK) {
+ int numberWakelock = mSustainedPerformanceUid.get(wakeLock.mOwnerUid);
+ if (numberWakelock == 1) {
+ mSustainedPerformanceUid.delete(wakeLock.mOwnerUid);
+ } else {
+ mSustainedPerformanceUid.put(wakeLock.mOwnerUid, numberWakelock - 1);
+ }
+ }
+
wakeLock.mLock.unlinkToDeath(wakeLock, 0);
removeWakeLockLocked(wakeLock, index);
}
@@ -1501,6 +1525,10 @@
break;
case PowerManager.DRAW_WAKE_LOCK:
mWakeLockSummary |= WAKE_LOCK_DRAW;
+ case PowerManager.SUSTAINED_PERFORMANCE_WAKE_LOCK:
+ if (!wakeLock.mDisabled) {
+ mWakeLockSummary |= WAKE_LOCK_SUSTAINED_PERFORMANCE;
+ }
break;
}
}
@@ -2198,6 +2226,14 @@
if (autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {
setHalAutoSuspendModeLocked(true);
}
+
+ if (mSustainedPerformanceMode
+ && (mWakeLockSummary & WAKE_LOCK_SUSTAINED_PERFORMANCE) == 0) {
+ setSustainedPerformanceModeLocked(false);
+ } else if (!mSustainedPerformanceMode
+ && (mWakeLockSummary & WAKE_LOCK_SUSTAINED_PERFORMANCE) != 0) {
+ setSustainedPerformanceModeLocked(true);
+ }
}
/**
@@ -2296,6 +2332,12 @@
}
}
+ private void setSustainedPerformanceModeLocked(boolean mode) {
+ mSustainedPerformanceMode = mode;
+ powerHintInternal(POWER_HINT_SUSTAINED_PERFORMANCE,
+ mSustainedPerformanceMode ? 1 : 0);
+ }
+
boolean isDeviceIdleModeInternal() {
synchronized (mLock) {
return mDeviceIdleMode;
@@ -2425,7 +2467,7 @@
void updateUidProcStateInternal(int uid, int procState) {
synchronized (mLock) {
mUidState.put(uid, procState);
- if (mDeviceIdleMode) {
+ if (mDeviceIdleMode || mSustainedPerformanceUid.get(uid) != 0) {
updateWakeLockDisabledStatesLocked();
}
}
@@ -2446,7 +2488,9 @@
for (int i = 0; i < numWakeLocks; i++) {
final WakeLock wakeLock = mWakeLocks.get(i);
if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
- == PowerManager.PARTIAL_WAKE_LOCK) {
+ == PowerManager.PARTIAL_WAKE_LOCK
+ || (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
+ == PowerManager.SUSTAINED_PERFORMANCE_WAKE_LOCK) {
if (setWakeLockDisabledStateLocked(wakeLock)) {
changed = true;
if (wakeLock.mDisabled) {
@@ -2465,9 +2509,9 @@
}
private boolean setWakeLockDisabledStateLocked(WakeLock wakeLock) {
+ boolean disabled = false;
if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
== PowerManager.PARTIAL_WAKE_LOCK) {
- boolean disabled = false;
if (mDeviceIdleMode) {
final int appid = UserHandle.getAppId(wakeLock.mOwnerUid);
// If we are in idle mode, we will ignore all partial wake locks that are
@@ -2481,10 +2525,16 @@
disabled = true;
}
}
- if (wakeLock.mDisabled != disabled) {
- wakeLock.mDisabled = disabled;
- return true;
- }
+ } else if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
+ == PowerManager.SUSTAINED_PERFORMANCE_WAKE_LOCK
+ && mUidState.get(wakeLock.mOwnerUid,
+ ActivityManager.PROCESS_STATE_CACHED_EMPTY)
+ > ActivityManager.PROCESS_STATE_TOP) {
+ disabled = true;
+ }
+ if (wakeLock.mDisabled != disabled) {
+ wakeLock.mDisabled = disabled;
+ return true;
}
return false;
}
@@ -2695,6 +2745,7 @@
pw.println(" mBatteryLevelLow=" + mBatteryLevelLow);
pw.println(" mLightDeviceIdleMode=" + mLightDeviceIdleMode);
pw.println(" mDeviceIdleMode=" + mDeviceIdleMode);
+ pw.println(" mSustainedPerformanceMode=" + mSustainedPerformanceMode);
pw.println(" mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist));
pw.println(" mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist));
pw.println(" mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime));
@@ -2809,6 +2860,14 @@
pw.println();
pw.println("Display Power: " + mDisplayPowerCallbacks);
+ pw.println();
+ pw.println("Sustained Performance UIDs:");
+ for (int i=0; i<mSustainedPerformanceUid.size(); i++) {
+ pw.print(" UID "); UserHandle.formatUid(pw, mSustainedPerformanceUid.keyAt(i));
+ pw.print(": "); pw.println(mSustainedPerformanceUid.valueAt(i));
+ }
+
+
wcd = mWirelessChargerDetector;
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 2833b35..f02e49e 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -587,6 +587,7 @@
outBounds.top = dockedBounds.bottom + dockDividerWidth;
}
}
+ DockedDividerUtils.sanitizeStackBounds(outBounds);
}
/** Resizes all non-docked stacks in the system to either fullscreen or the appropriate size
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e8de90c..c541b3f 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2061,7 +2061,8 @@
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
Configuration newConfig) throws RemoteException {
mClient.resized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, outsets,
- reportDraw, newConfig, getBackdropFrame(frame));
+ reportDraw, newConfig, getBackdropFrame(frame),
+ isDragResizeChanged() /* forceRelayout */);
}
public void registerFocusObserver(IWindowFocusObserver observer) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 4fd8990..b94e6d6 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -471,6 +471,7 @@
private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture";
private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management";
private static final String TAG_REQUIRE_AUTO_TIME = "require_auto_time";
+ private static final String TAG_FORCE_EPHEMERAL_USERS = "force_ephemeral_users";
private static final String TAG_ACCOUNT_TYPE = "account-type";
private static final String TAG_PERMITTED_ACCESSIBILITY_SERVICES
= "permitted-accessiblity-services";
@@ -559,6 +560,7 @@
boolean disableBluetoothContactSharing = true;
boolean disableScreenCapture = false; // Can only be set by a device/profile owner.
boolean requireAutoTime = false; // Can only be set by a device owner.
+ boolean forceEphemeralUsers = false; // Can only be set by a device owner.
ActiveAdmin parentAdmin;
final boolean isParent;
@@ -749,6 +751,11 @@
out.attribute(null, ATTR_VALUE, Boolean.toString(requireAutoTime));
out.endTag(null, TAG_REQUIRE_AUTO_TIME);
}
+ if (forceEphemeralUsers) {
+ out.startTag(null, TAG_FORCE_EPHEMERAL_USERS);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(forceEphemeralUsers));
+ out.endTag(null, TAG_FORCE_EPHEMERAL_USERS);
+ }
if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
out.startTag(null, TAG_DISABLE_KEYGUARD_FEATURES);
out.attribute(null, ATTR_VALUE, Integer.toString(disabledKeyguardFeatures));
@@ -919,7 +926,10 @@
disableScreenCapture = Boolean.parseBoolean(
parser.getAttributeValue(null, ATTR_VALUE));
} else if (TAG_REQUIRE_AUTO_TIME.equals(tag)) {
- requireAutoTime= Boolean.parseBoolean(
+ requireAutoTime = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_FORCE_EPHEMERAL_USERS.equals(tag)) {
+ forceEphemeralUsers = Boolean.parseBoolean(
parser.getAttributeValue(null, ATTR_VALUE));
} else if (TAG_DISABLE_KEYGUARD_FEATURES.equals(tag)) {
disabledKeyguardFeatures = Integer.parseInt(
@@ -1150,6 +1160,8 @@
pw.println(disableScreenCapture);
pw.print(prefix); pw.print("requireAutoTime=");
pw.println(requireAutoTime);
+ pw.print(prefix); pw.print("forceEphemeralUsers=");
+ pw.println(forceEphemeralUsers);
pw.print(prefix); pw.print("disabledKeyguardFeatures=");
pw.println(disabledKeyguardFeatures);
pw.print(prefix); pw.print("crossProfileWidgetProviders=");
@@ -1971,7 +1983,7 @@
final ResolveInfo ri = infos.get(0);
if (!permission.BIND_DEVICE_ADMIN.equals(ri.activityInfo.permission)) {
- final String message = "DeviceAdminReceiver " + adminName + " must be protected with"
+ final String message = "DeviceAdminReceiver " + adminName + " must be protected with "
+ permission.BIND_DEVICE_ADMIN;
Slog.w(LOG_TAG, message);
if (throwForMissiongPermission &&
@@ -2408,6 +2420,14 @@
if (packageList != null) {
mInjector.getPackageManagerInternal().setKeepUninstalledPackages(packageList);
}
+
+ synchronized (this) {
+ // push the force-ephemeral-users policy to the user manager.
+ ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
+ if (deviceOwner != null) {
+ mUserManagerInternal.setForceEphemeralUsers(deviceOwner.forceEphemeralUsers);
+ }
+ }
}
private void ensureDeviceOwnerUserStarted() {
@@ -4789,6 +4809,46 @@
}
}
+ @Override
+ public void setForceEphemeralUsers(ComponentName who, boolean forceEphemeralUsers) {
+ if (!mHasFeature) {
+ return;
+ }
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ boolean removeAllUsers = false;
+ synchronized (this) {
+ final ActiveAdmin deviceOwner =
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+ if (deviceOwner.forceEphemeralUsers != forceEphemeralUsers) {
+ deviceOwner.forceEphemeralUsers = forceEphemeralUsers;
+ saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ mUserManagerInternal.setForceEphemeralUsers(forceEphemeralUsers);
+ removeAllUsers = forceEphemeralUsers;
+ }
+ }
+ if (removeAllUsers) {
+ long identitity = mInjector.binderClearCallingIdentity();
+ try {
+ mUserManagerInternal.removeAllUsers();
+ } finally {
+ mInjector.binderRestoreCallingIdentity(identitity);
+ }
+ }
+ }
+
+ @Override
+ public boolean getForceEphemeralUsers(ComponentName who) {
+ if (!mHasFeature) {
+ return false;
+ }
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ synchronized (this) {
+ final ActiveAdmin deviceOwner =
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+ return deviceOwner.forceEphemeralUsers;
+ }
+ }
+
private void ensureDeviceOwnerManagingSingleUser(ComponentName who) throws SecurityException {
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -5319,6 +5379,8 @@
if (admin != null) {
admin.disableCamera = false;
admin.userRestrictions = null;
+ admin.forceEphemeralUsers = false;
+ mUserManagerInternal.setForceEphemeralUsers(admin.forceEphemeralUsers);
}
clearUserPoliciesLocked(new UserHandle(UserHandle.USER_SYSTEM));
@@ -5361,7 +5423,9 @@
if (!mHasFeature) {
return;
}
- UserHandle callingUser = mInjector.binderGetCallingUserHandle();
+ final UserHandle callingUser = mInjector.binderGetCallingUserHandle();
+ final int userId = callingUser.getIdentifier();
+ enforceNotManagedProfile(userId, "clear profile owner");
// Check if this is the profile owner who is calling
final ActiveAdmin admin =
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -5369,7 +5433,6 @@
admin.disableCamera = false;
admin.userRestrictions = null;
clearUserPoliciesLocked(callingUser);
- final int userId = callingUser.getIdentifier();
mOwners.removeProfileOwner(userId);
mOwners.writeProfileOwner(userId);
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c186a12..9f320e4 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -84,6 +84,7 @@
import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
import com.android.server.restrictions.RestrictionsManagerService;
+import com.android.server.soundtrigger.SoundTriggerService;
import com.android.server.statusbar.StatusBarManagerService;
import com.android.server.storage.DeviceStorageMonitorService;
import com.android.server.telecom.TelecomLoaderService;
@@ -959,6 +960,8 @@
mSystemServiceManager.startService(JobSchedulerService.class);
+ mSystemServiceManager.startService(SoundTriggerService.class);
+
if (!disableNonCoreServices) {
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_BACKUP)) {
mSystemServiceManager.startService(BACKUP_MANAGER_SERVICE_CLASS);
@@ -976,6 +979,7 @@
Slog.i(TAG, "Gesture Launcher Service");
mSystemServiceManager.startService(GestureLauncherService.class);
}
+ mSystemServiceManager.startService(SensorNotificationService.class);
}
traceBeginAndSlog("StartDiskStatsService");
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerDbHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerDbHelper.java
new file mode 100644
index 0000000..18a5d59
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerDbHelper.java
@@ -0,0 +1,144 @@
+/**
+ * Copyright (C) 2014 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.soundtrigger;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import java.util.Locale;
+import java.util.UUID;
+
+/**
+ * Helper to manage the database of the sound models that have been registered on the device.
+ *
+ * @hide
+ */
+public class SoundTriggerDbHelper extends SQLiteOpenHelper {
+ static final String TAG = "SoundTriggerDbHelper";
+ static final boolean DBG = false;
+
+ private static final String NAME = "st_sound_model.db";
+ private static final int VERSION = 1;
+
+ // Sound trigger-based sound models.
+ public static interface GenericSoundModelContract {
+ public static final String TABLE = "st_sound_model";
+ public static final String KEY_MODEL_UUID = "model_uuid";
+ public static final String KEY_VENDOR_UUID = "vendor_uuid";
+ public static final String KEY_DATA = "data";
+ }
+
+
+ // Table Create Statement for the sound trigger table
+ private static final String CREATE_TABLE_ST_SOUND_MODEL = "CREATE TABLE "
+ + GenericSoundModelContract.TABLE + "("
+ + GenericSoundModelContract.KEY_MODEL_UUID + " TEXT PRIMARY KEY,"
+ + GenericSoundModelContract.KEY_DATA + " BLOB" + " )";
+
+
+ public SoundTriggerDbHelper(Context context) {
+ super(context, NAME, null, VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ // creating required tables
+ db.execSQL(CREATE_TABLE_ST_SOUND_MODEL);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ // TODO: For now, drop older tables and recreate new ones.
+ db.execSQL("DROP TABLE IF EXISTS " + GenericSoundModelContract.TABLE);
+ onCreate(db);
+ }
+
+ /**
+ * Updates the given sound trigger model, adds it, if it doesn't already exist.
+ *
+ */
+ public boolean updateGenericSoundModel(GenericSoundModel soundModel) {
+ synchronized(this) {
+ SQLiteDatabase db = getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(GenericSoundModelContract.KEY_MODEL_UUID, soundModel.uuid.toString());
+ values.put(GenericSoundModelContract.KEY_VENDOR_UUID, soundModel.vendorUuid.toString());
+ values.put(GenericSoundModelContract.KEY_DATA, soundModel.data);
+
+ try {
+ return db.insertWithOnConflict(GenericSoundModelContract.TABLE, null, values,
+ SQLiteDatabase.CONFLICT_REPLACE) != -1;
+ } finally {
+ db.close();
+ }
+
+ }
+ }
+
+ public GenericSoundModel getGenericSoundModel(UUID model_uuid) {
+ synchronized(this) {
+
+ // Find the corresponding sound model ID for the keyphrase.
+ String selectQuery = "SELECT * FROM " + GenericSoundModelContract.TABLE
+ + " WHERE " + GenericSoundModelContract.KEY_MODEL_UUID + "= '" +
+ model_uuid + "'";
+ SQLiteDatabase db = getReadableDatabase();
+ Cursor c = db.rawQuery(selectQuery, null);
+ try {
+ if (c.moveToFirst()) {
+ do {
+ byte[] data = c.getBlob(c.getColumnIndex(
+ GenericSoundModelContract.KEY_DATA));
+ String vendor_uuid = c.getString(
+ c.getColumnIndex(GenericSoundModelContract.KEY_VENDOR_UUID));
+ return new GenericSoundModel(model_uuid, UUID.fromString(vendor_uuid),
+ data);
+ } while (c.moveToNext());
+ }
+ } finally {
+ c.close();
+ db.close();
+ }
+ }
+ return null;
+ }
+
+ public boolean deleteGenericSoundModel(UUID model_uuid) {
+ synchronized(this) {
+ GenericSoundModel soundModel = getGenericSoundModel(model_uuid);
+ if (soundModel == null) {
+ return false;
+ }
+ // Delete all sound models for the given keyphrase and specified user.
+ SQLiteDatabase db = getWritableDatabase();
+ String soundModelClause = GenericSoundModelContract.KEY_MODEL_UUID
+ + "='" + soundModel.uuid.toString() + "'";
+ try {
+ return db.delete(GenericSoundModelContract.TABLE, soundModelClause, null) != 0;
+ } finally {
+ db.close();
+ }
+ }
+ }
+}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
similarity index 99%
rename from services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
rename to services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 31d859f..597f915ec 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.voiceinteraction;
+package com.android.server.soundtrigger;
import android.content.BroadcastReceiver;
import android.content.Context;
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
new file mode 100644
index 0000000..0a06bfa
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
@@ -0,0 +1,84 @@
+/**
+ * Copyright (C) 2014 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.soundtrigger;
+
+import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.hardware.soundtrigger.SoundTrigger.Keyphrase;
+import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionEvent;
+import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra;
+import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
+import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
+import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
+import android.hardware.soundtrigger.SoundTrigger.RecognitionEvent;
+import android.hardware.soundtrigger.SoundTrigger.SoundModelEvent;
+import android.hardware.soundtrigger.SoundTriggerModule;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Provides a local service for managing voice-related recoginition models. This is primarily used
+ * by the {@link VoiceInteractionManagerService}.
+ */
+public abstract class SoundTriggerInternal {
+ /**
+ * Return codes for {@link #startRecognition(int, KeyphraseSoundModel,
+ * IRecognitionStatusCallback, RecognitionConfig)},
+ * {@link #stopRecognition(int, IRecognitionStatusCallback)}
+ */
+ public static final int STATUS_ERROR = SoundTrigger.STATUS_ERROR;
+ public static final int STATUS_OK = SoundTrigger.STATUS_OK;
+
+ /** The {@link ModuleProperties} for the system, or null if none exists. */
+ private ModuleProperties moduleProperties;
+
+ /**
+ * Starts recognition for the given keyphraseId.
+ *
+ * @param keyphraseId The identifier of the keyphrase for which
+ * the recognition is to be started.
+ * @param soundModel The sound model to use for recognition.
+ * @param listener The listener for the recognition events related to the given keyphrase.
+ * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
+ */
+ public abstract int startRecognition(int keyphraseId, KeyphraseSoundModel soundModel,
+ IRecognitionStatusCallback listener, RecognitionConfig recognitionConfig);
+
+ /**
+ * Stops recognition for the given {@link Keyphrase} if a recognition is
+ * currently active.
+ *
+ * @param keyphraseId The identifier of the keyphrase for which
+ * the recognition is to be stopped.
+ * @param listener The listener for the recognition events related to the given keyphrase.
+ *
+ * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
+ */
+ public abstract int stopRecognition(int keyphraseId, IRecognitionStatusCallback listener);
+
+ /**
+ * Stops all recognitions active currently and clears the internal state.
+ */
+ public abstract void stopAllRecognitions();
+
+ public ModuleProperties getModuleProperties() {
+ return moduleProperties;
+ }
+
+ public abstract void dump(FileDescriptor fd, PrintWriter pw, String[] args);
+}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
new file mode 100644
index 0000000..5e8fe9e
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2014 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.soundtrigger;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.Manifest;
+import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
+import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
+import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
+import android.os.Parcel;
+import android.os.ParcelUuid;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.server.SystemService;
+import com.android.internal.app.ISoundTriggerService;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.UUID;
+
+/**
+ * A single SystemService to manage all sound/voice-based sound models on the DSP.
+ * This services provides apis to manage sound trigger-based sound models via
+ * the ISoundTriggerService interface. This class also publishes a local interface encapsulating
+ * the functionality provided by {@link SoundTriggerHelper} for use by
+ * {@link VoiceInteractionManagerService}.
+ *
+ * @hide
+ */
+public class SoundTriggerService extends SystemService {
+ static final String TAG = "SoundTriggerService";
+ static final boolean DEBUG = false;
+
+ final Context mContext;
+ private final SoundTriggerServiceStub mServiceStub;
+ private final LocalSoundTriggerService mLocalSoundTriggerService;
+ private SoundTriggerDbHelper mDbHelper;
+
+ public SoundTriggerService(Context context) {
+ super(context);
+ mContext = context;
+ mServiceStub = new SoundTriggerServiceStub();
+ mLocalSoundTriggerService = new LocalSoundTriggerService(context);
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.SOUND_TRIGGER_SERVICE, mServiceStub);
+ publishLocalService(SoundTriggerInternal.class, mLocalSoundTriggerService);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (PHASE_SYSTEM_SERVICES_READY == phase) {
+ mLocalSoundTriggerService.initSoundTriggerHelper();
+ } else if (PHASE_THIRD_PARTY_APPS_CAN_START == phase) {
+ mDbHelper = new SoundTriggerDbHelper(mContext);
+ }
+ }
+
+ @Override
+ public void onStartUser(int userHandle) {
+ }
+
+ @Override
+ public void onSwitchUser(int userHandle) {
+ }
+
+ class SoundTriggerServiceStub extends ISoundTriggerService.Stub {
+ @Override
+ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+ throws RemoteException {
+ try {
+ return super.onTransact(code, data, reply, flags);
+ } catch (RuntimeException e) {
+ // The activity manager only throws security exceptions, so let's
+ // log all others.
+ if (!(e instanceof SecurityException)) {
+ Slog.wtf(TAG, "SoundTriggerService Crash", e);
+ }
+ throw e;
+ }
+ }
+
+ @Override
+ public void startRecognition(ParcelUuid parcelUuid, IRecognitionStatusCallback callback) {
+ enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+ if (DEBUG) {
+ Slog.i(TAG, "startRecognition(): Uuid : " + parcelUuid);
+ }
+ }
+
+ @Override
+ public void stopRecognition(ParcelUuid parcelUuid, IRecognitionStatusCallback callback) {
+ enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+ if (DEBUG) {
+ Slog.i(TAG, "stopRecognition(): Uuid : " + parcelUuid);
+ }
+ }
+
+ @Override
+ public SoundTrigger.GenericSoundModel getSoundModel(ParcelUuid soundModelId) {
+ enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+ if (DEBUG) {
+ Slog.i(TAG, "getSoundModel(): id = " + soundModelId);
+ }
+ SoundTrigger.GenericSoundModel model = mDbHelper.getGenericSoundModel(soundModelId.getUuid());
+ if (model == null) {
+ Slog.e(TAG, "Null model in database.");
+ }
+ return model;
+ }
+
+ @Override
+ public void updateSoundModel(SoundTrigger.GenericSoundModel soundModel) {
+ enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+ if (DEBUG) {
+ Slog.i(TAG, "updateSoundModel(): model = " + soundModel);
+ }
+ mDbHelper.updateGenericSoundModel(soundModel);
+ }
+
+ @Override
+ public void deleteSoundModel(ParcelUuid soundModelId) {
+ enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+ if (DEBUG) {
+ Slog.i(TAG, "deleteSoundModel(): id = " + soundModelId);
+ }
+ mDbHelper.deleteGenericSoundModel(soundModelId.getUuid());
+ }
+ }
+
+ public final class LocalSoundTriggerService extends SoundTriggerInternal {
+ private final Context mContext;
+ private SoundTriggerHelper mSoundTriggerHelper;
+
+ LocalSoundTriggerService(Context context) {
+ mContext = context;
+ }
+
+ void initSoundTriggerHelper() {
+ if (mSoundTriggerHelper == null) {
+ mSoundTriggerHelper = new SoundTriggerHelper(mContext);
+ }
+ }
+
+ @Override
+ public int startRecognition(int keyphraseId, KeyphraseSoundModel soundModel,
+ IRecognitionStatusCallback listener, RecognitionConfig recognitionConfig) {
+ return mSoundTriggerHelper.startRecognition(keyphraseId, soundModel, listener,
+ recognitionConfig);
+ }
+
+ @Override
+ public int stopRecognition(int keyphraseId, IRecognitionStatusCallback listener) {
+ return mSoundTriggerHelper.stopRecognition(keyphraseId, listener);
+ }
+
+ @Override
+ public void stopAllRecognitions() {
+ mSoundTriggerHelper.stopAllRecognitions();
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ mSoundTriggerHelper.dump(fd, pw, args);
+ }
+ }
+
+ private void enforceCallingPermission(String permission) {
+ if (mContext.checkCallingOrSelfPermission(permission)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Caller does not hold the permission " + permission);
+ }
+ }
+}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 2aef109..4a54643 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -62,6 +62,7 @@
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
import com.android.server.LocalServices;
+import com.android.server.soundtrigger.SoundTriggerInternal;
import com.android.server.SystemService;
import com.android.server.UiThread;
@@ -79,15 +80,14 @@
final Context mContext;
final ContentResolver mResolver;
final DatabaseHelper mDbHelper;
- final SoundTriggerHelper mSoundTriggerHelper;
final ActivityManagerInternal mAmInternal;
+ SoundTriggerInternal mSoundTriggerInternal;
public VoiceInteractionManagerService(Context context) {
super(context);
mContext = context;
mResolver = context.getContentResolver();
mDbHelper = new DatabaseHelper(context);
- mSoundTriggerHelper = new SoundTriggerHelper(context);
mServiceStub = new VoiceInteractionManagerServiceStub();
mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
@@ -115,7 +115,9 @@
@Override
public void onBootPhase(int phase) {
- if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+ if (PHASE_SYSTEM_SERVICES_READY == phase) {
+ mSoundTriggerInternal = LocalServices.getService(SoundTriggerInternal.class);
+ } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
mServiceStub.systemRunning(isSafeMode());
}
}
@@ -380,7 +382,7 @@
if (force || mImpl == null || mImpl.mUser != mCurUser
|| !mImpl.mComponent.equals(serviceComponent)) {
- mSoundTriggerHelper.stopAllRecognitions();
+ mSoundTriggerInternal.stopAllRecognitions();
if (mImpl != null) {
mImpl.shutdownLocked();
}
@@ -736,9 +738,9 @@
mImpl.notifySoundModelsChangedLocked();
}
}
- return SoundTriggerHelper.STATUS_OK;
+ return SoundTriggerInternal.STATUS_OK;
} else {
- return SoundTriggerHelper.STATUS_ERROR;
+ return SoundTriggerInternal.STATUS_ERROR;
}
} finally {
Binder.restoreCallingIdentity(caller);
@@ -759,7 +761,7 @@
boolean deleted = false;
try {
deleted = mDbHelper.deleteKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
- return deleted ? SoundTriggerHelper.STATUS_OK : SoundTriggerHelper.STATUS_ERROR;
+ return deleted ? SoundTriggerInternal.STATUS_OK : SoundTriggerInternal.STATUS_ERROR;
} finally {
if (deleted) {
synchronized (this) {
@@ -812,7 +814,7 @@
final long caller = Binder.clearCallingIdentity();
try {
- return mSoundTriggerHelper.moduleProperties;
+ return mSoundTriggerInternal.getModuleProperties();
} finally {
Binder.restoreCallingIdentity(caller);
}
@@ -845,9 +847,9 @@
|| soundModel.uuid == null
|| soundModel.keyphrases == null) {
Slog.w(TAG, "No matching sound model found in startRecognition");
- return SoundTriggerHelper.STATUS_ERROR;
+ return SoundTriggerInternal.STATUS_ERROR;
} else {
- return mSoundTriggerHelper.startRecognition(
+ return mSoundTriggerInternal.startRecognition(
keyphraseId, soundModel, callback, recognitionConfig);
}
} finally {
@@ -869,7 +871,7 @@
final long caller = Binder.clearCallingIdentity();
try {
- return mSoundTriggerHelper.stopRecognition(keyphraseId, callback);
+ return mSoundTriggerInternal.stopRecognition(keyphraseId, callback);
} finally {
Binder.restoreCallingIdentity(caller);
}
@@ -1011,7 +1013,7 @@
}
mImpl.dumpLocked(fd, pw, args);
}
- mSoundTriggerHelper.dump(fd, pw, args);
+ mSoundTriggerInternal.dump(fd, pw, args);
}
private void enforceCallingPermission(String permission) {
@@ -1060,7 +1062,7 @@
// The user is force stopping our current interactor/recognizer.
// Clear the current settings and restore default state.
synchronized (VoiceInteractionManagerService.this) {
- mSoundTriggerHelper.stopAllRecognitions();
+ mSoundTriggerInternal.stopAllRecognitions();
if (mImpl != null) {
mImpl.shutdownLocked();
mImpl = null;
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 3859294..de90202 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -265,6 +265,7 @@
// Next PROPERTY value: 0x00000040
//******************************************************************************************
+ private final String mTelecomCallId;
private final Uri mHandle;
private final int mHandlePresentation;
private final String mCallerDisplayName;
@@ -414,6 +415,11 @@
return builder.toString();
}
+ /** {@hide} */
+ public String getTelecomCallId() {
+ return mTelecomCallId;
+ }
+
/**
* @return The handle (e.g., phone number) to which the {@code Call} is currently
* connected.
@@ -567,6 +573,7 @@
/** {@hide} */
public Details(
+ String telecomCallId,
Uri handle,
int handlePresentation,
String callerDisplayName,
@@ -581,6 +588,7 @@
StatusHints statusHints,
Bundle extras,
Bundle intentExtras) {
+ mTelecomCallId = telecomCallId;
mHandle = handle;
mHandlePresentation = handlePresentation;
mCallerDisplayName = callerDisplayName;
@@ -596,6 +604,26 @@
mExtras = extras;
mIntentExtras = intentExtras;
}
+
+ /** {@hide} */
+ public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
+ return new Details(
+ parcelableCall.getId(),
+ parcelableCall.getHandle(),
+ parcelableCall.getHandlePresentation(),
+ parcelableCall.getCallerDisplayName(),
+ parcelableCall.getCallerDisplayNamePresentation(),
+ parcelableCall.getAccountHandle(),
+ parcelableCall.getCapabilities(),
+ parcelableCall.getProperties(),
+ parcelableCall.getDisconnectCause(),
+ parcelableCall.getConnectTimeMillis(),
+ parcelableCall.getGatewayInfo(),
+ parcelableCall.getVideoState(),
+ parcelableCall.getStatusHints(),
+ parcelableCall.getExtras(),
+ parcelableCall.getIntentExtras());
+ }
}
public static abstract class Callback {
@@ -1022,21 +1050,7 @@
/** {@hide} */
final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
// First, we update the internal state as far as possible before firing any updates.
- Details details = new Details(
- parcelableCall.getHandle(),
- parcelableCall.getHandlePresentation(),
- parcelableCall.getCallerDisplayName(),
- parcelableCall.getCallerDisplayNamePresentation(),
- parcelableCall.getAccountHandle(),
- parcelableCall.getCapabilities(),
- parcelableCall.getProperties(),
- parcelableCall.getDisconnectCause(),
- parcelableCall.getConnectTimeMillis(),
- parcelableCall.getGatewayInfo(),
- parcelableCall.getVideoState(),
- parcelableCall.getStatusHints(),
- parcelableCall.getExtras(),
- parcelableCall.getIntentExtras());
+ Details details = Details.createFromParcelableCall(parcelableCall);
boolean detailsChanged = !Objects.equals(mDetails, details);
if (detailsChanged) {
mDetails = details;
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
new file mode 100644
index 0000000..1b6e162
--- /dev/null
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 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
+ */
+
+package android.telecom;
+
+import android.annotation.SdkConstant;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+
+import com.android.internal.os.SomeArgs;
+import com.android.internal.telecom.ICallScreeningService;
+import com.android.internal.telecom.ICallScreeningAdapter;
+
+/**
+ * This service can be implemented by the default dialer (see
+ * {@link TelecomManager#getDefaultDialerPackage()}) to allow or disallow incoming calls before
+ * they are shown to a user.
+ * <p>
+ * Below is an example manifest registration for a {@code CallScreeningService}.
+ * <pre>
+ * {@code
+ * <service android:name="your.package.YourCallScreeningServiceImplementation"
+ * android:permission="android.permission.BIND_SCREENING_SERVICE">
+ * <intent-filter>
+ * <action android:name="android.telecom.CallScreeningService"/>
+ * </intent-filter>
+ * </service>
+ * }
+ * </pre>
+ */
+public abstract class CallScreeningService extends Service {
+ /**
+ * The {@link Intent} that must be declared as handled by the service.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String SERVICE_INTERFACE = "android.telecom.CallScreeningService";
+
+ private static final int MSG_SCREEN_CALL = 1;
+
+ private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_SCREEN_CALL:
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ mCallScreeningAdapter = (ICallScreeningAdapter) args.arg1;
+ onScreenCall(
+ Call.Details.createFromParcelableCall((ParcelableCall) args.arg2));
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
+ }
+ };
+
+ private final class CallScreeningBinder extends ICallScreeningService.Stub {
+ @Override
+ public void screenCall(ICallScreeningAdapter adapter, ParcelableCall call) {
+ Log.v(this, "screenCall");
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = adapter;
+ args.arg2 = call;
+ mHandler.obtainMessage(MSG_SCREEN_CALL, args).sendToTarget();
+ }
+ }
+
+ private ICallScreeningAdapter mCallScreeningAdapter;
+
+ /*
+ * Information about how to respond to an incoming call.
+ */
+ public class CallResponse {
+ private final boolean mShouldDisallowCall;
+ private final boolean mShouldRejectCall;
+ private final boolean mShouldSkipCallLog;
+ private final boolean mShouldSkipNotification;
+
+ private CallResponse(
+ boolean shouldDisallowCall,
+ boolean shouldRejectCall,
+ boolean shouldSkipCallLog,
+ boolean shouldSkipNotification) {
+ if (!shouldDisallowCall
+ && (shouldRejectCall || shouldSkipCallLog || shouldSkipNotification)) {
+ throw new IllegalStateException("Invalid response state for allowed call.");
+ }
+
+ mShouldDisallowCall = shouldDisallowCall;
+ mShouldRejectCall = shouldRejectCall;
+ mShouldSkipCallLog = shouldSkipCallLog;
+ mShouldSkipNotification = shouldSkipNotification;
+ }
+
+ /*
+ * @return Whether the incoming call should be blocked.
+ */
+ public boolean getDisallowCall() {
+ return mShouldDisallowCall;
+ }
+
+ /*
+ * @return Whether the incoming call should be disconnected as if the user had manually
+ * rejected it.
+ */
+ public boolean getRejectCall() {
+ return mShouldRejectCall;
+ }
+
+ /*
+ * @return Whether the incoming call should not be displayed in the call log.
+ */
+ public boolean getSkipCallLog() {
+ return mShouldSkipCallLog;
+ }
+
+ /*
+ * @return Whether a missed call notification should not be shown for the incoming call.
+ */
+ public boolean getSkipNotification() {
+ return mShouldSkipNotification;
+ }
+
+ public class Builder {
+ private boolean mShouldDisallowCall;
+ private boolean mShouldRejectCall;
+ private boolean mShouldSkipCallLog;
+ private boolean mShouldSkipNotification;
+
+ /*
+ * Sets whether the incoming call should be blocked.
+ */
+ public Builder setDisallowCall(boolean shouldDisallowCall) {
+ mShouldDisallowCall = shouldDisallowCall;
+ return this;
+ }
+
+ /*
+ * Sets whether the incoming call should be disconnected as if the user had manually
+ * rejected it. This property should only be set to true if the call is disallowed.
+ */
+ public Builder setRejectCall(boolean shouldRejectCall) {
+ mShouldRejectCall = shouldRejectCall;
+ return this;
+ }
+
+ /*
+ * Sets whether the incoming call should not be displayed in the call log. This property
+ * should only be set to true if the call is disallowed.
+ */
+ public Builder setSkipCallLog(boolean shouldSkipCallLog) {
+ mShouldSkipCallLog = shouldSkipCallLog;
+ return this;
+ }
+
+ /*
+ * Sets whether a missed call notification should not be shown for the incoming call.
+ * This property should only be set to true if the call is disallowed.
+ */
+ public Builder setSkipNotification(boolean shouldSkipNotification) {
+ mShouldSkipNotification = shouldSkipNotification;
+ return this;
+ }
+
+ public CallResponse build() {
+ return new CallResponse(
+ mShouldDisallowCall,
+ mShouldRejectCall,
+ mShouldSkipCallLog,
+ mShouldSkipNotification);
+ }
+ }
+ }
+
+ public CallScreeningService() {
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ Log.v(this, "onBind");
+ return new CallScreeningBinder();
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ Log.v(this, "onUnbind");
+ return false;
+ }
+
+ /**
+ * Called when a new incoming call is added.
+ * {@link CallScreeningService#respondToCall(Call.Details, CallScreeningService.CallResponse)}
+ * should be called to allow or disallow the call.
+ *
+ * @param callDetails Information about a new incoming call, see {@link Call.Details}.
+ */
+ public abstract void onScreenCall(Call.Details callDetails);
+
+ /**
+ * Responds to the given call, either allowing it or disallowing it.
+ *
+ * @param callDetails The call to allow.
+ * @param response The {@link CallScreeningService.CallResponse} which contains information
+ * about how to respond to a call.
+ */
+ public final void respondToCall(Call.Details callDetails, CallResponse response) {
+ try {
+ if (response.getDisallowCall()) {
+ mCallScreeningAdapter.disallowCall(
+ callDetails.getTelecomCallId(),
+ response.getRejectCall(),
+ !response.getSkipCallLog(),
+ !response.getSkipNotification());
+ } else {
+ mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId());
+ }
+ } catch (RemoteException e) {
+ }
+ }
+}
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 426b240..671399b 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -73,6 +73,7 @@
private static final int MSG_ON_CALL_AUDIO_STATE_CHANGED = 5;
private static final int MSG_BRING_TO_FOREGROUND = 6;
private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7;
+ private static final int MSG_SILENCE_RINGER = 8;
/** Default Handler used to consolidate binder method calls onto a single thread. */
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -114,6 +115,9 @@
case MSG_ON_CAN_ADD_CALL_CHANGED:
mPhone.internalSetCanAddCall(msg.arg1 == 1);
break;
+ case MSG_SILENCE_RINGER:
+ mPhone.internalSilenceRinger();
+ break;
default:
break;
}
@@ -165,6 +169,11 @@
mHandler.obtainMessage(MSG_ON_CAN_ADD_CALL_CHANGED, canAddCall ? 1 : 0, 0)
.sendToTarget();
}
+
+ @Override
+ public void silenceRinger() {
+ mHandler.obtainMessage(MSG_SILENCE_RINGER).sendToTarget();
+ }
}
private Phone.Listener mPhoneListener = new Phone.Listener() {
@@ -202,6 +211,12 @@
InCallService.this.onCanAddCallChanged(canAddCall);
}
+ /** ${inheritDoc} */
+ @Override
+ public void onSilenceRinger(Phone phone) {
+ InCallService.this.onSilenceRinger();
+ }
+
};
private Phone mPhone;
@@ -405,6 +420,12 @@
}
/**
+ * Called to silence the ringer if a ringing call exists.
+ */
+ public void onSilenceRinger() {
+ }
+
+ /**
* Used to issue commands to the {@link Connection.VideoProvider} associated with a
* {@link Call}.
*/
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index 47154da..56eb7ec 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -97,6 +97,13 @@
* @param canAddCall Indicates whether an additional call can be added.
*/
public void onCanAddCallChanged(Phone phone, boolean canAddCall) { }
+
+ /**
+ * Called to silence the ringer if a ringing call exists.
+ *
+ * @param phone The {@code Phone} calling this method.
+ */
+ public void onSilenceRinger(Phone phone) { }
}
// A Map allows us to track each Call by its Telecom-specified call ID
@@ -179,6 +186,10 @@
}
}
+ final void internalSilenceRinger() {
+ fireSilenceRinger();
+ }
+
/**
* Called to destroy the phone and cleanup any lingering calls.
*/
@@ -330,6 +341,12 @@
}
}
+ private void fireSilenceRinger() {
+ for (Listener listener : mListeners) {
+ listener.onSilenceRinger(this);
+ }
+ }
+
private void checkCallTree(ParcelableCall parcelableCall) {
if (parcelableCall.getParentCallId() != null &&
!mCallByTelecomCallId.containsKey(parcelableCall.getParentCallId())) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 497864e..72ff272 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -308,6 +308,15 @@
"android.telecom.IN_CALL_SERVICE_CAR_MODE_UI";
/**
+ * A boolean meta-data value indicating whether an {@link InCallService} implements ringing.
+ * Dialer implementations (see {@link #getDefaultDialerPackage()}) which would also like to
+ * override the system provided ringing should set this meta-data to {@code true} in the
+ * manifest registration of their {@link InCallService}.
+ */
+ public static final String METADATA_IN_CALL_SERVICE_RINGING =
+ "android.telecom.IN_CALL_SERVICE_RINGING";
+
+ /**
* The dual tone multi-frequency signaling character sent to indicate the dialing system should
* pause for a predefined period.
*/
diff --git a/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl b/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl
new file mode 100644
index 0000000..2e0af27
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package com.android.internal.telecom;
+
+/**
+ * Internal remote callback interface for call screening services.
+ *
+ * @see android.telecom.CallScreeningService
+ *
+ * {@hide}
+ */
+oneway interface ICallScreeningAdapter {
+ void allowCall(String callId);
+
+ void disallowCall(
+ String callId,
+ boolean shouldReject,
+ boolean shouldAddToCallLog,
+ boolean shouldShowNotification);
+}
diff --git a/telecomm/java/com/android/internal/telecom/ICallScreeningService.aidl b/telecomm/java/com/android/internal/telecom/ICallScreeningService.aidl
new file mode 100644
index 0000000..c3fe1af
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecom/ICallScreeningService.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package com.android.internal.telecom;
+
+import android.telecom.ParcelableCall;
+
+import com.android.internal.telecom.ICallScreeningAdapter;
+
+/**
+ * Internal remote interface for a call screening service.
+ * @see android.telecom.CallScreeningService
+ * @hide
+ */
+oneway interface ICallScreeningService {
+ void screenCall(in ICallScreeningAdapter adapter, in ParcelableCall call);
+}
diff --git a/telecomm/java/com/android/internal/telecom/IInCallService.aidl b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
index ded47d5..0088e0c 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
@@ -45,4 +45,6 @@
void bringToForeground(boolean showDialpad);
void onCanAddCallChanged(boolean canAddCall);
+
+ void silenceRinger();
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 630dacc..4368b81 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -409,6 +409,11 @@
public static final String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN = "vvm_cellular_data_required";
/**
+ * Whether to prefetch audio data on new voicemail arrival, defaulted to true.
+ */
+ public static final String KEY_VVM_PREFETCH_BOOLEAN = "vvm_prefetch";
+
+ /**
* The package name of the carrier's visual voicemail app to ensure that dialer visual voicemail
* and carrier visual voicemail are not active at the same time.
*/
@@ -638,6 +643,7 @@
sDefaults.putInt(KEY_VVM_PORT_NUMBER_INT, 0);
sDefaults.putString(KEY_VVM_TYPE_STRING, "");
sDefaults.putBoolean(KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN,false);
+ sDefaults.putBoolean(KEY_VVM_PREFETCH_BOOLEAN,true);
sDefaults.putString(KEY_CARRIER_VVM_PACKAGE_NAME_STRING, "");
sDefaults.putBoolean(KEY_CI_ACTION_ON_SYS_UPDATE_BOOL, false);
sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING, "");
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 90d2aa0..74f1171 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -38,6 +38,10 @@
private final int mLac;
// 16-bit GSM Cell Identity described in TS 27.007, 0..65535
private final int mCid;
+ // 16-bit GSM Absolute RF Channel Number
+ private final int mArfcn;
+ // 6-bit Base Station Identity Code
+ private final int mBsic;
/**
* @hide
@@ -47,6 +51,8 @@
mMnc = Integer.MAX_VALUE;
mLac = Integer.MAX_VALUE;
mCid = Integer.MAX_VALUE;
+ mArfcn = Integer.MAX_VALUE;
+ mBsic = Integer.MAX_VALUE;
}
/**
* public constructor
@@ -58,10 +64,27 @@
* @hide
*/
public CellIdentityGsm (int mcc, int mnc, int lac, int cid) {
+ this(mcc, mnc, lac, cid, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ }
+
+ /**
+ * public constructor
+ * @param mcc 3-digit Mobile Country Code, 0..999
+ * @param mnc 2 or 3-digit Mobile Network Code, 0..999
+ * @param lac 16-bit Location Area Code, 0..65535
+ * @param cid 16-bit GSM Cell Identity or 28-bit UMTS Cell Identity
+ * @param arfcn 16-bit GSM Absolute RF Channel Number
+ * @param bsic 6-bit Base Station Identity Code
+ *
+ * @hide
+ */
+ public CellIdentityGsm (int mcc, int mnc, int lac, int cid, int arfcn, int bsic) {
mMcc = mcc;
mMnc = mnc;
mLac = lac;
mCid = cid;
+ mArfcn = arfcn;
+ mBsic = bsic;
}
private CellIdentityGsm(CellIdentityGsm cid) {
@@ -69,6 +92,8 @@
mMnc = cid.mMnc;
mLac = cid.mLac;
mCid = cid.mCid;
+ mArfcn = cid.mArfcn;
+ mBsic = cid.mBsic;
}
CellIdentityGsm copy() {
@@ -106,6 +131,21 @@
}
/**
+ * @return 16-bit GSM Absolute RF Channel Number, Integer.MAX_VALUE if unknown
+ */
+ public int getArfcn() {
+ return mArfcn;
+ }
+
+ /**
+ * @return 6-bit Base Station Identity Code, Integer.MAX_VALUE if unknown
+ */
+ public int getBsic() {
+ return mBsic;
+ }
+
+
+ /**
* @return Integer.MAX_VALUE, undefined for GSM
*/
@Deprecated
@@ -132,7 +172,9 @@
return mMcc == o.mMcc &&
mMnc == o.mMnc &&
mLac == o.mLac &&
- mCid == o.mCid;
+ mCid == o.mCid &&
+ mArfcn == o.mArfcn &&
+ mBsic == o.mBsic;
}
@Override
@@ -142,6 +184,8 @@
sb.append(" mMnc=").append(mMnc);
sb.append(" mLac=").append(mLac);
sb.append(" mCid=").append(mCid);
+ sb.append(" mArfcn=").append(mArfcn);
+ sb.append(" mBsic=").append("0x").append(Integer.toHexString(mBsic));
sb.append("}");
return sb.toString();
@@ -161,6 +205,8 @@
dest.writeInt(mMnc);
dest.writeInt(mLac);
dest.writeInt(mCid);
+ dest.writeInt(mArfcn);
+ dest.writeInt(mBsic);
}
/** Construct from Parcel, type has already been processed */
@@ -169,6 +215,8 @@
mMnc = in.readInt();
mLac = in.readInt();
mCid = in.readInt();
+ mArfcn = in.readInt();
+ mBsic = in.readInt();
if (DBG) log("CellIdentityGsm(Parcel): " + toString());
}
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 1e7ac08..ce74383 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -40,6 +40,8 @@
private final int mPci;
// 16-bit tracking area code
private final int mTac;
+ // 18-bit Absolute RF Channel Number
+ private final int mEarfcn;
/**
* @hide
@@ -50,6 +52,7 @@
mCi = Integer.MAX_VALUE;
mPci = Integer.MAX_VALUE;
mTac = Integer.MAX_VALUE;
+ mEarfcn = Integer.MAX_VALUE;
}
/**
@@ -63,11 +66,27 @@
* @hide
*/
public CellIdentityLte (int mcc, int mnc, int ci, int pci, int tac) {
+ this(mcc, mnc, ci, pci, tac, Integer.MAX_VALUE);
+ }
+
+ /**
+ *
+ * @param mcc 3-digit Mobile Country Code, 0..999
+ * @param mnc 2 or 3-digit Mobile Network Code, 0..999
+ * @param ci 28-bit Cell Identity
+ * @param pci Physical Cell Id 0..503
+ * @param tac 16-bit Tracking Area Code
+ * @param earfcn 18-bit LTE Absolute RF Channel Number
+ *
+ * @hide
+ */
+ public CellIdentityLte (int mcc, int mnc, int ci, int pci, int tac, int earfcn) {
mMcc = mcc;
mMnc = mnc;
mCi = ci;
mPci = pci;
mTac = tac;
+ mEarfcn = earfcn;
}
private CellIdentityLte(CellIdentityLte cid) {
@@ -76,6 +95,7 @@
mCi = cid.mCi;
mPci = cid.mPci;
mTac = cid.mTac;
+ mEarfcn = cid.mEarfcn;
}
CellIdentityLte copy() {
@@ -117,6 +137,13 @@
return mTac;
}
+ /**
+ * @return 18-bit Absolute RF Channel Number, Integer.MAX_VALUE if unknown
+ */
+ public int getEarfcn() {
+ return mEarfcn;
+ }
+
@Override
public int hashCode() {
return Objects.hash(mMcc, mMnc, mCi, mPci, mTac);
@@ -137,7 +164,8 @@
mMnc == o.mMnc &&
mCi == o.mCi &&
mPci == o.mPci &&
- mTac == o.mTac;
+ mTac == o.mTac &&
+ mEarfcn == o.mEarfcn;
}
@Override
@@ -148,6 +176,7 @@
sb.append(" mCi="); sb.append(mCi);
sb.append(" mPci="); sb.append(mPci);
sb.append(" mTac="); sb.append(mTac);
+ sb.append(" mEarfcn="); sb.append(mEarfcn);
sb.append("}");
return sb.toString();
@@ -168,6 +197,7 @@
dest.writeInt(mCi);
dest.writeInt(mPci);
dest.writeInt(mTac);
+ dest.writeInt(mEarfcn);
}
/** Construct from Parcel, type has already been processed */
@@ -177,6 +207,7 @@
mCi = in.readInt();
mPci = in.readInt();
mTac = in.readInt();
+ mEarfcn = in.readInt();
if (DBG) log("CellIdentityLte(Parcel): " + toString());
}
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 56ee8c9..0d13efd 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -40,6 +40,8 @@
private final int mCid;
// 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511
private final int mPsc;
+ // 16-bit UMTS Absolute RF Channel Number
+ private final int mUarfcn;
/**
* @hide
@@ -50,6 +52,7 @@
mLac = Integer.MAX_VALUE;
mCid = Integer.MAX_VALUE;
mPsc = Integer.MAX_VALUE;
+ mUarfcn = Integer.MAX_VALUE;
}
/**
* public constructor
@@ -62,11 +65,27 @@
* @hide
*/
public CellIdentityWcdma (int mcc, int mnc, int lac, int cid, int psc) {
+ this(mcc, mnc, lac, cid, psc, Integer.MAX_VALUE);
+ }
+
+ /**
+ * public constructor
+ * @param mcc 3-digit Mobile Country Code, 0..999
+ * @param mnc 2 or 3-digit Mobile Network Code, 0..999
+ * @param lac 16-bit Location Area Code, 0..65535
+ * @param cid 28-bit UMTS Cell Identity
+ * @param psc 9-bit UMTS Primary Scrambling Code
+ * @param uarfcn 16-bit UMTS Absolute RF Channel Number
+ *
+ * @hide
+ */
+ public CellIdentityWcdma (int mcc, int mnc, int lac, int cid, int psc, int uarfcn) {
mMcc = mcc;
mMnc = mnc;
mLac = lac;
mCid = cid;
mPsc = psc;
+ mUarfcn = uarfcn;
}
private CellIdentityWcdma(CellIdentityWcdma cid) {
@@ -75,6 +94,7 @@
mLac = cid.mLac;
mCid = cid.mCid;
mPsc = cid.mPsc;
+ mUarfcn = cid.mUarfcn;
}
CellIdentityWcdma copy() {
@@ -123,6 +143,13 @@
return Objects.hash(mMcc, mMnc, mLac, mCid, mPsc);
}
+ /**
+ * @return 16-bit UMTS Absolute RF Channel Number, Integer.MAX_VALUE if unknown
+ */
+ public int getUarfcn() {
+ return mUarfcn;
+ }
+
@Override
public boolean equals(Object other) {
if (this == other) {
@@ -138,7 +165,8 @@
mMnc == o.mMnc &&
mLac == o.mLac &&
mCid == o.mCid &&
- mPsc == o.mPsc;
+ mPsc == o.mPsc &&
+ mUarfcn == o.mUarfcn;
}
@Override
@@ -149,6 +177,7 @@
sb.append(" mLac=").append(mLac);
sb.append(" mCid=").append(mCid);
sb.append(" mPsc=").append(mPsc);
+ sb.append(" mUarfcn=").append(mUarfcn);
sb.append("}");
return sb.toString();
@@ -169,6 +198,7 @@
dest.writeInt(mLac);
dest.writeInt(mCid);
dest.writeInt(mPsc);
+ dest.writeInt(mUarfcn);
}
/** Construct from Parcel, type has already been processed */
@@ -178,6 +208,7 @@
mLac = in.readInt();
mCid = in.readInt();
mPsc = in.readInt();
+ mUarfcn = in.readInt();
if (DBG) log("CellIdentityWcdma(Parcel): " + toString());
}
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index d27fcec..addf7ef 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -34,6 +34,7 @@
private int mSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5
+ private int mTimingAdvance;
/**
* Empty constructor
@@ -75,6 +76,22 @@
public void initialize(int ss, int ber) {
mSignalStrength = ss;
mBitErrorRate = ber;
+ mTimingAdvance = Integer.MAX_VALUE;
+ }
+
+ /**
+ * Initialize all the values
+ *
+ * @param ss SignalStrength as ASU value
+ * @param ber is Bit Error Rate
+ * @param ta timing advance
+ *
+ * @hide
+ */
+ public void initialize(int ss, int ber, int ta) {
+ mSignalStrength = ss;
+ mBitErrorRate = ber;
+ mTimingAdvance = ta;
}
/**
@@ -83,6 +100,7 @@
protected void copyFrom(CellSignalStrengthGsm s) {
mSignalStrength = s.mSignalStrength;
mBitErrorRate = s.mBitErrorRate;
+ mTimingAdvance = s.mTimingAdvance;
}
/**
@@ -98,6 +116,7 @@
public void setDefaultValues() {
mSignalStrength = Integer.MAX_VALUE;
mBitErrorRate = Integer.MAX_VALUE;
+ mTimingAdvance = Integer.MAX_VALUE;
}
/**
@@ -174,7 +193,8 @@
return false;
}
- return mSignalStrength == s.mSignalStrength && mBitErrorRate == s.mBitErrorRate;
+ return mSignalStrength == s.mSignalStrength && mBitErrorRate == s.mBitErrorRate &&
+ s.mTimingAdvance == mTimingAdvance;
}
/**
@@ -184,7 +204,8 @@
public String toString() {
return "CellSignalStrengthGsm:"
+ " ss=" + mSignalStrength
- + " ber=" + mBitErrorRate;
+ + " ber=" + mBitErrorRate
+ + " mTa=" + mTimingAdvance;
}
/** Implement the Parcelable interface */
@@ -193,6 +214,7 @@
if (DBG) log("writeToParcel(Parcel, int): " + toString());
dest.writeInt(mSignalStrength);
dest.writeInt(mBitErrorRate);
+ dest.writeInt(mTimingAdvance);
}
/**
@@ -202,6 +224,7 @@
private CellSignalStrengthGsm(Parcel in) {
mSignalStrength = in.readInt();
mBitErrorRate = in.readInt();
+ mTimingAdvance = in.readInt();
if (DBG) log("CellSignalStrengthGsm(Parcel): " + toString());
}
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index ea96e7c..c65e8ba 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -58,6 +58,7 @@
return "ModemActivityInfo{"
+ " mTimestamp=" + mTimestamp
+ " mSleepTimeMs=" + mSleepTimeMs
+ + " mIdleTimeMs=" + mIdleTimeMs
+ " mTxTimeMs[]=" + Arrays.toString(mTxTimeMs)
+ " mRxTimeMs=" + mRxTimeMs
+ " mEnergyUsed=" + mEnergyUsed
@@ -153,7 +154,7 @@
for (int i = 0; i < TX_POWER_LEVELS; i++) {
totalTxTimeMs += txTime[i];
}
- return ((getIdleTimeMillis() != 0) || (totalTxTimeMs != 0)
- || (getSleepTimeMillis() != 0) || (getIdleTimeMillis() != 0));
+ return ((getIdleTimeMillis() >= 0) && (totalTxTimeMs >= 0)
+ && (getSleepTimeMillis() >= 0) && (getIdleTimeMillis() >= 0));
}
}
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index b089387..962a600 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1857,9 +1857,6 @@
// to the list.
number = extractNetworkPortionAlt(number);
- Rlog.d(LOG_TAG, "subId:" + subId + ", defaultCountryIso:" +
- ((defaultCountryIso == null) ? "NULL" : defaultCountryIso));
-
String emergencyNumbers = "";
int slotId = SubscriptionManager.getSlotId(subId);
@@ -1869,7 +1866,8 @@
emergencyNumbers = SystemProperties.get(ecclist, "");
- Rlog.d(LOG_TAG, "slotId:" + slotId + ", emergencyNumbers: " + emergencyNumbers);
+ Rlog.d(LOG_TAG, "slotId:" + slotId + " subId:" + subId + " country:"
+ + defaultCountryIso + " emergencyNumbers: " + emergencyNumbers);
if (TextUtils.isEmpty(emergencyNumbers)) {
// then read-only ecclist property since old RIL only uses this
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index c680999..ad007c6 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -37,6 +37,7 @@
static final String LOG_TAG = "PHONE";
static final boolean DBG = true;
+ static final boolean VDBG = false; // STOPSHIP if true
/**
* Normal operation condition, the phone is registered
@@ -829,7 +830,7 @@
/** @hide */
public void setDataRegState(int state) {
mDataRegState = state;
- if (DBG) Rlog.d(LOG_TAG, "[ServiceState] setDataRegState=" + mDataRegState);
+ if (VDBG) Rlog.d(LOG_TAG, "[ServiceState] setDataRegState=" + mDataRegState);
}
public void setRoaming(boolean roaming) {
@@ -1017,7 +1018,8 @@
/** @hide */
public void setRilDataRadioTechnology(int rt) {
this.mRilDataRadioTechnology = rt;
- if (DBG) Rlog.d(LOG_TAG, "[ServiceState] setDataRadioTechnology=" + mRilDataRadioTechnology);
+ if (VDBG) Rlog.d(LOG_TAG, "[ServiceState] setRilDataRadioTechnology=" +
+ mRilDataRadioTechnology);
}
/** @hide */
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 3c4c04b..7d5645e 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -336,6 +336,8 @@
int RIL_REQUEST_PULL_LCEDATA = 134;
int RIL_REQUEST_GET_ACTIVITY_INFO = 135;
+ int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
+
int RIL_UNSOL_RESPONSE_BASE = 1000;
int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000;
int RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED = 1001;
diff --git a/tests/SoundTriggerTestApp/Android.mk b/tests/SoundTriggerTestApp/Android.mk
new file mode 100644
index 0000000..7bcab5e
--- /dev/null
+++ b/tests/SoundTriggerTestApp/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := SoundTriggerTestApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_PRIVILEGED_MODULE := true
+
+include $(BUILD_PACKAGE)
diff --git a/tests/SoundTriggerTestApp/AndroidManifest.xml b/tests/SoundTriggerTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..40619da
--- /dev/null
+++ b/tests/SoundTriggerTestApp/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.soundtrigger">
+
+ <uses-permission android:name="android.permission.MANAGE_SOUND_TRIGGER" />
+ <application
+ android:permission="android.permission.MANAGE_SOUND_TRIGGER">
+ <activity
+ android:name="TestSoundTriggerActivity"
+ android:label="SoundTrigger Test Application"
+ android:theme="@android:style/Theme.Material.Light.Voice">
+ <intent-filter>
+ <action android:name="com.android.intent.action.MANAGE_SOUND_TRIGGER" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/SoundTriggerTestApp/res/layout/main.xml b/tests/SoundTriggerTestApp/res/layout/main.xml
new file mode 100644
index 0000000..9d2b9d9
--- /dev/null
+++ b/tests/SoundTriggerTestApp/res/layout/main.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 Google Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/enroll"
+ android:onClick="onEnrollButtonClicked"
+ android:padding="20dp" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/reenroll"
+ android:onClick="onReEnrollButtonClicked"
+ android:padding="20dp" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/unenroll"
+ android:onClick="onUnEnrollButtonClicked"
+ android:padding="20dp" />
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/SoundTriggerTestApp/res/values/strings.xml b/tests/SoundTriggerTestApp/res/values/strings.xml
new file mode 100644
index 0000000..07bac2a
--- /dev/null
+++ b/tests/SoundTriggerTestApp/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 Google Inc.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <string name="enroll">Enroll</string>
+ <string name="reenroll">Re-enroll</string>
+ <string name="unenroll">Un-enroll</string>
+</resources>
\ No newline at end of file
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java
new file mode 100644
index 0000000..4702835
--- /dev/null
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2014 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.test.soundtrigger;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
+import android.media.soundtrigger.SoundTriggerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import com.android.internal.app.ISoundTriggerService;
+
+import java.util.UUID;
+
+/**
+ * Utility class for the managing sound trigger sound models.
+ */
+public class SoundTriggerUtil {
+ private static final String TAG = "TestSoundTriggerUtil:Hotsound";
+
+ private final ISoundTriggerService mSoundTriggerService;
+ private final SoundTriggerManager mSoundTriggerManager;
+ private final Context mContext;
+
+ public SoundTriggerUtil(Context context) {
+ mSoundTriggerService = ISoundTriggerService.Stub.asInterface(
+ ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
+ mSoundTriggerManager = (SoundTriggerManager) context.getSystemService(
+ Context.SOUND_TRIGGER_SERVICE);
+ mContext = context;
+ }
+
+ /**
+ * Adds/Updates a sound model.
+ * The sound model must contain a valid UUID.
+ *
+ * @param soundModel The sound model to add/update.
+ */
+ public boolean addOrUpdateSoundModel(GenericSoundModel soundModel) {
+ try {
+ mSoundTriggerService.updateSoundModel(soundModel);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in updateSoundModel", e);
+ }
+ return true;
+ }
+
+ public void addOrUpdateSoundModel(SoundTriggerManager.Model soundModel) {
+ mSoundTriggerManager.updateModel(soundModel);
+ }
+
+ /**
+ * Gets the sound model for the given keyphrase, null if none exists.
+ * If a sound model for a given keyphrase exists, and it needs to be updated,
+ * it should be obtained using this method, updated and then passed in to
+ * {@link #addOrUpdateSoundModel(GenericSoundModel)} without changing the IDs.
+ *
+ * @param modelId The model ID to look-up the sound model for.
+ * @return The sound model if one was found, null otherwise.
+ */
+ @Nullable
+ public GenericSoundModel getSoundModel(UUID modelId) {
+ GenericSoundModel model = null;
+ try {
+ model = mSoundTriggerService.getSoundModel(new ParcelUuid(modelId));
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in updateKeyphraseSoundModel");
+ }
+
+ if (model == null) {
+ Log.w(TAG, "No models present for the gien keyphrase ID");
+ return null;
+ } else {
+ return model;
+ }
+ }
+
+ /**
+ * Deletes the sound model for the given keyphrase id.
+ *
+ * @param modelId The model ID to look-up the sound model for.
+ * @return {@code true} if the call succeeds, {@code false} otherwise.
+ */
+ @Nullable
+ public boolean deleteSoundModel(UUID modelId) {
+ try {
+ mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelId));
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in updateSoundModel");
+ }
+ return true;
+ }
+
+ public void deleteSoundModelUsingManager(UUID modelId) {
+ mSoundTriggerManager.deleteModel(modelId);
+ }
+}
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
new file mode 100644
index 0000000..966179b
--- /dev/null
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2014 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.test.soundtrigger;
+
+import java.util.Random;
+import java.util.UUID;
+
+import android.app.Activity;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
+import android.media.soundtrigger.SoundTriggerManager;
+import android.os.Bundle;
+import android.os.UserManager;
+import android.util.Log;
+import android.view.View;
+import android.widget.Toast;
+
+public class TestSoundTriggerActivity extends Activity {
+ private static final String TAG = "TestSoundTriggerActivity";
+ private static final boolean DBG = true;
+
+ private SoundTriggerUtil mSoundTriggerUtil;
+ private Random mRandom;
+ private UUID mModelUuid = UUID.randomUUID();
+ private UUID mModelUuid2 = UUID.randomUUID();
+ private UUID mVendorUuid = UUID.randomUUID();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ if (DBG) Log.d(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ mSoundTriggerUtil = new SoundTriggerUtil(this);
+ mRandom = new Random();
+ }
+
+ /**
+ * Called when the user clicks the enroll button.
+ * Performs a fresh enrollment.
+ */
+ public void onEnrollButtonClicked(View v) {
+ // Generate a fake model to push.
+ byte[] data = new byte[1024];
+ mRandom.nextBytes(data);
+ GenericSoundModel model = new GenericSoundModel(mModelUuid, mVendorUuid, data);
+
+ boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(model);
+ if (status) {
+ Toast.makeText(
+ this, "Successfully created sound trigger model UUID=" + mModelUuid, Toast.LENGTH_SHORT)
+ .show();
+ } else {
+ Toast.makeText(this, "Failed to enroll!!!" + mModelUuid, Toast.LENGTH_SHORT).show();
+ }
+
+ // Test the SoundManager API.
+ SoundTriggerManager.Model tmpModel = SoundTriggerManager.Model.create(mModelUuid2,
+ mVendorUuid, data);
+ mSoundTriggerUtil.addOrUpdateSoundModel(tmpModel);
+ }
+
+ /**
+ * Called when the user clicks the un-enroll button.
+ * Clears the enrollment information for the user.
+ */
+ public void onUnEnrollButtonClicked(View v) {
+ GenericSoundModel soundModel = mSoundTriggerUtil.getSoundModel(mModelUuid);
+ if (soundModel == null) {
+ Toast.makeText(this, "Sound model not found!!!", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ boolean status = mSoundTriggerUtil.deleteSoundModel(mModelUuid);
+ if (status) {
+ Toast.makeText(this, "Successfully deleted model UUID=" + soundModel.uuid,
+ Toast.LENGTH_SHORT)
+ .show();
+ } else {
+ Toast.makeText(this, "Failed to delete sound model!!!", Toast.LENGTH_SHORT).show();
+ }
+ mSoundTriggerUtil.deleteSoundModelUsingManager(mModelUuid2);
+ }
+
+ /**
+ * Called when the user clicks the re-enroll button.
+ * Uses the previously enrolled sound model and makes changes to it before pushing it back.
+ */
+ public void onReEnrollButtonClicked(View v) {
+ GenericSoundModel soundModel = mSoundTriggerUtil.getSoundModel(mModelUuid);
+ if (soundModel == null) {
+ Toast.makeText(this, "Sound model not found!!!", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ // Generate a fake model to push.
+ byte[] data = new byte[2048];
+ mRandom.nextBytes(data);
+ GenericSoundModel updated = new GenericSoundModel(soundModel.uuid,
+ soundModel.vendorUuid, data);
+ boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(updated);
+ if (status) {
+ Toast.makeText(this, "Successfully re-enrolled, model UUID=" + updated.uuid,
+ Toast.LENGTH_SHORT)
+ .show();
+ } else {
+ Toast.makeText(this, "Failed to re-enroll!!!", Toast.LENGTH_SHORT).show();
+ }
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index a3f3821..2000fbc 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -50,7 +50,7 @@
@Override
public void resized(Rect rect, Rect rect2, Rect rect3, Rect rect4, Rect rect5, Rect rect6,
- boolean b, Configuration configuration, Rect rect7) throws RemoteException {
+ boolean b, Configuration configuration, Rect rect7, boolean b2) throws RemoteException {
// pass for now.
}