Merge "Allow Path approximation to work with a single point Path." into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index fd72d34..b06951f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -588,6 +588,7 @@
field public static final int fastScrollThumbDrawable = 16843574; // 0x1010336
field public static final int fastScrollTrackDrawable = 16843577; // 0x1010339
field public static final int fillAfter = 16843197; // 0x10101bd
+ field public static final int fillAlpha = 16843981; // 0x10104cd
field public static final int fillBefore = 16843196; // 0x10101bc
field public static final int fillColor = 16843806; // 0x101041e
field public static final int fillEnabled = 16843343; // 0x101024f
@@ -1203,6 +1204,7 @@
field public static final int streamType = 16843273; // 0x1010209
field public static final int stretchColumns = 16843081; // 0x1010149
field public static final int stretchMode = 16843030; // 0x1010116
+ field public static final int strokeAlpha = 16843980; // 0x10104cc
field public static final int strokeColor = 16843808; // 0x1010420
field public static final int strokeLineCap = 16843813; // 0x1010425
field public static final int strokeLineJoin = 16843814; // 0x1010426
@@ -2395,7 +2397,6 @@
field public static final int Widget_Holo_DropDownItem_Spinner = 16973995; // 0x10300ab
field public static final int Widget_Holo_EditText = 16973971; // 0x1030093
field public static final int Widget_Holo_ExpandableListView = 16973972; // 0x1030094
- field public static final int Widget_Holo_FastScroll = 16974341; // 0x1030205
field public static final int Widget_Holo_GridView = 16973973; // 0x1030095
field public static final int Widget_Holo_HorizontalScrollView = 16973988; // 0x10300a4
field public static final int Widget_Holo_ImageButton = 16973974; // 0x1030096
@@ -2416,7 +2417,6 @@
field public static final int Widget_Holo_Light_ActionMode_Inverse = 16974119; // 0x1030127
field public static final int Widget_Holo_Light_AutoCompleteTextView = 16974011; // 0x10300bb
field public static final int Widget_Holo_Light_Button = 16974006; // 0x10300b6
- field public static final int Widget_Holo_Light_Button_Borderless = 16974343; // 0x1030207
field public static final int Widget_Holo_Light_Button_Borderless_Small = 16974107; // 0x103011b
field public static final int Widget_Holo_Light_Button_Inset = 16974008; // 0x10300b8
field public static final int Widget_Holo_Light_Button_Small = 16974007; // 0x10300b7
@@ -2430,7 +2430,6 @@
field public static final int Widget_Holo_Light_DropDownItem_Spinner = 16974041; // 0x10300d9
field public static final int Widget_Holo_Light_EditText = 16974014; // 0x10300be
field public static final int Widget_Holo_Light_ExpandableListView = 16974015; // 0x10300bf
- field public static final int Widget_Holo_Light_FastScroll = 16974344; // 0x1030208
field public static final int Widget_Holo_Light_GridView = 16974016; // 0x10300c0
field public static final int Widget_Holo_Light_HorizontalScrollView = 16974034; // 0x10300d2
field public static final int Widget_Holo_Light_ImageButton = 16974017; // 0x10300c1
@@ -2454,7 +2453,6 @@
field public static final int Widget_Holo_Light_ScrollView = 16974033; // 0x10300d1
field public static final int Widget_Holo_Light_SeekBar = 16974028; // 0x10300cc
field public static final int Widget_Holo_Light_Spinner = 16974035; // 0x10300d3
- field public static final int Widget_Holo_Light_StackView = 16974345; // 0x1030209
field public static final int Widget_Holo_Light_Tab = 16974052; // 0x10300e4
field public static final int Widget_Holo_Light_TabWidget = 16974037; // 0x10300d5
field public static final int Widget_Holo_Light_TextView = 16974010; // 0x10300ba
@@ -2478,7 +2476,6 @@
field public static final int Widget_Holo_ScrollView = 16973987; // 0x10300a3
field public static final int Widget_Holo_SeekBar = 16973982; // 0x103009e
field public static final int Widget_Holo_Spinner = 16973989; // 0x10300a5
- field public static final int Widget_Holo_StackView = 16974342; // 0x1030206
field public static final int Widget_Holo_Tab = 16974051; // 0x10300e3
field public static final int Widget_Holo_TabWidget = 16973991; // 0x10300a7
field public static final int Widget_Holo_TextView = 16973967; // 0x103008f
@@ -2579,6 +2576,7 @@
field public static final int Widget_Material_Light_RatingBar_Indicator = 16974531; // 0x10302c3
field public static final int Widget_Material_Light_RatingBar_Small = 16974532; // 0x10302c4
field public static final int Widget_Material_Light_ScrollView = 16974533; // 0x10302c5
+ field public static final int Widget_Material_Light_SearchView = 16974575; // 0x10302ef
field public static final int Widget_Material_Light_SeekBar = 16974534; // 0x10302c6
field public static final int Widget_Material_Light_SegmentedButton = 16974535; // 0x10302c7
field public static final int Widget_Material_Light_Spinner = 16974537; // 0x10302c9
@@ -2606,6 +2604,7 @@
field public static final int Widget_Material_RatingBar_Indicator = 16974468; // 0x1030284
field public static final int Widget_Material_RatingBar_Small = 16974469; // 0x1030285
field public static final int Widget_Material_ScrollView = 16974470; // 0x1030286
+ field public static final int Widget_Material_SearchView = 16974574; // 0x10302ee
field public static final int Widget_Material_SeekBar = 16974471; // 0x1030287
field public static final int Widget_Material_SegmentedButton = 16974472; // 0x1030288
field public static final int Widget_Material_Spinner = 16974474; // 0x103028a
@@ -2641,7 +2640,12 @@
field public static final int Widget_Toolbar = 16974339; // 0x1030203
field public static final int Widget_Toolbar_Button_Navigation = 16974340; // 0x1030204
field public static final int Widget_WebView = 16973875; // 0x1030033
- field public static final int __removed = 16974559; // 0x10302df
+ field public static final int __removed1 = 16974559; // 0x10302df
+ field public static final int __removed3 = 16974341; // 0x1030205
+ field public static final int __removed4 = 16974342; // 0x1030206
+ field public static final int __removed5 = 16974343; // 0x1030207
+ field public static final int __removed6 = 16974344; // 0x1030208
+ field public static final int __removed7 = 16974345; // 0x1030209
field public static final int l_resource_pad1 = 16974336; // 0x1030200
field public static final int l_resource_pad10 = 16974327; // 0x10301f7
field public static final int l_resource_pad11 = 16974326; // 0x10301f6
@@ -3792,7 +3796,6 @@
public class ActivityOptions {
method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
- method public static deprecated android.app.ActivityOptions makeLaunchTaskBehindAnimation();
method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.view.View, java.lang.String);
method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.util.Pair<android.view.View, java.lang.String>...);
@@ -5450,6 +5453,7 @@
method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]);
method public boolean hasGrantedPolicy(android.content.ComponentName, int);
method public boolean installCaCert(android.content.ComponentName, byte[]);
+ method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String);
method public boolean isActivePasswordSufficient();
method public boolean isAdminActive(android.content.ComponentName);
method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
@@ -5500,7 +5504,7 @@
method public void uninstallCaCert(android.content.ComponentName, byte[]);
method public void wipeData(int);
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
- field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.ACTION_PROVISION_MANAGED_PROFILE";
+ field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE";
field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD";
field public static final java.lang.String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION";
field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
@@ -5510,11 +5514,10 @@
field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
field public static final java.lang.String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
- field public static final java.lang.String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME = "android.app.extra.PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
- field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.deviceAdminPackageName";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE";
@@ -5526,8 +5529,8 @@
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_PORT = "android.app.extra.PROVISIONING_WIFI_PROXY_PORT";
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE";
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.PROVISIONING_WIFI_SSID";
- field public static int FLAG_MANAGED_CAN_ACCESS_PARENT;
- field public static int FLAG_PARENT_CAN_ACCESS_MANAGED;
+ field public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 2; // 0x2
+ field public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 1; // 0x1
field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
field public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0; // 0x0
field public static final int KEYGUARD_DISABLE_FINGERPRINT = 32; // 0x20
@@ -5681,6 +5684,7 @@
method public int describeContents();
method public android.os.PersistableBundle getExtras();
method public int getJobId();
+ method public boolean isOverrideDeadlineExpired();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
@@ -8617,21 +8621,16 @@
public class LauncherApps {
method public void addCallback(android.content.pm.LauncherApps.Callback);
- method public void addCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
- method public void addOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback);
- method public void addOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback, android.os.Handler);
method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
- method public boolean isActivityEnabledForProfile(android.content.ComponentName, android.os.UserHandle);
method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
- method public boolean isPackageEnabledForProfile(java.lang.String, android.os.UserHandle);
+ method public void registerCallback(android.content.pm.LauncherApps.Callback);
+ method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
method public void removeCallback(android.content.pm.LauncherApps.Callback);
- method public void removeOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback);
method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
- method public void showAppDetailsForProfile(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
- method public void startActivityForProfile(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
+ method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
}
public static abstract class LauncherApps.Callback {
@@ -8643,10 +8642,6 @@
method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean);
}
- public static abstract class LauncherApps.OnAppsChangedCallback extends android.content.pm.LauncherApps.Callback {
- ctor public LauncherApps.OnAppsChangedCallback();
- }
-
public class PackageInfo implements android.os.Parcelable {
ctor public PackageInfo();
method public int describeContents();
@@ -8901,6 +8896,7 @@
field public static final java.lang.String FEATURE_FAKETOUCH = "android.hardware.faketouch";
field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT = "android.hardware.faketouch.multitouch.distinct";
field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = "android.hardware.faketouch.multitouch.jazzhand";
+ field public static final java.lang.String FEATURE_GAMEPAD = "android.hardware.gamepad";
field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
@@ -8917,6 +8913,7 @@
field public static final java.lang.String FEATURE_PRINTING = "android.software.print";
field public static final java.lang.String FEATURE_SCREEN_LANDSCAPE = "android.hardware.screen.landscape";
field public static final java.lang.String FEATURE_SCREEN_PORTRAIT = "android.hardware.screen.portrait";
+ field public static final java.lang.String FEATURE_SECURELY_REMOVES_USERS = "android.software.securely_removes_users";
field public static final java.lang.String FEATURE_SENSOR_ACCELEROMETER = "android.hardware.sensor.accelerometer";
field public static final java.lang.String FEATURE_SENSOR_AMBIENT_TEMPERATURE = "android.hardware.sensor.ambient_temperature";
field public static final java.lang.String FEATURE_SENSOR_BAROMETER = "android.hardware.sensor.barometer";
@@ -8941,6 +8938,7 @@
field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH_JAZZHAND = "android.hardware.touchscreen.multitouch.jazzhand";
field public static final java.lang.String FEATURE_USB_ACCESSORY = "android.hardware.usb.accessory";
field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host";
+ field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
@@ -12691,7 +12689,7 @@
method public void onCaptureProgressed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult);
method public void onCaptureSequenceAborted(android.hardware.camera2.CameraCaptureSession, int);
method public void onCaptureSequenceCompleted(android.hardware.camera2.CameraCaptureSession, int, long);
- method public void onCaptureStarted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, long);
+ method public void onCaptureStarted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, long, long);
}
public static abstract class CameraCaptureSession.StateCallback {
@@ -14055,6 +14053,7 @@
field public static final int CONTENT_TYPE_UNKNOWN = 0; // 0x0
field public static final android.os.Parcelable.Creator 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 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
@@ -14082,29 +14081,6 @@
method public android.media.AudioAttributes.Builder setUsage(int);
}
- public class AudioDevice {
- field public static final int DEVICE_TYPE_AUX_LINE = 19; // 0x13
- field public static final int DEVICE_TYPE_BLUETOOTH_A2DP = 8; // 0x8
- field public static final int DEVICE_TYPE_BLUETOOTH_SCO = 7; // 0x7
- field public static final int DEVICE_TYPE_BUILTIN_EARPIECE = 1; // 0x1
- field public static final int DEVICE_TYPE_BUILTIN_MIC = 15; // 0xf
- field public static final int DEVICE_TYPE_BUILTIN_SPEAKER = 2; // 0x2
- field public static final int DEVICE_TYPE_DOCK = 13; // 0xd
- field public static final int DEVICE_TYPE_FM = 14; // 0xe
- field public static final int DEVICE_TYPE_FM_TUNER = 16; // 0x10
- field public static final int DEVICE_TYPE_HDMI = 9; // 0x9
- field public static final int DEVICE_TYPE_HDMI_ARC = 10; // 0xa
- field public static final int DEVICE_TYPE_LINE_ANALOG = 5; // 0x5
- field public static final int DEVICE_TYPE_LINE_DIGITAL = 6; // 0x6
- field public static final int DEVICE_TYPE_TELEPHONY = 18; // 0x12
- field public static final int DEVICE_TYPE_TV_TUNER = 17; // 0x11
- field public static final int DEVICE_TYPE_UNKNOWN = 0; // 0x0
- field public static final int DEVICE_TYPE_USB_ACCESSORY = 12; // 0xc
- field public static final int DEVICE_TYPE_USB_DEVICE = 11; // 0xb
- field public static final int DEVICE_TYPE_WIRED_HEADPHONES = 4; // 0x4
- field public static final int DEVICE_TYPE_WIRED_HEADSET = 3; // 0x3
- }
-
public class AudioFormat {
method public int getChannelMask();
method public int getEncoding();
@@ -14428,6 +14404,7 @@
field public static final int QUALITY_CIF = 3; // 0x3
field public static final int QUALITY_HIGH = 1; // 0x1
field public static final int QUALITY_HIGH_SPEED_1080P = 2004; // 0x7d4
+ field public static final int QUALITY_HIGH_SPEED_2160P = 2005; // 0x7d5
field public static final int QUALITY_HIGH_SPEED_480P = 2002; // 0x7d2
field public static final int QUALITY_HIGH_SPEED_720P = 2003; // 0x7d3
field public static final int QUALITY_HIGH_SPEED_HIGH = 2001; // 0x7d1
@@ -14672,7 +14649,7 @@
}
public static final class MediaCodec.CodecException extends java.lang.IllegalStateException {
- method public int getErrorCode();
+ method public java.lang.String getDiagnosticInfo();
method public boolean isRecoverable();
method public boolean isTransient();
}
@@ -14680,6 +14657,7 @@
public static final class MediaCodec.CryptoException extends java.lang.RuntimeException {
ctor public MediaCodec.CryptoException(int, java.lang.String);
method public int getErrorCode();
+ field public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4; // 0x4
field public static final int ERROR_KEY_EXPIRED = 2; // 0x2
field public static final int ERROR_NO_KEY = 1; // 0x1
field public static final int ERROR_RESOURCE_BUSY = 3; // 0x3
@@ -15009,7 +14987,7 @@
public static final class MediaDrm.MediaDrmStateException extends java.lang.IllegalStateException {
ctor public MediaDrm.MediaDrmStateException(int, java.lang.String);
- method public int getErrorCode();
+ method public java.lang.String getDiagnosticInfo();
}
public static abstract interface MediaDrm.OnEventListener {
@@ -16195,12 +16173,16 @@
method public short getRoundedStrength() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
method public boolean getSpeakerAngles(int, int, int[]) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
method public boolean getStrengthSupported();
- method public int getVirtualizationMode() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+ method public int getVirtualizationMode() throws java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
method public void setParameterListener(android.media.audiofx.Virtualizer.OnParameterChangeListener);
method public void setProperties(android.media.audiofx.Virtualizer.Settings) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
method public void setStrength(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
field public static final int PARAM_STRENGTH = 1; // 0x1
field public static final int PARAM_STRENGTH_SUPPORTED = 0; // 0x0
+ field public static final int VIRTUALIZATION_MODE_AUTO = 1; // 0x1
+ field public static final int VIRTUALIZATION_MODE_BINAURAL = 2; // 0x2
+ field public static final int VIRTUALIZATION_MODE_OFF = 0; // 0x0
+ field public static final int VIRTUALIZATION_MODE_TRANSAURAL = 3; // 0x3
}
public static abstract interface Virtualizer.OnParameterChangeListener {
@@ -16363,10 +16345,10 @@
package android.media.projection {
public final class MediaProjection {
- method public void addCallback(android.media.projection.MediaProjection.Callback, android.os.Handler);
method public android.hardware.display.VirtualDisplay createVirtualDisplay(java.lang.String, int, int, int, int, android.view.Surface, android.hardware.display.VirtualDisplay.Callback, android.os.Handler);
- method public void removeCallback(android.media.projection.MediaProjection.Callback);
+ method public void registerCallback(android.media.projection.MediaProjection.Callback, android.os.Handler);
method public void stop();
+ method public void unregisterCallback(android.media.projection.MediaProjection.Callback);
}
public static abstract class MediaProjection.Callback {
@@ -16375,8 +16357,8 @@
}
public final class MediaProjectionManager {
+ method public android.content.Intent createScreenCaptureIntent();
method public android.media.projection.MediaProjection getMediaProjection(int, android.content.Intent);
- method public android.content.Intent getScreenCaptureIntent();
}
}
@@ -17555,14 +17537,12 @@
public class VpnService extends android.app.Service {
ctor public VpnService();
- method public boolean addAddress(java.net.InetAddress, int);
method public android.os.IBinder onBind(android.content.Intent);
method public void onRevoke();
method public static android.content.Intent prepare(android.content.Context);
method public boolean protect(int);
method public boolean protect(java.net.Socket);
method public boolean protect(java.net.DatagramSocket);
- method public boolean removeAddress(java.net.InetAddress, int);
field public static final java.lang.String SERVICE_INTERFACE = "android.net.VpnService";
}
@@ -22508,6 +22488,7 @@
field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
field public static final java.lang.String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
+ field public static final java.lang.String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
field public static final java.lang.String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
@@ -23704,7 +23685,6 @@
field public static final java.lang.String DURATION = "duration";
field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER";
field public static final java.lang.String FEATURES = "features";
- field public static final int FEATURES_NONE = 0; // 0x0
field public static final int FEATURES_VIDEO = 1; // 0x1
field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location";
field public static final int INCOMING_TYPE = 1; // 0x1
@@ -27275,6 +27255,7 @@
method public android.view.SurfaceHolder getSurfaceHolder();
method public boolean isPreview();
method public boolean isVisible();
+ method public void onApplyWindowInsets(android.view.WindowInsets);
method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
method public void onCreate(android.view.SurfaceHolder);
method public void onDesiredSizeChanged(int, int);
@@ -27428,11 +27409,12 @@
ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener);
ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener, java.lang.String);
method public int addEarcon(java.lang.String, java.lang.String, int);
- method public int addEarcon(java.lang.String, java.lang.String);
+ method public deprecated int addEarcon(java.lang.String, java.lang.String);
+ method public int addEarcon(java.lang.String, java.io.File);
method public int addSpeech(java.lang.String, java.lang.String, int);
method public int addSpeech(java.lang.CharSequence, java.lang.String, int);
method public int addSpeech(java.lang.String, java.lang.String);
- method public int addSpeech(java.lang.CharSequence, java.lang.String);
+ method public int addSpeech(java.lang.CharSequence, java.io.File);
method public deprecated boolean areDefaultsEnforced();
method public java.util.Set<java.util.Locale> getAvailableLanguages();
method public java.lang.String getDefaultEngine();
@@ -27446,7 +27428,7 @@
method public java.util.Set<android.speech.tts.Voice> getVoices();
method public int isLanguageAvailable(java.util.Locale);
method public boolean isSpeaking();
- method public int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String);
+ method public int playEarcon(java.lang.String, int, android.os.Bundle, java.lang.String);
method public deprecated int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>);
method public int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String);
method public deprecated int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>);
@@ -27459,10 +27441,10 @@
method public int setSpeechRate(float);
method public int setVoice(android.speech.tts.Voice);
method public void shutdown();
- method public int speak(java.lang.CharSequence, int, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String);
+ method public int speak(java.lang.CharSequence, int, android.os.Bundle, java.lang.String);
method public deprecated int speak(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>);
method public int stop();
- method public int synthesizeToFile(java.lang.CharSequence, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String, java.lang.String);
+ method public int synthesizeToFile(java.lang.CharSequence, android.os.Bundle, java.io.File, java.lang.String);
method public deprecated int synthesizeToFile(java.lang.String, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String);
field public static final java.lang.String ACTION_TTS_QUEUE_PROCESSING_COMPLETED = "android.speech.tts.TTS_QUEUE_PROCESSING_COMPLETED";
field public static final int ERROR = -1; // 0xffffffff
@@ -27535,15 +27517,15 @@
public abstract class TextToSpeechService extends android.app.Service {
ctor public TextToSpeechService();
- method protected int isValidVoiceName(java.lang.String);
method public android.os.IBinder onBind(android.content.Intent);
method protected java.lang.String onGetDefaultVoiceNameFor(java.lang.String, java.lang.String, java.lang.String);
method protected java.util.Set<java.lang.String> onGetFeaturesForLanguage(java.lang.String, java.lang.String, java.lang.String);
method protected abstract java.lang.String[] onGetLanguage();
- method protected java.util.List<android.speech.tts.Voice> onGetVoices();
+ method public java.util.List<android.speech.tts.Voice> onGetVoices();
method protected abstract int onIsLanguageAvailable(java.lang.String, java.lang.String, java.lang.String);
+ method public int onIsValidVoiceName(java.lang.String);
method protected abstract int onLoadLanguage(java.lang.String, java.lang.String, java.lang.String);
- method protected int onLoadVoice(java.lang.String);
+ method public int onLoadVoice(java.lang.String);
method protected abstract void onStop();
method protected abstract void onSynthesizeText(android.speech.tts.SynthesisRequest, android.speech.tts.SynthesisCallback);
}
@@ -27564,7 +27546,7 @@
method public java.util.Locale getLocale();
method public java.lang.String getName();
method public int getQuality();
- method public boolean getRequiresNetworkConnection();
+ method public boolean isNetworkConnectionRequired();
method public void writeToParcel(android.os.Parcel, int);
field public static final int LATENCY_HIGH = 400; // 0x190
field public static final int LATENCY_LOW = 200; // 0xc8
@@ -28221,7 +28203,6 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
- field public static final int ROUTE_ALL = 15; // 0xf
field public static final int ROUTE_BLUETOOTH = 2; // 0x2
field public static final int ROUTE_EARPIECE = 1; // 0x1
field public static final int ROUTE_SPEAKER = 8; // 0x8
@@ -28238,7 +28219,7 @@
method public final void destroy();
method public final int getCapabilities();
method public final java.util.List<android.telecomm.Connection> getConnections();
- method public final android.telecomm.PhoneAccountHandle getPhoneAccount();
+ method public final android.telecomm.PhoneAccountHandle getPhoneAccountHandle();
method public final int getState();
method public void onDisconnect();
method public void onHold();
@@ -28258,6 +28239,8 @@
method public static android.telecomm.Connection createCanceledConnection();
method public static android.telecomm.Connection createFailedConnection(int, java.lang.String);
method public final void destroy();
+ method public final android.net.Uri getAddress();
+ method public final int getAddressPresentation();
method public final boolean getAudioModeIsVoip();
method public final android.telecomm.AudioState getAudioState();
method public final int getCallCapabilities();
@@ -28267,26 +28250,24 @@
method public final java.util.List<android.telecomm.Connection> getConferenceableConnections();
method public final int getDisconnectCause();
method public final java.lang.String getDisconnectMessage();
- method public final android.net.Uri getHandle();
- method public final int getHandlePresentation();
method public final int getState();
method public final android.telecomm.StatusHints getStatusHints();
- method public final boolean isRequestingRingback();
+ method public final boolean isRingbackRequested();
method public void onAbort();
method public void onAnswer();
+ method public void onAudioStateChanged(android.telecomm.AudioState);
method public void onConferenceWith(android.telecomm.Connection);
method public void onDisconnect();
method public void onHold();
- method public void onPhoneAccountClicked();
method public void onPlayDtmfTone(char);
method public void onPostDialContinue(boolean);
method public void onReject();
method public void onSeparate();
- method public void onSetAudioState(android.telecomm.AudioState);
- method public void onSetState(int);
+ method public void onStateChanged(int);
method public void onStopDtmfTone();
method public void onUnhold();
method public final void setActive();
+ method public final void setAddress(android.net.Uri, int);
method public final void setAudioModeIsVoip(boolean);
method public final void setCallCapabilities(int);
method public final void setCallerDisplayName(java.lang.String, int);
@@ -28294,12 +28275,11 @@
method public final void setConnectionService(android.telecomm.ConnectionService);
method public final void setDialing();
method public final void setDisconnected(int, java.lang.String);
- method public final void setHandle(android.net.Uri, int);
method public final void setInitialized();
method public final void setInitializing();
method public final void setOnHold();
method public final void setPostDialWait(java.lang.String);
- method public final void setRequestingRingback(boolean);
+ method public final void setRingbackRequested(boolean);
method public final void setRinging();
method public final void setStatusHints(android.telecomm.StatusHints);
method public static java.lang.String stateToString(int);
@@ -28313,12 +28293,11 @@
}
public final class ConnectionRequest implements android.os.Parcelable {
- ctor public ConnectionRequest(android.telecomm.PhoneAccountHandle, android.net.Uri, int, android.os.Bundle);
+ ctor public ConnectionRequest(android.telecomm.PhoneAccountHandle, android.net.Uri, android.os.Bundle);
method public int describeContents();
method public android.telecomm.PhoneAccountHandle getAccountHandle();
+ method public android.net.Uri getAddress();
method public android.os.Bundle getExtras();
- method public android.net.Uri getHandle();
- method public int getHandlePresentation();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
@@ -28340,29 +28319,32 @@
public class GatewayInfo implements android.os.Parcelable {
method public int describeContents();
- method public android.net.Uri getGatewayHandle();
+ method public android.net.Uri getGatewayAddress();
method public java.lang.String getGatewayProviderPackageName();
- method public android.net.Uri getOriginalHandle();
+ method public android.net.Uri getOriginalAddress();
method public boolean isEmpty();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
public class PhoneAccount implements android.os.Parcelable {
- method public static android.telecomm.PhoneAccount.Builder builder();
+ method public static android.telecomm.PhoneAccount.Builder builder(android.telecomm.PhoneAccountHandle, java.lang.CharSequence);
method public int describeContents();
method public android.telecomm.PhoneAccountHandle getAccountHandle();
+ method public android.net.Uri getAddress();
method public int getCapabilities();
- method public android.net.Uri getHandle();
method public android.graphics.drawable.Drawable getIcon(android.content.Context);
method public int getIconResId();
method public java.lang.CharSequence getLabel();
method public java.lang.CharSequence getShortDescription();
- method public java.lang.String getSubscriptionNumber();
+ method public android.net.Uri getSubscriptionAddress();
method public java.util.List<java.lang.String> getSupportedUriSchemes();
+ method public boolean hasCapabilities(int);
+ method public boolean isEnabled();
method public boolean supportsUriScheme(java.lang.String);
method public void writeToParcel(android.os.Parcel, int);
field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
+ field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
field public static final android.os.Parcelable.Creator CREATOR;
field public static final java.lang.String SCHEME_SIP = "sip";
@@ -28371,17 +28353,15 @@
}
public static class PhoneAccount.Builder {
- ctor public PhoneAccount.Builder();
+ ctor public PhoneAccount.Builder(android.telecomm.PhoneAccountHandle, java.lang.CharSequence);
+ ctor public PhoneAccount.Builder(android.telecomm.PhoneAccount);
method public android.telecomm.PhoneAccount build();
- method public android.telecomm.PhoneAccount.Builder withAccountHandle(android.telecomm.PhoneAccountHandle);
- method public android.telecomm.PhoneAccount.Builder withCapabilities(int);
- method public android.telecomm.PhoneAccount.Builder withHandle(android.net.Uri);
- method public android.telecomm.PhoneAccount.Builder withIconResId(int);
- method public android.telecomm.PhoneAccount.Builder withLabel(java.lang.CharSequence);
- method public android.telecomm.PhoneAccount.Builder withShortDescription(java.lang.CharSequence);
- method public android.telecomm.PhoneAccount.Builder withSubscriptionNumber(java.lang.String);
- method public android.telecomm.PhoneAccount.Builder withSupportedUriScheme(java.lang.String);
- method public android.telecomm.PhoneAccount.Builder withSupportedUriSchemes(java.util.List<java.lang.String>);
+ method public android.telecomm.PhoneAccount.Builder setAddress(android.net.Uri);
+ method public android.telecomm.PhoneAccount.Builder setCapabilities(int);
+ method public android.telecomm.PhoneAccount.Builder setIconResId(int);
+ method public android.telecomm.PhoneAccount.Builder setShortDescription(java.lang.CharSequence);
+ method public android.telecomm.PhoneAccount.Builder setSubscriptionAddress(android.net.Uri);
+ method public android.telecomm.PhoneAccount.Builder setSupportedUriSchemes(java.util.List<java.lang.String>);
}
public class PhoneAccountHandle implements android.os.Parcelable {
@@ -28406,16 +28386,7 @@
field public static final int SWAP_CONFERENCE = 8; // 0x8
}
- public class PropertyPresentation {
- ctor public PropertyPresentation();
- field public static final int ALLOWED = 1; // 0x1
- field public static final int PAYPHONE = 4; // 0x4
- field public static final int RESTRICTED = 2; // 0x2
- field public static final int UNKNOWN = 3; // 0x3
- }
-
public final class RemoteConference {
- method public final void addCallback(android.telecomm.RemoteConference.Callback);
method public void disconnect();
method public final int getCallCapabilities();
method public final java.util.List<android.telecomm.RemoteConnection> getConnections();
@@ -28423,9 +28394,10 @@
method public java.lang.String getDisconnectMessage();
method public final int getState();
method public void hold();
- method public final void removeCallback(android.telecomm.RemoteConference.Callback);
+ method public final void registerCallback(android.telecomm.RemoteConference.Callback);
method public void separate(android.telecomm.RemoteConnection);
method public void unhold();
+ method public final void unregisterCallback(android.telecomm.RemoteConference.Callback);
}
public static abstract class RemoteConference.Callback {
@@ -28440,67 +28412,58 @@
public final class RemoteConnection {
method public void abort();
- method public void addListener(android.telecomm.RemoteConnection.Listener);
method public void answer();
method public void disconnect();
- method public boolean getAudioModeIsVoip();
+ method public android.net.Uri getAddress();
+ method public int getAddressPresentation();
method public int getCallCapabilities();
- method public java.lang.String getCallerDisplayName();
+ method public java.lang.CharSequence getCallerDisplayName();
method public int getCallerDisplayNamePresentation();
- method public java.util.List<android.telecomm.RemoteConnection> getChildren();
method public android.telecomm.RemoteConference getConference();
method public java.util.List<android.telecomm.RemoteConnection> getConferenceableConnections();
method public int getDisconnectCauseCode();
method public java.lang.String getDisconnectCauseMessage();
method public int getFailureCode();
method public java.lang.String getFailureMessage();
- method public android.net.Uri getHandle();
- method public int getHandlePresentation();
- method public android.telecomm.RemoteConnection getParent();
method public int getState();
method public android.telecomm.StatusHints getStatusHints();
method public void hold();
- method public boolean isRequestingRingback();
+ method public boolean isRingbackRequested();
+ method public boolean isVoipAudioMode();
method public void playDtmfTone(char);
method public void postDialContinue(boolean);
+ method public void registerCallback(android.telecomm.RemoteConnection.Callback);
method public void reject();
- method public void removeListener(android.telecomm.RemoteConnection.Listener);
method public void setAudioState(android.telecomm.AudioState);
method public void stopDtmfTone();
method public void unhold();
+ method public void unregisterCallback(android.telecomm.RemoteConnection.Callback);
}
- public static abstract class RemoteConnection.Listener {
- ctor public RemoteConnection.Listener();
- method public void onAudioModeIsVoipChanged(android.telecomm.RemoteConnection, boolean);
+ public static abstract class RemoteConnection.Callback {
+ ctor public RemoteConnection.Callback();
+ method public void onAddressChanged(android.telecomm.RemoteConnection, android.net.Uri, int);
method public void onCallCapabilitiesChanged(android.telecomm.RemoteConnection, int);
method public void onCallerDisplayNameChanged(android.telecomm.RemoteConnection, java.lang.String, int);
- method public void onChildrenChanged(android.telecomm.RemoteConnection, java.util.List<android.telecomm.RemoteConnection>);
method public void onConferenceChanged(android.telecomm.RemoteConnection, android.telecomm.RemoteConference);
method public void onConferenceableConnectionsChanged(android.telecomm.RemoteConnection, java.util.List<android.telecomm.RemoteConnection>);
method public void onDestroyed(android.telecomm.RemoteConnection);
method public void onDisconnected(android.telecomm.RemoteConnection, int, java.lang.String);
- method public void onHandleChanged(android.telecomm.RemoteConnection, android.net.Uri, int);
- method public void onParentChanged(android.telecomm.RemoteConnection, android.telecomm.RemoteConnection);
method public void onPostDialWait(android.telecomm.RemoteConnection, java.lang.String);
- method public void onRequestingRingback(android.telecomm.RemoteConnection, boolean);
+ method public void onRingbackRequested(android.telecomm.RemoteConnection, boolean);
method public void onStateChanged(android.telecomm.RemoteConnection, int);
method public void onStatusHintsChanged(android.telecomm.RemoteConnection, android.telecomm.StatusHints);
- }
-
- public abstract interface Response {
- method public abstract void onError(IN, int, java.lang.String);
- method public abstract void onResult(IN, OUT...);
+ method public void onVoipAudioChanged(android.telecomm.RemoteConnection, boolean);
}
public final class StatusHints implements android.os.Parcelable {
ctor public StatusHints(android.content.ComponentName, java.lang.CharSequence, int, android.os.Bundle);
method public int describeContents();
- method public android.content.ComponentName getComponentName();
method public android.os.Bundle getExtras();
method public android.graphics.drawable.Drawable getIcon(android.content.Context);
method public int getIconResId();
method public java.lang.CharSequence getLabel();
+ method public android.content.ComponentName getPackageName();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
@@ -28508,7 +28471,7 @@
public class TelecommManager {
method public void addNewIncomingCall(android.telecomm.PhoneAccountHandle, android.os.Bundle);
method public void cancelMissedCallsNotification();
- method public void clearAccounts(java.lang.String);
+ method public void clearAccounts();
method public android.telecomm.PhoneAccountHandle getConnectionManager();
method public android.telecomm.PhoneAccountHandle getDefaultOutgoingPhoneAccount(java.lang.String);
method public java.util.List<android.telecomm.PhoneAccountHandle> getEnabledPhoneAccounts();
@@ -28531,6 +28494,12 @@
field public static final java.lang.String EXTRA_CONNECTION_SERVICE = "android.telecomm.extra.CONNECTION_SERVICE";
field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecomm.extra.PHONE_ACCOUNT_HANDLE";
field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecomm.extra.START_CALL_WITH_SPEAKERPHONE";
+ field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecomm.extra.GATEWAY_ORIGINAL_ADDRESS";
+ field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecomm.extra.GATEWAY_PROVIDER_PACKAGE";
+ field public static final int PRESENTATION_ALLOWED = 1; // 0x1
+ field public static final int PRESENTATION_PAYPHONE = 4; // 0x4
+ field public static final int PRESENTATION_RESTRICTED = 2; // 0x2
+ field public static final int PRESENTATION_UNKNOWN = 3; // 0x3
}
}
@@ -28894,8 +28863,6 @@
method public void downloadMultimediaMessage(java.lang.String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
method public android.os.Bundle getCarrierConfigValues();
method public static android.telephony.SmsManager getDefault();
- method public static android.telephony.SmsManager getSmsManagerUsingSubId(long);
- method public long getSubId();
method public void injectSmsPdu(byte[], java.lang.String, android.app.PendingIntent);
method public void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
method public void sendMultimediaMessage(android.net.Uri, java.lang.String, android.os.Bundle, android.app.PendingIntent);
@@ -29047,7 +29014,6 @@
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
method public boolean setGlobalPreferredNetworkType();
method public void setLine1NumberForDisplay(java.lang.String, java.lang.String);
- method public void setLine1NumberForDisplay(long, java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
@@ -32160,6 +32126,7 @@
ctor public SizeF(float, float);
method public float getHeight();
method public float getWidth();
+ method public static android.util.SizeF parseSizeF(java.lang.String) throws java.lang.NumberFormatException;
}
public class SparseArray implements java.lang.Cloneable {
@@ -34989,12 +34956,18 @@
public final class WindowInsets {
ctor public WindowInsets(android.view.WindowInsets);
+ method public android.view.WindowInsets consumeStableInsets();
method public android.view.WindowInsets consumeSystemWindowInsets();
+ method public int getStableInsetBottom();
+ method public int getStableInsetLeft();
+ method public int getStableInsetRight();
+ method public int getStableInsetTop();
method public int getSystemWindowInsetBottom();
method public int getSystemWindowInsetLeft();
method public int getSystemWindowInsetRight();
method public int getSystemWindowInsetTop();
method public boolean hasInsets();
+ method public boolean hasStableInsets();
method public boolean hasSystemWindowInsets();
method public boolean isConsumed();
method public boolean isRound();
@@ -35899,8 +35872,8 @@
public final class CursorAnchorInfo implements android.os.Parcelable {
ctor public CursorAnchorInfo(android.os.Parcel);
method public int describeContents();
- method public android.graphics.RectF getCharacterRect(int);
- method public int getCharacterRectFlags(int);
+ method public android.graphics.RectF getCharacterBounds(int);
+ method public int getCharacterBoundsFlags(int);
method public java.lang.CharSequence getComposingText();
method public int getComposingTextStart();
method public float getInsertionMarkerBaseline();
@@ -35915,11 +35888,12 @@
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int FLAG_HAS_INVISIBLE_REGION = 2; // 0x2
field public static final int FLAG_HAS_VISIBLE_REGION = 1; // 0x1
+ field public static final int FLAG_IS_RTL = 4; // 0x4
}
public static final class CursorAnchorInfo.Builder {
ctor public CursorAnchorInfo.Builder();
- method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterRect(int, float, float, float, float, int);
+ method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterBounds(int, float, float, float, float, int);
method public android.view.inputmethod.CursorAnchorInfo build();
method public void reset();
method public android.view.inputmethod.CursorAnchorInfo.Builder setComposingText(int, java.lang.CharSequence);
@@ -36505,23 +36479,18 @@
public static abstract class WebChromeClient.FileChooserParams {
ctor public WebChromeClient.FileChooserParams();
+ method public abstract android.content.Intent createIntent();
method public abstract java.lang.String[] getAcceptTypes();
method public abstract java.lang.String getFilenameHint();
method public abstract int getMode();
method public abstract java.lang.CharSequence getTitle();
- method public abstract android.webkit.WebChromeClient.UploadHelper getUploadHelper();
method public abstract boolean isCaptureEnabled();
+ method public static android.net.Uri[] parseResult(int, android.content.Intent);
field public static final int MODE_OPEN = 0; // 0x0
field public static final int MODE_OPEN_MULTIPLE = 1; // 0x1
field public static final int MODE_SAVE = 3; // 0x3
}
- public static abstract class WebChromeClient.UploadHelper {
- ctor public WebChromeClient.UploadHelper();
- method public abstract android.content.Intent buildIntent();
- method public abstract android.net.Uri[] parseResult(int, android.content.Intent);
- }
-
public class WebHistoryItem implements java.lang.Cloneable {
method public android.graphics.Bitmap getFavicon();
method public java.lang.String getOriginalUrl();
@@ -37562,6 +37531,7 @@
method public android.widget.CalendarView getCalendarView();
method public boolean getCalendarViewShown();
method public int getDayOfMonth();
+ method public int getFirstDayOfWeek();
method public long getMaxDate();
method public long getMinDate();
method public int getMonth();
@@ -37569,6 +37539,7 @@
method public int getYear();
method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener);
method public void setCalendarViewShown(boolean);
+ method public void setFirstDayOfWeek(int);
method public void setMaxDate(long);
method public void setMinDate(long);
method public void setSpinnersShown(boolean);
diff --git a/api/removed.txt b/api/removed.txt
index 7f5f46c..c8a3b4b 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -22,14 +22,6 @@
}
-package android.service.notification {
-
- public static class NotificationListenerService.Ranking {
- method public boolean meetsInterruptionFilter();
- }
-
-}
-
package android.view {
public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
@@ -45,6 +37,8 @@
}
public final class CursorAnchorInfo implements android.os.Parcelable {
+ method public android.graphics.RectF getCharacterRect(int);
+ method public int getCharacterRectFlags(int);
method public boolean isInsertionMarkerClipped();
field public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1; // 0x1
field public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3; // 0x3
@@ -55,6 +49,7 @@
}
public static final class CursorAnchorInfo.Builder {
+ method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterRect(int, float, float, float, float, int);
method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float, boolean);
}
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index c06ef0d..57c1505 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -28,10 +28,15 @@
import android.app.Instrumentation;
import android.app.ProfilerInfo;
import android.app.UiAutomationConnection;
+import android.app.usage.ConfigurationStats;
+import android.app.usage.IUsageStatsManager;
+import android.app.usage.UsageStatsManager;
import android.content.ComponentName;
+import android.content.Context;
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.pm.IPackageManager;
+import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -47,6 +52,7 @@
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.AndroidException;
+import android.util.ArrayMap;
import android.view.IWindowManager;
import android.view.View;
@@ -61,6 +67,9 @@
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
@@ -846,7 +855,7 @@
}
private void sendBroadcast() throws Exception {
- Intent intent = makeIntent(UserHandle.USER_ALL);
+ Intent intent = makeIntent(UserHandle.USER_CURRENT);
IntentReceiver receiver = new IntentReceiver();
System.out.println("Broadcasting: " + intent);
mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, mReceiverPermission,
@@ -1722,7 +1731,64 @@
}
}
+ private List<Configuration> getRecentConfigurations(int days) {
+ IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
+ Context.USAGE_STATS_SERVICE));
+ final long now = System.currentTimeMillis();
+ final long nDaysAgo = now - (days * 24 * 60 * 60 * 1000);
+ try {
+ @SuppressWarnings("unchecked")
+ ParceledListSlice<ConfigurationStats> configStatsSlice = usm.queryConfigurationStats(
+ UsageStatsManager.INTERVAL_BEST, nDaysAgo, now, "com.android.shell");
+ if (configStatsSlice == null) {
+ return Collections.emptyList();
+ }
+
+ final ArrayMap<Configuration, Integer> recentConfigs = new ArrayMap<>();
+ final List<ConfigurationStats> configStatsList = configStatsSlice.getList();
+ final int configStatsListSize = configStatsList.size();
+ for (int i = 0; i < configStatsListSize; i++) {
+ final ConfigurationStats stats = configStatsList.get(i);
+ final int indexOfKey = recentConfigs.indexOfKey(stats.getConfiguration());
+ if (indexOfKey < 0) {
+ recentConfigs.put(stats.getConfiguration(), stats.getActivationCount());
+ } else {
+ recentConfigs.setValueAt(indexOfKey,
+ recentConfigs.valueAt(indexOfKey) + stats.getActivationCount());
+ }
+ }
+
+ final Comparator<Configuration> comparator = new Comparator<Configuration>() {
+ @Override
+ public int compare(Configuration a, Configuration b) {
+ return recentConfigs.get(b).compareTo(recentConfigs.get(a));
+ }
+ };
+
+ ArrayList<Configuration> configs = new ArrayList<>(recentConfigs.size());
+ configs.addAll(recentConfigs.keySet());
+ Collections.sort(configs, comparator);
+ return configs;
+
+ } catch (RemoteException e) {
+ return Collections.emptyList();
+ }
+ }
+
private void runGetConfig() throws Exception {
+ int days = 14;
+ String option = nextOption();
+ if (option != null) {
+ if (!option.equals("--days")) {
+ throw new IllegalArgumentException("unrecognized option " + option);
+ }
+
+ days = Integer.parseInt(nextArgRequired());
+ if (days <= 0) {
+ throw new IllegalArgumentException("--days must be a positive integer");
+ }
+ }
+
try {
Configuration config = mAm.getConfiguration();
if (config == null) {
@@ -1733,6 +1799,17 @@
System.out.println("config: " + Configuration.resourceQualifierString(config));
System.out.println("abi: " + TextUtils.join(",", Build.SUPPORTED_ABIS));
+ final List<Configuration> recentConfigs = getRecentConfigurations(days);
+ final int recentConfigSize = recentConfigs.size();
+ if (recentConfigSize > 0) {
+ System.out.println("recentConfigs:");
+ }
+
+ for (int i = 0; i < recentConfigSize; i++) {
+ System.out.println(" config: " + Configuration.resourceQualifierString(
+ recentConfigs.get(i)));
+ }
+
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 5f7a17d..27a03b6 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -54,6 +54,10 @@
int action, in Bundle arguments, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long threadId);
+ boolean computeClickPointInScreen(int accessibilityWindowId, long accessibilityNodeId,
+ int interactionId, IAccessibilityInteractionConnectionCallback callback,
+ long threadId);
+
AccessibilityWindowInfo getWindow(int windowId);
List<AccessibilityWindowInfo> getWindows();
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index f4e4671..25417ed 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -92,21 +92,27 @@
*/
public static Animator loadAnimator(Resources resources, Theme theme, int id)
throws NotFoundException {
+ return loadAnimator(resources, theme, id, 1);
+ }
+
+ /** @hide */
+ public static Animator loadAnimator(Resources resources, Theme theme, int id,
+ float pathErrorScale) throws NotFoundException {
XmlResourceParser parser = null;
try {
parser = resources.getAnimation(id);
- return createAnimatorFromXml(resources, theme, parser);
+ return createAnimatorFromXml(resources, theme, parser, pathErrorScale);
} catch (XmlPullParserException ex) {
Resources.NotFoundException rnf =
new Resources.NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
+ Integer.toHexString(id));
rnf.initCause(ex);
throw rnf;
} catch (IOException ex) {
Resources.NotFoundException rnf =
new Resources.NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
+ Integer.toHexString(id));
rnf.initCause(ex);
throw rnf;
} finally {
@@ -177,7 +183,7 @@
}
if (animator == null) {
animator = createAnimatorFromXml(context.getResources(),
- context.getTheme(), parser);
+ context.getTheme(), parser, 1f);
}
if (animator == null) {
@@ -248,9 +254,11 @@
* @param arrayAnimator Incoming typed array for Animator's attributes.
* @param arrayObjectAnimator Incoming typed array for Object Animator's
* attributes.
+ * @param pixelSize The relative pixel size, used to calculate the
+ * maximum error for path animations.
*/
private static void parseAnimatorFromTypeArray(ValueAnimator anim,
- TypedArray arrayAnimator, TypedArray arrayObjectAnimator) {
+ TypedArray arrayAnimator, TypedArray arrayObjectAnimator, float pixelSize) {
long duration = arrayAnimator.getInt(R.styleable.Animator_duration, 300);
long startDelay = arrayAnimator.getInt(R.styleable.Animator_startOffset, 0);
@@ -303,7 +311,7 @@
}
if (arrayObjectAnimator != null) {
- setupObjectAnimator(anim, arrayObjectAnimator, getFloats);
+ setupObjectAnimator(anim, arrayObjectAnimator, getFloats, pixelSize);
}
}
@@ -351,9 +359,11 @@
* @param anim The target Animator which will be updated.
* @param arrayObjectAnimator TypedArray for the ObjectAnimator.
* @param getFloats True if the value type is float.
+ * @param pixelSize The relative pixel size, used to calculate the
+ * maximum error for path animations.
*/
private static void setupObjectAnimator(ValueAnimator anim, TypedArray arrayObjectAnimator,
- boolean getFloats) {
+ boolean getFloats, float pixelSize) {
ObjectAnimator oa = (ObjectAnimator) anim;
String pathData = arrayObjectAnimator.getString(R.styleable.PropertyAnimator_pathData);
@@ -370,7 +380,8 @@
+ " propertyXName or propertyYName is needed for PathData");
} else {
Path path = PathParser.createPathFromPathData(pathData);
- PathKeyframes keyframeSet = KeyframeSet.ofPath(path);
+ float error = 0.5f * pixelSize; // max half a pixel error
+ PathKeyframes keyframeSet = KeyframeSet.ofPath(path, error);
Keyframes xKeyframes;
Keyframes yKeyframes;
if (getFloats) {
@@ -487,13 +498,15 @@
}
}
- private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser)
+ private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser,
+ float pixelSize)
throws XmlPullParserException, IOException {
- return createAnimatorFromXml(res, theme, parser, Xml.asAttributeSet(parser), null, 0);
+ return createAnimatorFromXml(res, theme, parser, Xml.asAttributeSet(parser), null, 0,
+ pixelSize);
}
private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser,
- AttributeSet attrs, AnimatorSet parent, int sequenceOrdering)
+ AttributeSet attrs, AnimatorSet parent, int sequenceOrdering, float pixelSize)
throws XmlPullParserException, IOException {
Animator anim = null;
@@ -513,9 +526,9 @@
String name = parser.getName();
if (name.equals("objectAnimator")) {
- anim = loadObjectAnimator(res, theme, attrs);
+ anim = loadObjectAnimator(res, theme, attrs, pixelSize);
} else if (name.equals("animator")) {
- anim = loadAnimator(res, theme, attrs, null);
+ anim = loadAnimator(res, theme, attrs, null, pixelSize);
} else if (name.equals("set")) {
anim = new AnimatorSet();
TypedArray a;
@@ -526,7 +539,8 @@
}
int ordering = a.getInt(R.styleable.AnimatorSet_ordering,
TOGETHER);
- createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering);
+ createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering,
+ pixelSize);
a.recycle();
} else {
throw new RuntimeException("Unknown animator name: " + parser.getName());
@@ -556,11 +570,11 @@
}
- private static ObjectAnimator loadObjectAnimator(Resources res, Theme theme, AttributeSet attrs)
- throws NotFoundException {
+ private static ObjectAnimator loadObjectAnimator(Resources res, Theme theme, AttributeSet attrs,
+ float pathErrorScale) throws NotFoundException {
ObjectAnimator anim = new ObjectAnimator();
- loadAnimator(res, theme, attrs, anim);
+ loadAnimator(res, theme, attrs, anim, pathErrorScale);
return anim;
}
@@ -575,7 +589,7 @@
* ObjectAnimator
*/
private static ValueAnimator loadAnimator(Resources res, Theme theme,
- AttributeSet attrs, ValueAnimator anim)
+ AttributeSet attrs, ValueAnimator anim, float pathErrorScale)
throws NotFoundException {
TypedArray arrayAnimator = null;
@@ -601,7 +615,7 @@
anim = new ValueAnimator();
}
- parseAnimatorFromTypeArray(anim, arrayAnimator, arrayObjectAnimator);
+ parseAnimatorFromTypeArray(anim, arrayAnimator, arrayObjectAnimator, pathErrorScale);
final int resID =
arrayAnimator.getResourceId(R.styleable.Animator_interpolator, 0);
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 7c13dbe..0aa8fdd 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -636,6 +636,7 @@
anim.mNodes = new ArrayList<Node>();
anim.mSortedNodes = new ArrayList<Node>();
anim.mReversible = mReversible;
+ anim.mSetListener = null;
// Walk through the old nodes list, cloning each node and adding it to the new nodemap.
// One problem is that the old node dependencies point to nodes in the old AnimatorSet.
diff --git a/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java
index fc9bbb1..8d15db2 100644
--- a/core/java/android/animation/KeyframeSet.java
+++ b/core/java/android/animation/KeyframeSet.java
@@ -154,6 +154,10 @@
return new PathKeyframes(path);
}
+ public static PathKeyframes ofPath(Path path, float error) {
+ return new PathKeyframes(path, error);
+ }
+
/**
* Sets the TypeEvaluator to be used when calculating animated values. This object
* is required only for KeyframeSets that are not either IntKeyframeSet or FloatKeyframeSet,
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 394b183..677fcef 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2295,6 +2295,13 @@
reply.writeNoException();
return true;
}
+
+ case BOOT_ANIMATION_COMPLETE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ bootAnimationComplete();
+ reply.writeNoException();
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -5301,5 +5308,16 @@
reply.recycle();
}
+ @Override
+ public void bootAnimationComplete() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(BOOT_ANIMATION_COMPLETE_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 9dd4605..213c7f6 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -84,13 +84,13 @@
* Initial width of the animation.
* @hide
*/
- public static final String KEY_ANIM_START_WIDTH = "android:animStartWidth";
+ public static final String KEY_ANIM_WIDTH = "android:animWidth";
/**
* Initial height of the animation.
* @hide
*/
- public static final String KEY_ANIM_START_HEIGHT = "android:animStartHeight";
+ public static final String KEY_ANIM_HEIGHT = "android:animHeight";
/**
* Callback for when animation is started.
@@ -140,8 +140,8 @@
private Bitmap mThumbnail;
private int mStartX;
private int mStartY;
- private int mStartWidth;
- private int mStartHeight;
+ private int mWidth;
+ private int mHeight;
private IRemoteCallback mAnimationStartedListener;
private ResultReceiver mTransitionReceiver;
private boolean mIsReturning;
@@ -238,13 +238,13 @@
* defines the coordinate space for <var>startX</var> and <var>startY</var>.
* @param startX The x starting location of the new activity, relative to <var>source</var>.
* @param startY The y starting location of the activity, relative to <var>source</var>.
- * @param startWidth The initial width of the new activity.
- * @param startHeight The initial height of the new activity.
+ * @param width The initial width of the new activity.
+ * @param height The initial height of the new activity.
* @return Returns a new ActivityOptions object that you can use to
* supply these options as the options Bundle when starting an activity.
*/
public static ActivityOptions makeScaleUpAnimation(View source,
- int startX, int startY, int startWidth, int startHeight) {
+ int startX, int startY, int width, int height) {
ActivityOptions opts = new ActivityOptions();
opts.mPackageName = source.getContext().getPackageName();
opts.mAnimationType = ANIM_SCALE_UP;
@@ -252,8 +252,8 @@
source.getLocationOnScreen(pts);
opts.mStartX = pts[0] + startX;
opts.mStartY = pts[1] + startY;
- opts.mStartWidth = startWidth;
- opts.mStartHeight = startHeight;
+ opts.mWidth = width;
+ opts.mHeight = height;
return opts;
}
@@ -359,9 +359,10 @@
* @hide
*/
public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source,
- Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
- return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener,
- true);
+ Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
+ OnAnimationStartedListener listener) {
+ return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
+ targetWidth, targetHeight, listener, true);
}
/**
@@ -382,13 +383,15 @@
* @hide
*/
public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source,
- Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
- return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener,
- false);
+ Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
+ OnAnimationStartedListener listener) {
+ return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
+ targetWidth, targetHeight, listener, false);
}
private static ActivityOptions makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail,
- int startX, int startY, OnAnimationStartedListener listener, boolean scaleUp) {
+ int startX, int startY, int targetWidth, int targetHeight,
+ OnAnimationStartedListener listener, boolean scaleUp) {
ActivityOptions opts = new ActivityOptions();
opts.mPackageName = source.getContext().getPackageName();
opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_ASPECT_SCALE_UP :
@@ -398,6 +401,8 @@
source.getLocationOnScreen(pts);
opts.mStartX = pts[0] + startX;
opts.mStartY = pts[1] + startY;
+ opts.mWidth = targetWidth;
+ opts.mHeight = targetHeight;
opts.setOnAnimationStartedListener(source.getHandler(), listener);
return opts;
}
@@ -515,11 +520,6 @@
return opts;
}
- @Deprecated
- public static ActivityOptions makeLaunchTaskBehindAnimation() {
- return makeTaskLaunchBehind();
- }
-
/** @hide */
public boolean getLaunchTaskBehind() {
return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
@@ -543,8 +543,8 @@
case ANIM_SCALE_UP:
mStartX = opts.getInt(KEY_ANIM_START_X, 0);
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
- mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0);
- mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0);
+ mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
+ mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
break;
case ANIM_THUMBNAIL_SCALE_UP:
@@ -554,6 +554,8 @@
mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL);
mStartX = opts.getInt(KEY_ANIM_START_X, 0);
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
+ mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
+ mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
opts.getBinder(KEY_ANIM_START_LISTENER));
break;
@@ -605,13 +607,13 @@
}
/** @hide */
- public int getStartWidth() {
- return mStartWidth;
+ public int getWidth() {
+ return mWidth;
}
/** @hide */
- public int getStartHeight() {
- return mStartHeight;
+ public int getHeight() {
+ return mHeight;
}
/** @hide */
@@ -690,8 +692,8 @@
case ANIM_SCALE_UP:
mStartX = otherOptions.mStartX;
mStartY = otherOptions.mStartY;
- mStartWidth = otherOptions.mStartWidth;
- mStartHeight = otherOptions.mStartHeight;
+ mWidth = otherOptions.mWidth;
+ mHeight = otherOptions.mHeight;
if (mAnimationStartedListener != null) {
try {
mAnimationStartedListener.sendResult(null);
@@ -707,6 +709,8 @@
mThumbnail = otherOptions.mThumbnail;
mStartX = otherOptions.mStartX;
mStartY = otherOptions.mStartY;
+ mWidth = otherOptions.mWidth;
+ mHeight = otherOptions.mHeight;
if (mAnimationStartedListener != null) {
try {
mAnimationStartedListener.sendResult(null);
@@ -755,8 +759,8 @@
case ANIM_SCALE_UP:
b.putInt(KEY_ANIM_START_X, mStartX);
b.putInt(KEY_ANIM_START_Y, mStartY);
- b.putInt(KEY_ANIM_START_WIDTH, mStartWidth);
- b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight);
+ b.putInt(KEY_ANIM_WIDTH, mWidth);
+ b.putInt(KEY_ANIM_HEIGHT, mHeight);
break;
case ANIM_THUMBNAIL_SCALE_UP:
case ANIM_THUMBNAIL_SCALE_DOWN:
@@ -765,6 +769,8 @@
b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
b.putInt(KEY_ANIM_START_X, mStartX);
b.putInt(KEY_ANIM_START_Y, mStartY);
+ b.putInt(KEY_ANIM_WIDTH, mWidth);
+ b.putInt(KEY_ANIM_HEIGHT, mHeight);
b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
!= null ? mAnimationStartedListener.asBinder() : null);
break;
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 9e80a4b..43fa3f0 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -205,6 +205,7 @@
private boolean mIsStartingTransition;
private ArrayList<GhostViewListeners> mGhostViewListeners =
new ArrayList<GhostViewListeners>();
+ private ArrayMap<View, Float> mOriginalAlphas = new ArrayMap<View, Float>();
public ActivityTransitionCoordinator(Window window,
ArrayList<String> allSharedElementNames,
@@ -580,6 +581,7 @@
mWindow = null;
mSharedElements.clear();
mTransitioningViews.clear();
+ mOriginalAlphas.clear();
mResultReceiver = null;
mPendingTransition = null;
mListener = null;
@@ -589,10 +591,28 @@
return getWindow().getTransitionBackgroundFadeDuration();
}
- protected static void setTransitionAlpha(ArrayList<View> views, float alpha) {
+ protected void hideViews(ArrayList<View> views) {
int count = views.size();
for (int i = 0; i < count; i++) {
- views.get(i).setTransitionAlpha(alpha);
+ View view = views.get(i);
+ if (!mOriginalAlphas.containsKey(view)) {
+ mOriginalAlphas.put(view, view.getAlpha());
+ }
+ view.setAlpha(0f);
+ }
+ }
+
+ protected void showViews(ArrayList<View> views, boolean setTransitionAlpha) {
+ int count = views.size();
+ for (int i = 0; i < count; i++) {
+ View view = views.get(i);
+ Float alpha = mOriginalAlphas.remove(view);
+ if (alpha != null) {
+ view.setAlpha(alpha);
+ }
+ if (setTransitionAlpha) {
+ view.setTransitionAlpha(1f);
+ }
}
}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 9cd6d49..d746745 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1645,30 +1645,6 @@
/**
* @hide
*/
- public void addCrossProfileIntentsForPackage(String packageName,
- int sourceUserId, int targetUserId) {
- try {
- mPM.addCrossProfileIntentsForPackage(packageName, sourceUserId, targetUserId);
- } catch (RemoteException e) {
- // Should never happen!
- }
- }
-
- /**
- * @hide
- */
- public void removeCrossProfileIntentsForPackage(String packageName,
- int sourceUserId, int targetUserId) {
- try {
- mPM.removeCrossProfileIntentsForPackage(packageName, sourceUserId, targetUserId);
- } catch (RemoteException e) {
- // Should never happen!
- }
- }
-
- /**
- * @hide
- */
@Override
public void clearCrossProfileIntentFilters(int sourceUserId) {
try {
@@ -1693,7 +1669,7 @@
if (dr == null) {
dr = itemInfo.loadDefaultIcon(this);
}
- return getUserBadgedDrawableForDensity(dr, new UserHandle(mContext.getUserId()), null, 0);
+ return getUserBadgedIcon(dr, new UserHandle(mContext.getUserId()));
}
private Drawable getBadgedDrawable(Drawable drawable, Drawable badgeDrawable,
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 8227915..b09f169 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -38,7 +38,6 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Collection;
final class BackStackState implements Parcelable {
final int[] mOps;
@@ -745,13 +744,8 @@
SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
-
calculateFragments(firstOutFragments, lastInFragments);
-
- TransitionState state = null;
- if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) {
- state = beginTransition(firstOutFragments, lastInFragments, false);
- }
+ beginTransition(firstOutFragments, lastInFragments, false);
Op op = mHead;
while (op != null) {
@@ -842,10 +836,6 @@
if (mAddToBackStack) {
mManager.addBackStackState(this);
}
-
- if (state != null) {
- updateTransitionEndState(state, firstOutFragments, lastInFragments, false);
- }
}
private static void setFirstOut(SparseArray<Fragment> fragments, Fragment fragment) {
@@ -920,43 +910,6 @@
op = op.next;
}
-
- if (!haveTransitions(firstOutFragments, lastInFragments, false)) {
- firstOutFragments.clear();
- lastInFragments.clear();
- }
- }
-
- /**
- * @return true if custom transitions exist on any fragment in firstOutFragments or
- * lastInFragments or false otherwise.
- */
- private static boolean haveTransitions(SparseArray<Fragment> firstOutFragments,
- SparseArray<Fragment> lastInFragments, boolean isBack) {
- for (int i = firstOutFragments.size() - 1; i >= 0; i--) {
- Fragment f = firstOutFragments.valueAt(i);
- if (isBack) {
- if (f.getReturnTransition() != null ||
- f.getSharedElementReturnTransition() != null) {
- return true;
- }
- } else if (f.getExitTransition() != null) {
- return true;
- }
- }
-
- for (int i = lastInFragments.size() - 1; i >= 0; i--) {
- Fragment f = lastInFragments.valueAt(i);
- if (isBack) {
- if (f.getReenterTransition() != null) {
- return true;
- }
- } else if (f.getEnterTransition() != null ||
- f.getSharedElementEnterTransition() != null) {
- return true;
- }
- }
- return false;
}
/**
@@ -1003,11 +956,6 @@
op = op.next;
}
-
- if (!haveTransitions(firstOutFragments, lastInFragments, true)) {
- firstOutFragments.clear();
- lastInFragments.clear();
- }
}
/**
@@ -1038,8 +986,8 @@
* @param isBack true if this is popping the back stack or false if this is a
* forward operation.
* @return The TransitionState used to complete the operation of the transition
- * in {@link #updateTransitionEndState(android.app.BackStackRecord.TransitionState,
- * android.util.SparseArray, android.util.SparseArray, boolean)}.
+ * in {@link #setNameOverrides(android.app.BackStackRecord.TransitionState, java.util.ArrayList,
+ * java.util.ArrayList)}.
*/
private TransitionState beginTransition(SparseArray<Fragment> firstOutFragments,
SparseArray<Fragment> lastInFragments, boolean isBack) {
@@ -1050,16 +998,11 @@
// add any, then no views will be targeted.
state.nonExistentView = new View(mManager.mActivity);
- ArrayMap<String, View> tempViews1 = new ArrayMap<String, View>();
- ArrayMap<String, View> tempViews2 = new ArrayMap<String, View>();
- ArrayList<String> tempNames = new ArrayList<String>();
- ArrayList<View> tempViewList = new ArrayList<View>();
-
// Go over all leaving fragments.
for (int i = 0; i < firstOutFragments.size(); i++) {
int containerId = firstOutFragments.keyAt(i);
configureTransitions(containerId, state, isBack, firstOutFragments,
- lastInFragments, tempViews1, tempViews2, tempNames, tempViewList);
+ lastInFragments);
}
// Now go over all entering fragments that didn't have a leaving fragment.
@@ -1067,28 +1010,33 @@
int containerId = lastInFragments.keyAt(i);
if (firstOutFragments.get(containerId) == null) {
configureTransitions(containerId, state, isBack, firstOutFragments,
- lastInFragments, tempViews1, tempViews2, tempNames, tempViewList);
+ lastInFragments);
}
}
-
- if (state.overallTransitions.size() == 0) {
- state = null;
- }
return state;
}
+ private static Transition cloneTransition(Transition transition) {
+ if (transition != null) {
+ transition = transition.clone();
+ }
+ return transition;
+ }
+
private static Transition getEnterTransition(Fragment inFragment, boolean isBack) {
if (inFragment == null) {
return null;
}
- return isBack ? inFragment.getReenterTransition() : inFragment.getEnterTransition();
+ return cloneTransition(isBack ? inFragment.getReenterTransition() :
+ inFragment.getEnterTransition());
}
private static Transition getExitTransition(Fragment outFragment, boolean isBack) {
if (outFragment == null) {
return null;
}
- return isBack ? outFragment.getReturnTransition() : outFragment.getExitTransition();
+ return cloneTransition(isBack ? outFragment.getReturnTransition() :
+ outFragment.getExitTransition());
}
private static Transition getSharedElementTransition(Fragment inFragment, Fragment outFragment,
@@ -1096,34 +1044,32 @@
if (inFragment == null || outFragment == null) {
return null;
}
- return isBack ? outFragment.getSharedElementReturnTransition() :
- inFragment.getSharedElementEnterTransition();
+ return cloneTransition(isBack ? outFragment.getSharedElementReturnTransition() :
+ inFragment.getSharedElementEnterTransition());
}
- private static Transition captureExitingViews(Transition exitTransition, Fragment outFragment,
- ArrayList<View> viewList) {
+ private static ArrayList<View> captureExitingViews(Transition exitTransition,
+ Fragment outFragment) {
+ ArrayList<View> viewList = null;
if (exitTransition != null) {
+ viewList = new ArrayList<View>();
View root = outFragment.getView();
- viewList.clear();
root.captureTransitioningViews(viewList);
- if (viewList.isEmpty()) {
- exitTransition = null;
- } else {
- addTransitioningViews(exitTransition, viewList);
- }
+ addTargets(exitTransition, viewList);
}
- return exitTransition;
+ return viewList;
}
private ArrayMap<String, View> remapSharedElements(TransitionState state, Fragment outFragment,
- ArrayMap<String, View> namedViews, ArrayMap<String, View> tempViews2, boolean isBack) {
+ boolean isBack) {
+ ArrayMap<String, View> namedViews = new ArrayMap<String, View>();
if (mSharedElementSourceNames != null) {
outFragment.getView().findNamedViews(namedViews);
if (isBack) {
namedViews.retainAll(mSharedElementTargetNames);
} else {
namedViews = remapNames(mSharedElementSourceNames, mSharedElementTargetNames,
- namedViews, tempViews2);
+ namedViews);
}
}
@@ -1147,41 +1093,94 @@
* We will add to the views before the end state of the transition is captured so that the
* views will appear. At the start of the transition, we clear the list of targets so that
* we can restore the state of the transition and use it again.
+ *
+ * <p>The shared element transition maps its shared elements immediately prior to
+ * capturing the final state of the Transition.</p>
*/
- private void prepareEnterTransition(TransitionState state, final Transition enterTransition,
- final View container, final Fragment inFragment) {
- if (enterTransition != null) {
- final ArrayList<View> enteringViews = new ArrayList<View>();
- final View nonExistentView = state.nonExistentView;
- enterTransition.addTarget(state.nonExistentView);
- enterTransition.addListener(new Transition.TransitionListenerAdapter() {
- @Override
- public void onTransitionStart(Transition transition) {
- transition.removeListener(this);
- transition.removeTarget(nonExistentView);
- int numViews = enteringViews.size();
- for (int i = 0; i < numViews; i++) {
- transition.removeTarget(enteringViews.get(i));
- }
- }
- });
- container.getViewTreeObserver().addOnPreDrawListener(
- new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- container.getViewTreeObserver().removeOnPreDrawListener(this);
+ private ArrayList<View> addTransitionTargets(final TransitionState state,
+ final Transition enterTransition, final Transition sharedElementTransition,
+ final Transition overallTransition, final View container,
+ final Fragment inFragment, final Fragment outFragment,
+ final ArrayList<View> hiddenFragmentViews, final boolean isBack) {
+ if (enterTransition == null && sharedElementTransition == null &&
+ overallTransition == null) {
+ return null;
+ }
+ final ArrayList<View> enteringViews = new ArrayList<View>();
+ container.getViewTreeObserver().addOnPreDrawListener(
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ container.getViewTreeObserver().removeOnPreDrawListener(this);
+
+ // Don't include any newly-hidden fragments in the transition.
+ excludeHiddenFragments(hiddenFragmentViews, inFragment.mContainerId,
+ overallTransition);
+
+ if (sharedElementTransition != null) {
+ ArrayMap<String, View> namedViews = mapSharedElementsIn(
+ state, isBack, inFragment);
+
+ setEpicenterIn(namedViews, state);
+
+ callSharedElementEnd(state, inFragment, outFragment, isBack,
+ namedViews);
+ }
+
+ if (enterTransition != null) {
View view = inFragment.getView();
if (view != null) {
view.captureTransitioningViews(enteringViews);
- addTransitioningViews(enterTransition, enteringViews);
+ addTargets(enterTransition, enteringViews);
}
- return true;
+ setSharedElementEpicenter(enterTransition, state);
}
- });
- setSharedElementEpicenter(enterTransition, state);
+ return true;
+ }
+ });
+ return enteringViews;
+ }
+
+ private void callSharedElementEnd(TransitionState state, Fragment inFragment,
+ Fragment outFragment, boolean isBack, ArrayMap<String, View> namedViews) {
+ SharedElementCallback sharedElementCallback = isBack ?
+ outFragment.mEnterTransitionCallback :
+ inFragment.mEnterTransitionCallback;
+ ArrayList<String> names = new ArrayList<String>(namedViews.keySet());
+ ArrayList<View> views = new ArrayList<View>(namedViews.values());
+ sharedElementCallback.onSharedElementEnd(names, views, null);
+ }
+
+ private void setEpicenterIn(ArrayMap<String, View> namedViews, TransitionState state) {
+ if (mSharedElementTargetNames != null && !namedViews.isEmpty()) {
+ // now we know the epicenter of the entering transition.
+ View epicenter = namedViews
+ .get(mSharedElementTargetNames.get(0));
+ if (epicenter != null) {
+ state.enteringEpicenterView = epicenter;
+ }
}
}
+ private ArrayMap<String, View> mapSharedElementsIn(TransitionState state,
+ boolean isBack, Fragment inFragment) {
+ // Now map the shared elements in the incoming fragment
+ ArrayMap<String, View> namedViews = mapEnteringSharedElements(state, inFragment, isBack);
+
+ // remap shared elements and set the name mapping used
+ // in the shared element transition.
+ if (isBack) {
+ inFragment.mExitTransitionCallback.onMapSharedElements(
+ mSharedElementTargetNames, namedViews);
+ setBackNameOverrides(state, namedViews, true);
+ } else {
+ inFragment.mEnterTransitionCallback.onMapSharedElements(
+ mSharedElementTargetNames, namedViews);
+ setNameOverrides(state, namedViews, true);
+ }
+ return namedViews;
+ }
+
private static Transition mergeTransitions(Transition enterTransition,
Transition exitTransition, Transition sharedElementTransition, Fragment inFragment,
boolean isBack) {
@@ -1209,26 +1208,16 @@
* Configures custom transitions for a specific fragment container.
*
* @param containerId The container ID of the fragments to configure the transition for.
- * @param state The Transition State to be shared with {@link #updateTransitionEndState(
- * android.app.BackStackRecord.TransitionState, android.util.SparseArray,
- * android.util.SparseArray, boolean)} later.
+ * @param state The Transition State keeping track of the executing transitions.
* @param firstOutFragments The list of first fragments to be removed, keyed on the
* container ID.
* @param lastInFragments The list of last fragments to be added, keyed on the
* container ID.
* @param isBack true if this is popping the back stack or false if this is a
* forward operation.
- * @param tempViews1 A temporary mapping of names to Views, used to avoid allocation
- * inside a loop.
- * @param tempViews2 A temporary mapping of names to Views, used to avoid allocation
- * inside a loop.
- * @param tempNames A temporary list of Strings, used to avoid allocation inside a loop.
- * @param tempViewList A temporary list of Views, used to avoid allocation inside a loop.
*/
private void configureTransitions(int containerId, TransitionState state, boolean isBack,
- SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments,
- ArrayMap<String, View> tempViews1, ArrayMap<String, View> tempViews2,
- ArrayList<String> tempNames, ArrayList<View> tempViewList) {
+ SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments) {
ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.findViewById(containerId);
if (sceneRoot != null) {
Fragment inFragment = lastInFragments.get(containerId);
@@ -1238,146 +1227,150 @@
Transition sharedElementTransition = getSharedElementTransition(inFragment, outFragment,
isBack);
Transition exitTransition = getExitTransition(outFragment, isBack);
- exitTransition = captureExitingViews(exitTransition, outFragment, tempViewList);
- ArrayMap<String, View> namedViews = tempViews1;
- namedViews.clear();
- if (sharedElementTransition != null) {
- namedViews = remapSharedElements(state,
- outFragment, namedViews, tempViews2, isBack);
+ if (enterTransition == null && sharedElementTransition == null &&
+ exitTransition == null) {
+ return; // no transitions!
+ }
+ ArrayList<View> exitingViews = captureExitingViews(exitTransition, outFragment);
+ if (exitingViews == null || exitingViews.isEmpty()) {
+ exitTransition = null;
}
- // Notify the start of the transition.
- SharedElementCallback callback = isBack ?
- outFragment.mEnterTransitionCallback :
- inFragment.mEnterTransitionCallback;
- tempNames.clear();
- tempNames.addAll(namedViews.keySet());
- tempViewList.clear();
- tempViewList.addAll(namedViews.values());
- callback.onSharedElementStart(tempNames, tempViewList, null);
+ ArrayMap<String, View> namedViews = null;
+ if (sharedElementTransition != null) {
+ namedViews = remapSharedElements(state, outFragment, isBack);
+
+ // Notify the start of the transition.
+ SharedElementCallback callback = isBack ?
+ outFragment.mEnterTransitionCallback :
+ inFragment.mEnterTransitionCallback;
+ ArrayList<String> names = new ArrayList<String>(namedViews.keySet());
+ ArrayList<View> views = new ArrayList<View>(namedViews.values());
+ callback.onSharedElementStart(names, views, null);
+ }
// Set the epicenter of the exit transition
- if (mSharedElementTargetNames != null && exitTransition != null) {
+ if (mSharedElementTargetNames != null && exitTransition != null && namedViews != null) {
View epicenterView = namedViews.get(mSharedElementTargetNames.get(0));
if (epicenterView != null) {
setEpicenter(exitTransition, epicenterView);
}
}
- prepareEnterTransition(state, enterTransition, sceneRoot, inFragment);
-
Transition transition = mergeTransitions(enterTransition, exitTransition,
sharedElementTransition, inFragment, isBack);
if (transition != null) {
- state.overallTransitions.put(containerId, transition);
+ ArrayList<View> hiddenFragments = new ArrayList<View>();
+ ArrayList<View> enteringViews = addTransitionTargets(state, enterTransition,
+ sharedElementTransition, transition, sceneRoot, inFragment, outFragment,
+ hiddenFragments, isBack);
+
transition.setNameOverrides(state.nameOverrides);
// We want to exclude hidden views later, so we need a non-null list in the
// transition now.
transition.excludeTarget(state.nonExistentView, true);
// Now exclude all currently hidden fragments.
- excludeHiddenFragments(state, containerId, transition);
- cleanupHiddenFragments(transition, state);
+ excludeHiddenFragments(hiddenFragments, containerId, transition);
TransitionManager.beginDelayedTransition(sceneRoot, transition);
+ // Remove the view targeting after the transition starts
+ removeTargetedViewsFromTransitions(sceneRoot, state.nonExistentView,
+ enterTransition, enteringViews, exitTransition, exitingViews,
+ transition, hiddenFragments);
}
}
}
/**
+ * After the transition has started, remove all targets that we added to the transitions
+ * so that the transitions are left in a clean state.
+ */
+ private void removeTargetedViewsFromTransitions(
+ final ViewGroup sceneRoot, final View nonExistingView,
+ final Transition enterTransition, final ArrayList<View> enteringViews,
+ final Transition exitTransition, final ArrayList<View> exitingViews,
+ final Transition overallTransition, final ArrayList<View> hiddenViews) {
+ if (enterTransition != null || exitTransition != null) {
+ sceneRoot.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
+ if (enterTransition != null) {
+ enterTransition.removeTarget(nonExistingView);
+ removeTargets(enterTransition, enteringViews);
+ }
+ if (exitTransition != null) {
+ removeTargets(exitTransition, exitingViews);
+ }
+ int numViews = hiddenViews.size();
+ for (int i = 0; i < numViews; i++) {
+ overallTransition.excludeTarget(hiddenViews.get(i), false);
+ }
+ overallTransition.excludeTarget(nonExistingView, false);
+ return true;
+ }
+ });
+ }
+ }
+
+ private static void removeTargets(Transition transition, ArrayList<View> views) {
+ int numViews = views.size();
+ for (int i = 0; i < numViews; i++) {
+ transition.removeTarget(views.get(i));
+ }
+ }
+
+ private static void addTargets(Transition transition, ArrayList<View> views) {
+ int numViews = views.size();
+ for (int i = 0; i < numViews; i++) {
+ transition.addTarget(views.get(i));
+ }
+ }
+
+ /**
* Remaps a name-to-View map, substituting different names for keys.
*
* @param inMap A list of keys found in the map, in the order in toGoInMap
* @param toGoInMap A list of keys to use for the new map, in the order of inMap
* @param namedViews The current mapping
- * @param tempMap A temporary mapping that will be filled with the new values.
- * @return tempMap after it has been mapped with the new names as keys.
+ * @return a new Map after it has been mapped with the new names as keys.
*/
private static ArrayMap<String, View> remapNames(ArrayList<String> inMap,
- ArrayList<String> toGoInMap, ArrayMap<String, View> namedViews,
- ArrayMap<String, View> tempMap) {
- tempMap.clear();
+ ArrayList<String> toGoInMap, ArrayMap<String, View> namedViews) {
+ ArrayMap<String, View> remappedViews = new ArrayMap<String, View>();
if (!namedViews.isEmpty()) {
int numKeys = inMap.size();
for (int i = 0; i < numKeys; i++) {
View view = namedViews.get(inMap.get(i));
+
if (view != null) {
- tempMap.put(toGoInMap.get(i), view);
+ remappedViews.put(toGoInMap.get(i), view);
}
}
}
- return tempMap;
+ return remappedViews;
}
/**
- * After making all fragment changes, this updates the custom transitions to take into
- * account the entering views and any remapping.
+ * Maps shared elements to views in the entering fragment.
*
* @param state The transition State as returned from {@link #beginTransition(
* android.util.SparseArray, android.util.SparseArray, boolean)}.
- * @param outFragments The list of first fragments to be removed, keyed on the
- * container ID.
- * @param inFragments The list of last fragments to be added, keyed on the
- * container ID.
+ * @param inFragment The last fragment to be added.
* @param isBack true if this is popping the back stack or false if this is a
* forward operation.
*/
- private void updateTransitionEndState(TransitionState state, SparseArray<Fragment> outFragments,
- SparseArray<Fragment> inFragments, boolean isBack) {
- ArrayMap<String, View> tempViews1 = new ArrayMap<String, View>();
- ArrayMap<String, View> tempViews2 = new ArrayMap<String, View>();
- ArrayList<String> tempNames = new ArrayList<String>();
- ArrayList<View> tempViews = new ArrayList<View>();
-
- int numInFragments = inFragments.size();
- for (int i = 0; i < numInFragments; i++) {
- Fragment inFragment = inFragments.valueAt(i);
- tempViews1.clear();
- ArrayMap<String, View> namedViews = mapEnteringSharedElements(inFragment, tempViews1,
- tempViews2, isBack);
- // remap shared elements and set the name mapping used in the shared element transition.
- if (isBack) {
- inFragment.mExitTransitionCallback.onMapSharedElements(
- mSharedElementTargetNames, namedViews);
- setBackNameOverrides(state, namedViews, true);
- } else {
- inFragment.mEnterTransitionCallback.onMapSharedElements(
- mSharedElementTargetNames, namedViews);
- setNameOverrides(state, namedViews, true);
- }
-
- if (mSharedElementTargetNames != null && !namedViews.isEmpty()) {
- // now we know the epicenter of the entering transition.
- View epicenter = namedViews.get(mSharedElementTargetNames.get(0));
- if (epicenter != null) {
- state.enteringEpicenterView = epicenter;
- }
- }
-
- int containerId = inFragments.keyAt(i);
- SharedElementCallback sharedElementCallback = isBack ?
- outFragments.get(containerId).mEnterTransitionCallback :
- inFragment.mEnterTransitionCallback;
- tempNames.clear();
- tempNames.addAll(namedViews.keySet());
- tempViews.clear();
- tempViews.addAll(namedViews.values());
- sharedElementCallback.onSharedElementEnd(tempNames, tempViews, null);
- }
-
- // Don't include any newly-hidden fragments in the transition.
- excludeHiddenFragments(state);
- }
-
- private ArrayMap<String, View> mapEnteringSharedElements(Fragment inFragment,
- ArrayMap<String, View> namedViews, ArrayMap<String, View> tempViews2, boolean isBack) {
+ private ArrayMap<String, View> mapEnteringSharedElements(TransitionState state,
+ Fragment inFragment, boolean isBack) {
+ ArrayMap<String, View> namedViews = new ArrayMap<String, View>();
View root = inFragment.getView();
if (root != null) {
if (mSharedElementSourceNames != null) {
root.findNamedViews(namedViews);
if (isBack) {
namedViews = remapNames(mSharedElementSourceNames,
- mSharedElementTargetNames, namedViews, tempViews2);
+ mSharedElementTargetNames, namedViews);
} else {
namedViews.retainAll(mSharedElementTargetNames);
}
@@ -1386,21 +1379,7 @@
return namedViews;
}
- private static void cleanupHiddenFragments(Transition transition, TransitionState state) {
- final ArrayList<View> hiddenViews = state.hiddenFragmentViews;
- transition.addListener(new Transition.TransitionListenerAdapter() {
- @Override
- public void onTransitionStart(Transition transition) {
- transition.removeListener(this);
- int numViews = hiddenViews.size();
- for (int i = 0; i < numViews; i++) {
- transition.excludeTarget(hiddenViews.get(i), false);
- }
- }
- });
- }
-
- private void excludeHiddenFragments(TransitionState state, int containerId,
+ private void excludeHiddenFragments(final ArrayList<View> hiddenFragmentViews, int containerId,
Transition transition) {
if (mManager.mAdded != null) {
for (int i = 0; i < mManager.mAdded.size(); i++) {
@@ -1408,44 +1387,19 @@
if (fragment.mView != null && fragment.mContainer != null &&
fragment.mContainerId == containerId) {
if (fragment.mHidden) {
- if (!state.hiddenFragmentViews.contains(fragment.mView)) {
+ if (!hiddenFragmentViews.contains(fragment.mView)) {
transition.excludeTarget(fragment.mView, true);
- state.hiddenFragmentViews.add(fragment.mView);
+ hiddenFragmentViews.add(fragment.mView);
}
} else {
transition.excludeTarget(fragment.mView, false);
- state.hiddenFragmentViews.remove(fragment.mView);
+ hiddenFragmentViews.remove(fragment.mView);
}
}
}
}
}
- private void excludeHiddenFragments(TransitionState state) {
- int numTransitions = state.overallTransitions.size();
- for (int i = 0; i < numTransitions; i++) {
- Transition transition = state.overallTransitions.valueAt(i);
- int containerId = state.overallTransitions.keyAt(i);
- excludeHiddenFragments(state, containerId, transition);
- }
- }
-
- private static void addTransitioningViews(Transition transition, final Collection<View> views) {
- for (View view : views) {
- transition.addTarget(view);
- }
-
- transition.addListener(new Transition.TransitionListenerAdapter() {
- @Override
- public void onTransitionStart(Transition transition) {
- transition.removeListener(this);
- for (View view : views) {
- transition.removeTarget(view);
- }
- }
- });
- }
-
private static void setEpicenter(Transition transition, View view) {
final Rect epicenter = new Rect();
view.getBoundsOnScreen(epicenter);
@@ -1566,10 +1520,7 @@
if (doStateMove) {
mManager.moveToState(mManager.mCurState,
FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle, true);
- if (state != null) {
- updateTransitionEndState(state, firstOutFragments, lastInFragments, true);
- state = null;
- }
+ state = null;
}
if (mIndex >= 0) {
@@ -1609,11 +1560,14 @@
for (int i = 0; i < count; i++) {
String source = mSharedElementSourceNames.get(i);
String originalTarget = mSharedElementTargetNames.get(i);
- String target = namedViews.get(originalTarget).getTransitionName();
- if (isEnd) {
- setNameOverride(state.nameOverrides, source, target);
- } else {
- setNameOverride(state.nameOverrides, target, source);
+ View view = namedViews.get(originalTarget);
+ if (view != null) {
+ String target = view.getTransitionName();
+ if (isEnd) {
+ setNameOverride(state.nameOverrides, source, target);
+ } else {
+ setNameOverride(state.nameOverrides, target, source);
+ }
}
}
}
@@ -1649,10 +1603,7 @@
}
public class TransitionState {
- public SparseArray<Transition> overallTransitions = new SparseArray<Transition>();
public ArrayMap<String, String> nameOverrides = new ArrayMap<String, String>();
- public ArrayList<View> hiddenFragmentViews = new ArrayList<View>();
-
public View enteringEpicenterView;
public View nonExistentView;
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 91a0aed..64eafb0 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2237,7 +2237,6 @@
mUser = user;
mPackageInfo = packageInfo;
- mContentResolver = new ApplicationContentResolver(this, mainThread, user);
mResourcesManager = ResourcesManager.getInstance();
mDisplay = display;
mOverrideConfiguration = overrideConfiguration;
@@ -2284,6 +2283,8 @@
mOpPackageName = mBasePackageName;
}
}
+
+ mContentResolver = new ApplicationContentResolver(this, mainThread, user);
}
void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index f432c49..922561d 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -112,9 +112,9 @@
protected void viewsReady(ArrayMap<String, View> sharedElements) {
super.viewsReady(sharedElements);
mIsReadyForTransition = true;
- setTransitionAlpha(mSharedElements, 0);
+ hideViews(mSharedElements);
if (getViewsTransition() != null) {
- setTransitionAlpha(mTransitioningViews, 0);
+ hideViews(mTransitioningViews);
}
if (mIsReturning) {
sendSharedElementDestination();
@@ -136,11 +136,12 @@
if (sharedElements.isEmpty() || !sharedElements.valueAt(0).isLayoutRequested()) {
viewsReady(sharedElements);
} else {
- sharedElements.valueAt(0).getViewTreeObserver()
+ final View sharedElement = sharedElements.valueAt(0);
+ sharedElement.getViewTreeObserver()
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- sharedElements.valueAt(0).getViewTreeObserver().removeOnPreDrawListener(this);
+ sharedElement.getViewTreeObserver().removeOnPreDrawListener(this);
viewsReady(sharedElements);
return true;
}
@@ -240,7 +241,7 @@
if (!mIsCanceled) {
mIsCanceled = true;
if (getViewsTransition() == null || mIsViewsTransitionStarted) {
- setTransitionAlpha(mSharedElements, 1);
+ showViews(mSharedElements, true);
} else {
mTransitioningViews.addAll(mSharedElements);
}
@@ -300,7 +301,7 @@
// Now start shared element transition
ArrayList<View> sharedElementSnapshots = createSnapshots(sharedElementState,
mSharedElementNames);
- setTransitionAlpha(mSharedElements, 1);
+ showViews(mSharedElements, true);
scheduleSetSharedElementEnd(sharedElementSnapshots);
ArrayList<SharedElementOriginalState> originalImageViewState =
setSharedElementState(sharedElementState, sharedElementSnapshots);
@@ -411,7 +412,7 @@
@Override
public void onTransitionStart(Transition transition) {
mEnterViewsTransition = transition;
- setTransitionAlpha(mTransitioningViews, 1);
+ showViews(mTransitioningViews, false);
super.onTransitionStart(transition);
}
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index a59a927..e85ec63 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -126,8 +126,8 @@
}
public void resetViews() {
- setTransitionAlpha(mTransitioningViews, 1);
- setTransitionAlpha(mSharedElements, 1);
+ showViews(mTransitioningViews, true);
+ showViews(mSharedElements, true);
mIsHidden = true;
if (!mIsReturning && getDecor() != null) {
getDecor().suppressLayout(false);
@@ -187,7 +187,7 @@
private void hideSharedElements() {
moveSharedElementsFromOverlay();
if (!mIsHidden) {
- setTransitionAlpha(mSharedElements, 0);
+ hideViews(mSharedElements);
}
mSharedElementsHidden = true;
finishIfNecessary();
@@ -296,7 +296,7 @@
transition.removeListener(this);
exitTransitionComplete();
if (mIsHidden) {
- setTransitionAlpha(mTransitioningViews, 1);
+ showViews(mTransitioningViews, true);
}
if (mSharedElementBundle != null) {
delayCancel();
@@ -323,7 +323,7 @@
transition.removeListener(this);
sharedElementTransitionComplete();
if (mIsHidden) {
- setTransitionAlpha(mSharedElements, 1);
+ showViews(mSharedElements, true);
}
}
});
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 672ef7b..4374622 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -166,11 +166,12 @@
* activity: if the activity is stopped, no fragments inside of it can be
* started; when the activity is destroyed, all fragments will be destroyed.
*
- * <p>All subclasses of Fragment must include a public empty constructor.
+ * <p>All subclasses of Fragment must include a public no-argument constructor.
* The framework will often re-instantiate a fragment class when needed,
* in particular during state restore, and needs to be able to find this
- * constructor to instantiate it. If the empty constructor is not available,
- * a runtime exception will occur in some cases during state restore.
+ * constructor to instantiate it. If the no-argument constructor is not
+ * available, a runtime exception will occur in some cases during state
+ * restore.
*
* <p>Topics covered here:
* <ol>
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 9483680..8fa1fd53 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -327,6 +327,8 @@
public void notifyActivityDrawn(IBinder token) throws RemoteException;
public ActivityOptions getActivityOptions(IBinder token) throws RemoteException;
+ public void bootAnimationComplete() throws RemoteException;
+
public void setImmersive(IBinder token, boolean immersive) throws RemoteException;
public boolean isImmersive(IBinder token) throws RemoteException;
public boolean isTopActivityImmersive() throws RemoteException;
@@ -772,4 +774,5 @@
int GET_APP_TASK_THUMBNAIL_SIZE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+234;
int RELEASE_ACTIVITY_INSTANCE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+235;
int RELEASE_SOME_ACTIVITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+236;
+ int BOOT_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+237;
}
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index 181eb63..3b5900b 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -16,6 +16,7 @@
package android.app;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.app.IWallpaperManagerCallback;
@@ -73,6 +74,11 @@
int getHeightHint();
/**
+ * Sets extra padding that we would like the wallpaper to have outside of the display.
+ */
+ void setDisplayPadding(in Rect padding);
+
+ /**
* Returns the name of the wallpaper. Private API.
*/
String getName();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 1083943..f9e4895 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -545,8 +545,26 @@
*/
public int visibility;
+ /**
+ * Notification visibility: Show this notification in its entirety on all lockscreens.
+ *
+ * {@see #visibility}
+ */
public static final int VISIBILITY_PUBLIC = 1;
+
+ /**
+ * Notification visibility: Show this notification on all lockscreens, but conceal sensitive or
+ * private information on secure lockscreens.
+ *
+ * {@see #visibility}
+ */
public static final int VISIBILITY_PRIVATE = 0;
+
+ /**
+ * Notification visibility: Do not reveal any part of this notification on a secure lockscreen.
+ *
+ * {@see #visibility}
+ */
public static final int VISIBILITY_SECRET = -1;
/**
@@ -824,6 +842,13 @@
public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions";
/**
+ * {@link #extras} key: the user that built the notification.
+ *
+ * @hide
+ */
+ public static final String EXTRA_ORIGINATING_USERID = "android.originatingUserId";
+
+ /**
* Value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification should not be
* displayed in the heads up space.
*
@@ -1862,6 +1887,11 @@
private int mColor = COLOR_DEFAULT;
/**
+ * The user that built the notification originally.
+ */
+ private int mOriginatingUserId;
+
+ /**
* Contains extras related to rebuilding during the build phase.
*/
private Bundle mRebuildBundle = new Bundle();
@@ -2581,7 +2611,7 @@
// Note: This assumes that the current user can read the profile badge of the
// originating user.
return mContext.getPackageManager().getUserBadgeForDensity(
- new UserHandle(mContext.getUserId()), 0);
+ new UserHandle(mOriginatingUserId), 0);
}
private Bitmap getProfileBadge() {
@@ -2721,9 +2751,9 @@
} else {
contentView.setViewVisibility(R.id.text2, View.GONE);
if (hasProgress && (mProgressMax != 0 || mProgressIndeterminate)) {
+ contentView.setViewVisibility(R.id.progress, View.VISIBLE);
contentView.setProgressBar(
R.id.progress, mProgressMax, mProgress, mProgressIndeterminate);
- contentView.setViewVisibility(R.id.progress, View.VISIBLE);
showLine2 = true;
} else {
contentView.setViewVisibility(R.id.progress, View.GONE);
@@ -3052,6 +3082,7 @@
*/
public void populateExtras(Bundle extras) {
// Store original information used in the construction of this object
+ extras.putInt(EXTRA_ORIGINATING_USERID, mOriginatingUserId);
extras.putParcelable(EXTRA_REBUILD_CONTEXT_APPLICATION_INFO,
mContext.getApplicationInfo());
extras.putCharSequence(EXTRA_TITLE, mContentTitle);
@@ -3283,6 +3314,7 @@
// Extras.
Bundle extras = n.extras;
+ mOriginatingUserId = extras.getInt(EXTRA_ORIGINATING_USERID);
mContentTitle = extras.getCharSequence(EXTRA_TITLE);
mContentText = extras.getCharSequence(EXTRA_TEXT);
mSubText = extras.getCharSequence(EXTRA_SUB_TEXT);
@@ -3315,6 +3347,7 @@
* object.
*/
public Notification build() {
+ mOriginatingUserId = mContext.getUserId();
mHasThreeLines = hasThreeLines();
Notification n = buildUnstyled();
@@ -3386,8 +3419,16 @@
*/
public static abstract class Style {
private CharSequence mBigContentTitle;
- private CharSequence mSummaryText = null;
- private boolean mSummaryTextSet = false;
+
+ /**
+ * @hide
+ */
+ protected CharSequence mSummaryText = null;
+
+ /**
+ * @hide
+ */
+ protected boolean mSummaryTextSet = false;
protected Builder mBuilder;
@@ -3679,6 +3720,11 @@
* @see Notification#bigContentView
*/
public static class BigTextStyle extends Style {
+
+ private static final int MAX_LINES = 13;
+ private static final int LINES_CONSUMED_BY_ACTIONS = 3;
+ private static final int LINES_CONSUMED_BY_SUMMARY = 2;
+
private CharSequence mBigText;
public BigTextStyle() {
@@ -3745,6 +3791,7 @@
contentView.setTextViewText(R.id.big_text, mBuilder.processLegacyText(mBigText));
contentView.setViewVisibility(R.id.big_text, View.VISIBLE);
+ contentView.setInt(R.id.big_text, "setMaxLines", calculateMaxLines());
contentView.setViewVisibility(R.id.text2, View.GONE);
applyTopPadding(contentView);
@@ -3756,6 +3803,24 @@
return contentView;
}
+ private int calculateMaxLines() {
+ int lineCount = MAX_LINES;
+ boolean hasActions = mBuilder.mActions.size() > 0;
+ boolean hasSummary = (mSummaryTextSet ? mSummaryText : mBuilder.mSubText) != null;
+ if (hasActions) {
+ lineCount -= LINES_CONSUMED_BY_ACTIONS;
+ }
+ if (hasSummary) {
+ lineCount -= LINES_CONSUMED_BY_SUMMARY;
+ }
+
+ // If we have less top padding at the top, we can fit less lines.
+ if (!mBuilder.mHasThreeLines) {
+ lineCount--;
+ }
+ return lineCount;
+ }
+
/**
* @hide
*/
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 48ff5b6..8bfe6d3 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -951,6 +952,48 @@
}
/**
+ * Specify extra padding that the wallpaper should have outside of the display.
+ * That is, the given padding supplies additional pixels the wallpaper should extend
+ * outside of the display itself.
+ * @param padding The number of pixels the wallpaper should extend beyond the display,
+ * on its left, top, right, and bottom sides.
+ * @hide
+ */
+ @SystemApi
+ public void setDisplayPadding(Rect padding) {
+ try {
+ if (sGlobals.mService == null) {
+ Log.w(TAG, "WallpaperService not running");
+ } else {
+ sGlobals.mService.setDisplayPadding(padding);
+ }
+ } catch (RemoteException e) {
+ // Ignore
+ }
+ }
+
+ /**
+ * Apply a raw offset to the wallpaper window. Should only be used in
+ * combination with {@link #setDisplayPadding(android.graphics.Rect)} when you
+ * have ensured that the wallpaper will extend outside of the display area so that
+ * it can be moved without leaving part of the display uncovered.
+ * @param x The offset, in pixels, to apply to the left edge.
+ * @param y The offset, in pixels, to apply to the top edge.
+ * @hide
+ */
+ @SystemApi
+ public void setDisplayOffset(IBinder windowToken, int x, int y) {
+ try {
+ //Log.v(TAG, "Sending new wallpaper display offsets from app...");
+ WindowManagerGlobal.getWindowSession().setWallpaperDisplayOffset(
+ windowToken, x, y);
+ //Log.v(TAG, "...app returning after sending display offset!");
+ } catch (RemoteException e) {
+ // Ignore.
+ }
+ }
+
+ /**
* Set the position of the current wallpaper within any larger space, when
* that wallpaper is visible behind the given window. The X and Y offsets
* are floating point numbers ranging from 0 to 1, representing where the
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 112fc82..4a21913 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -38,6 +38,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.security.Credentials;
import android.service.restrictions.RestrictionsReceiver;
import android.util.Log;
@@ -49,6 +50,8 @@
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
@@ -97,8 +100,7 @@
* Provisioning adds a managed profile and sets the mdm as the profile owner who has full
* control over the profile
*
- * <p>This intent must contain the extras {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}
- * {@link #EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME} and {@link #EXTRA_DEVICE_ADMIN}.
+ * <p>This intent must contain the extra {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}.
*
* <p> When managed provisioning has completed, an intent of the type
* {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcasted to the
@@ -112,7 +114,7 @@
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_PROVISION_MANAGED_PROFILE
- = "android.app.action.ACTION_PROVISION_MANAGED_PROFILE";
+ = "android.app.action.PROVISION_MANAGED_PROFILE";
/**
* A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that allows
@@ -139,21 +141,18 @@
* message containing an Nfc record with MIME type {@link #MIME_TYPE_PROVISIONING_NFC}.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME
- = "android.app.extra.deviceAdminPackageName";
+ = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
/**
- * A String extra holding the default name of the profile that is created during managed profile
- * provisioning.
+ * A String extra that, holds the email address of the account which a managed profile is
+ * created for. Used with {@link #ACTION_PROVISION_MANAGED_PROFILE} and
+ * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}.
*
- * <p>Use with {@link #ACTION_PROVISION_MANAGED_PROFILE}
- */
- public static final String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME
- = "android.app.extra.PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME";
-
- /**
- * A bundle key, used in the bundle extra {@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}. The
- * corresponding value holds the email address of the account which the managed profile is
- * created for.
+ * <p> If the {@link #ACTION_PROVISION_MANAGED_PROFILE} intent that starts managed provisioning
+ * contains this extra, it is forwarded in the
+ * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} intent to the mobile
+ * device management application that was set as the profile owner during provisioning.
+ * It is usually used to avoid that the user has to enter their email address twice.
*/
public static final String KEY_PROVISIONING_EMAIL_ADDRESS
= "android.app.key.PROVISIONING_EMAIL_ADDRESS";
@@ -441,13 +440,13 @@
* Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from a
* managed profile to its parent.
*/
- public static int FLAG_PARENT_CAN_ACCESS_MANAGED = 0x0001;
+ public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 0x0001;
/**
* Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from the
* parent to its managed profile.
*/
- public static int FLAG_MANAGED_CAN_ACCESS_PARENT = 0x0002;
+ public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 0x0002;
/**
* Return true if the given administrator component is currently
@@ -1842,6 +1841,32 @@
}
/**
+ * Called by a device or profile owner to install a certificate and private key pair. The
+ * keypair will be visible to all apps within the profile.
+ *
+ * @param who Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param privKey The private key to install.
+ * @param cert The certificate to install.
+ * @param alias The private key alias under which to install the certificate. If a certificate
+ * with that alias already exists, it will be overwritten.
+ * @return {@code true} if the keys were installed, {@code false} otherwise.
+ */
+ public boolean installKeyPair(ComponentName who, PrivateKey privKey, Certificate cert,
+ String alias) {
+ try {
+ final byte[] pemCert = Credentials.convertToPem(cert);
+ return mService.installKeyPair(who, privKey.getEncoded(), pemCert, alias);
+ } catch (CertificateException e) {
+ Log.w(TAG, "Error encoding certificate", e);
+ } catch (IOException e) {
+ Log.w(TAG, "Error writing certificate", e);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ return false;
+ }
+
+ /**
* Returns the alias of a given CA certificate in the certificate store, or null if it
* doesn't exist.
*/
@@ -3249,11 +3274,15 @@
* Called by profile or device owners to update {@link Settings.Secure} settings. Validation
* that the value of the setting is in the correct form for the setting type should be performed
* by the caller.
- * <p>The settings that can be updated with this method are:
+ * <p>The settings that can be updated by a profile or device owner with this method are:
* <ul>
* <li>{@link Settings.Secure#DEFAULT_INPUT_METHOD}</li>
* <li>{@link Settings.Secure#SKIP_FIRST_USE_HINTS}</li>
* </ul>
+ * <p>A device owner can additionally update the following settings:
+ * <ul>
+ * <li>{@link Settings.Secure#LOCATION_MODE}</li>
+ * </ul>
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param setting The name of the setting to update.
* @param value The value to update the setting to.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 57d8b95..c8e1780 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -126,6 +126,8 @@
void uninstallCaCert(in ComponentName admin, in String alias);
void enforceCanManageCaCerts(in ComponentName admin);
+ boolean installKeyPair(in ComponentName who, in byte[] privKeyBuffer, in byte[] certBuffer, String alias);
+
void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity);
void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName);
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 1bb4eba..9151a16 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -218,6 +218,7 @@
*/
@SystemApi
public boolean isBackupEnabled() {
+ checkServiceBinder();
if (sService != null) {
try {
return sService.isBackupEnabled();
diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java
index 724856a..62734f2 100644
--- a/core/java/android/app/job/JobParameters.java
+++ b/core/java/android/app/job/JobParameters.java
@@ -32,12 +32,15 @@
private final int jobId;
private final PersistableBundle extras;
private final IBinder callback;
+ private final boolean overrideDeadlineExpired;
/** @hide */
- public JobParameters(int jobId, PersistableBundle extras, IBinder callback) {
+ public JobParameters(IBinder callback, int jobId, PersistableBundle extras,
+ boolean overrideDeadlineExpired) {
this.jobId = jobId;
this.extras = extras;
this.callback = callback;
+ this.overrideDeadlineExpired = overrideDeadlineExpired;
}
/**
@@ -56,6 +59,16 @@
return extras;
}
+ /**
+ * For jobs with {@link android.app.job.JobInfo.Builder#setOverrideDeadline(long)} set, this
+ * provides an easy way to tell whether the job is being executed due to the deadline
+ * expiring. Note: If the job is running because its deadline expired, it implies that its
+ * constraints will not be met.
+ */
+ public boolean isOverrideDeadlineExpired() {
+ return overrideDeadlineExpired;
+ }
+
/** @hide */
public IJobCallback getCallback() {
return IJobCallback.Stub.asInterface(callback);
@@ -65,6 +78,7 @@
jobId = in.readInt();
extras = in.readPersistableBundle();
callback = in.readStrongBinder();
+ overrideDeadlineExpired = in.readInt() == 1;
}
@Override
@@ -77,6 +91,7 @@
dest.writeInt(jobId);
dest.writePersistableBundle(extras);
dest.writeStrongBinder(callback);
+ dest.writeInt(overrideDeadlineExpired ? 1 : 0);
}
public static final Creator<JobParameters> CREATOR = new Creator<JobParameters>() {
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index fde8b2e..2853c58 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -639,12 +639,14 @@
* @param authorities the semi-colon separated authorities of the ContentProvider.
*/
protected final void setAuthorities(String authorities) {
- if (authorities.indexOf(';') == -1) {
- mAuthority = authorities;
- mAuthorities = null;
- } else {
- mAuthority = null;
- mAuthorities = authorities.split(";");
+ if (authorities != null) {
+ if (authorities.indexOf(';') == -1) {
+ mAuthority = authorities;
+ mAuthorities = null;
+ } else {
+ mAuthority = null;
+ mAuthorities = authorities.split(";");
+ }
}
}
@@ -653,9 +655,11 @@
if (mAuthority != null) {
return mAuthority.equals(authority);
}
- int length = mAuthorities.length;
- for (int i = 0; i < length; i++) {
- if (mAuthorities[i].equals(authority)) return true;
+ if (mAuthorities != null) {
+ int length = mAuthorities.length;
+ for (int i = 0; i < length; i++) {
+ if (mAuthorities[i].equals(authority)) return true;
+ }
}
return false;
}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index b2b48e8..a09fee9 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1763,7 +1763,7 @@
* @param extras any extras to pass to the SyncAdapter.
*/
public static void requestSync(Account account, String authority, Bundle extras) {
- requestSyncAsUser(account, authority, UserHandle.getCallingUserId(), extras);
+ requestSyncAsUser(account, authority, UserHandle.myUserId(), extras);
}
/**
@@ -1938,7 +1938,7 @@
* @param sync true if the provider should be synced when tickles are received for it
*/
public static void setSyncAutomatically(Account account, String authority, boolean sync) {
- setSyncAutomaticallyAsUser(account, authority, sync, UserHandle.getCallingUserId());
+ setSyncAutomaticallyAsUser(account, authority, sync, UserHandle.myUserId());
}
/**
@@ -2165,7 +2165,7 @@
* @param sync the master auto-sync setting that applies to all the providers and accounts
*/
public static void setMasterSyncAutomatically(boolean sync) {
- setMasterSyncAutomaticallyAsUser(sync, UserHandle.getCallingUserId());
+ setMasterSyncAutomaticallyAsUser(sync, UserHandle.myUserId());
}
/**
@@ -2297,7 +2297,7 @@
* @return true if there is a pending sync with the matching account and authority
*/
public static boolean isSyncPending(Account account, String authority) {
- return isSyncPendingAsUser(account, authority, UserHandle.getCallingUserId());
+ return isSyncPendingAsUser(account, authority, UserHandle.myUserId());
}
/**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index f979a0c..61dd7476 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3062,6 +3062,14 @@
* "content://foo". It will not remove any prefix grants that exist at a
* higher level.
*
+ * <p>Prior to {@link android.os.Build.VERSION_CODES#L}, if you did not have
+ * regular permission access to a Uri, but had received access to it through
+ * a specific Uri permission grant, you could not revoke that grant with this
+ * function and a {@link SecurityException} would be thrown. As of
+ * {@link android.os.Build.VERSION_CODES#L}, this function will not throw a security exception,
+ * but will remove whatever permission grants to the Uri had been given to the app
+ * (or none).</p>
+ *
* @param uri The Uri you would like to revoke access to.
* @param modeFlags The desired access modes. Any combination of
* {@link Intent#FLAG_GRANT_READ_URI_PERMISSION
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 3e1f60a..6d9c58b 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -259,12 +259,6 @@
void addCrossProfileIntentFilter(in IntentFilter intentFilter, String ownerPackage,
int ownerUserId, int sourceUserId, int targetUserId, int flags);
- void addCrossProfileIntentsForPackage(in String packageName, int sourceUserId,
- int targetUserId);
-
- void removeCrossProfileIntentsForPackage(String packageName, int sourceUserId,
- int targetUserId);
-
void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage, int ownerUserId);
/**
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index f9370b3..d49bc50 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -278,21 +278,21 @@
/**
- * Adds a callback for changes to packages in current and managed profiles.
+ * Registers a callback for changes to packages in current and managed profiles.
*
- * @param callback The callback to add.
+ * @param callback The callback to register.
*/
- public void addCallback(Callback callback) {
- addCallback(callback, null);
+ public void registerCallback(Callback callback) {
+ registerCallback(callback, null);
}
/**
- * Adds a callback for changes to packages in current and managed profiles.
+ * Registers a callback for changes to packages in current and managed profiles.
*
- * @param callback The callback to add.
+ * @param callback The callback to register.
* @param handler that should be used to post callbacks on, may be null.
*/
- public void addCallback(Callback callback, Handler handler) {
+ public void registerCallback(Callback callback, Handler handler) {
synchronized (this) {
if (callback != null && !mCallbacks.contains(callback)) {
boolean addedFirstCallback = mCallbacks.size() == 0;
@@ -308,12 +308,12 @@
}
/**
- * Removes a callback that was previously added.
+ * Unregisters a callback that was previously registered.
*
- * @param callback The callback to remove.
- * @see #addCallback(Callback)
+ * @param callback The callback to unregister.
+ * @see #registerCallback(Callback)
*/
- public void removeCallback(Callback callback) {
+ public void unregisterCallback(Callback callback) {
synchronized (this) {
removeCallbackLocked(callback);
if (mCallbacks.size() == 0) {
@@ -500,44 +500,12 @@
}
}
- /** Remove after unbundled apps have migrated STOP SHIP */
- public static abstract class OnAppsChangedCallback extends Callback {
+ /** STOPSHIP remove when launcher 3 has been updated */
+ public void addCallback(Callback callback) {
+ registerCallback(callback);
}
-
- /** Remove after unbundled apps have migrated STOP SHIP */
- public void addOnAppsChangedCallback(OnAppsChangedCallback callback) {
- addCallback(callback, null);
- }
-
- /** Remove after unbundled apps have migrated STOP SHIP */
- public void addOnAppsChangedCallback(OnAppsChangedCallback callback, Handler handler) {
- addCallback(callback, handler);
- }
-
- /** Remove after unbundled apps have migrated STOP SHIP */
- public void removeOnAppsChangedCallback(OnAppsChangedCallback callback) {
- removeCallback(callback);
- }
-
- /** Remove after unbundled apps have migrated STOP SHIP */
- public void startActivityForProfile(ComponentName component, UserHandle user, Rect sourceBounds,
- Bundle opts) {
- startMainActivity(component, user, sourceBounds, opts);
- }
-
- /** Remove after unbundled apps have migrated STOP SHIP */
- public void showAppDetailsForProfile(ComponentName component, UserHandle user,
- Rect sourceBounds, Bundle opts) {
- startAppDetailsActivity(component, user, sourceBounds, opts);
- }
-
- /** Remove after unbundled apps have migrated STOP SHIP */
- public boolean isPackageEnabledForProfile(String packageName, UserHandle user) {
- return isPackageEnabled(packageName, user);
- }
-
- /** Remove after unbundled apps have migrated STOP SHIP */
- public boolean isActivityEnabledForProfile(ComponentName component, UserHandle user) {
- return isActivityEnabled(component, user);
+ /** STOPSHIP remove when launcher 3 has been updated */
+ public void removeCallback(Callback callback) {
+ unregisterCallback(callback);
}
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 0a211cf..06d4c4a 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -285,6 +285,9 @@
*
* @throws IOException if parameters were unsatisfiable, such as lack of
* disk space or unavailable media.
+ * @throws SecurityException when installation services are unavailable,
+ * such as when called from a restricted user.
+ * @throws IllegalArgumentException when {@link SessionParams} is invalid.
* @return positive, non-zero unique ID that represents the created session.
* This ID remains consistent across device reboots until the
* session is finalized. IDs are not reused during a given boot.
@@ -303,6 +306,11 @@
/**
* Open an existing session to actively perform work. To succeed, the caller
* must be the owner of the install session.
+ *
+ * @throws IOException if parameters were unsatisfiable, such as lack of
+ * disk space or unavailable media.
+ * @throws SecurityException when the caller does not own the session, or
+ * the session is invalid.
*/
public @NonNull Session openSession(int sessionId) throws IOException {
try {
@@ -319,6 +327,9 @@
* Update the icon representing the app being installed in a specific
* session. This should be roughly
* {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions.
+ *
+ * @throws SecurityException when the caller does not own the session, or
+ * the session is invalid.
*/
public void updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon) {
try {
@@ -331,6 +342,9 @@
/**
* Update the label representing the app being installed in a specific
* session.
+ *
+ * @throws SecurityException when the caller does not own the session, or
+ * the session is invalid.
*/
public void updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel) {
try {
@@ -341,6 +355,15 @@
}
}
+ /**
+ * Completely abandon the given session, destroying all staged data and
+ * rendering it invalid. Abandoned sessions will be reported to
+ * {@link SessionCallback} listeners as failures. This is equivalent to
+ * opening the session and calling {@link Session#abandon()}.
+ *
+ * @throws SecurityException when the caller does not own the session, or
+ * the session is invalid.
+ */
public void abandonSession(int sessionId) {
try {
mInstaller.abandonSession(sessionId);
@@ -350,7 +373,11 @@
}
/**
- * Return details for a specific session.
+ * Return details for a specific session. No special permissions are
+ * required to retrieve these details.
+ *
+ * @return details for the requested session, or {@code null} if the session
+ * does not exist.
*/
public @Nullable SessionInfo getSessionInfo(int sessionId) {
try {
@@ -361,7 +388,7 @@
}
/**
- * Return list of all active install sessions, regardless of the installer.
+ * Return list of all known install sessions, regardless of the installer.
*/
public @NonNull List<SessionInfo> getAllSessions() {
final ApplicationInfo info = mContext.getApplicationInfo();
@@ -379,7 +406,7 @@
}
/**
- * Return list of all install sessions owned by the calling app.
+ * Return list of all known install sessions owned by the calling app.
*/
public @NonNull List<SessionInfo> getMySessions() {
try {
@@ -547,7 +574,8 @@
}
/**
- * Register to watch for session lifecycle events.
+ * Register to watch for session lifecycle events. No special permissions
+ * are required to watch for these events.
*/
public void registerSessionCallback(@NonNull SessionCallback callback) {
registerSessionCallback(callback, new Handler());
@@ -560,7 +588,8 @@
}
/**
- * Register to watch for session lifecycle events.
+ * Register to watch for session lifecycle events. No special permissions
+ * are required to watch for these events.
*
* @param handler to dispatch callback events through, otherwise uses
* calling thread.
@@ -593,7 +622,7 @@
}
/**
- * Unregister an existing callback.
+ * Unregister a previously registered callback.
*/
public void unregisterSessionCallback(@NonNull SessionCallback callback) {
synchronized (mDelegates) {
@@ -686,6 +715,12 @@
* start at the beginning of the file.
* @param lengthBytes total size of the file being written, used to
* preallocate the underlying disk space, or -1 if unknown.
+ * The system may clear various caches as needed to allocate
+ * this space.
+ * @throws IOException if trouble opening the file for writing, such as
+ * lack of disk space or unavailable media.
+ * @throws SecurityException if called after the session has been
+ * committed or abandoned.
*/
public @NonNull OutputStream openWrite(@NonNull String name, long offsetBytes,
long lengthBytes) throws IOException {
@@ -719,6 +754,9 @@
* <p>
* This returns all names which have been previously written through
* {@link #openWrite(String, long, long)} as part of this session.
+ *
+ * @throws SecurityException if called after the session has been
+ * committed or abandoned.
*/
public @NonNull String[] getNames() throws IOException {
try {
@@ -738,6 +776,9 @@
* through {@link #openWrite(String, long, long)} as part of this
* session. For example, this stream may be used to calculate a
* {@link MessageDigest} of a written APK before committing.
+ *
+ * @throws SecurityException if called after the session has been
+ * committed or abandoned.
*/
public @NonNull InputStream openRead(@NonNull String name) throws IOException {
try {
@@ -759,6 +800,9 @@
* Once this method is called, no additional mutations may be performed
* on the session. If the device reboots before the session has been
* finalized, you may commit the session again.
+ *
+ * @throws SecurityException if streams opened through
+ * {@link #openWrite(String, long, long)} are still open.
*/
public void commit(@NonNull IntentSender statusReceiver) {
try {
@@ -783,7 +827,9 @@
/**
* Completely abandon this session, destroying all staged data and
- * rendering it invalid.
+ * rendering it invalid. Abandoned sessions will be reported to
+ * {@link SessionCallback} listeners as failures. This is equivalent to
+ * opening the session and calling {@link Session#abandon()}.
*/
public void abandon() {
try {
@@ -937,6 +983,18 @@
}
/** {@hide} */
+ public void setInstallFlagsInternal() {
+ installFlags |= PackageManager.INSTALL_INTERNAL;
+ installFlags &= ~PackageManager.INSTALL_EXTERNAL;
+ }
+
+ /** {@hide} */
+ public void setInstallFlagsExternal() {
+ installFlags |= PackageManager.INSTALL_EXTERNAL;
+ installFlags &= ~PackageManager.INSTALL_INTERNAL;
+ }
+
+ /** {@hide} */
public void dump(IndentingPrintWriter pw) {
pw.printPair("mode", mode);
pw.printHexPair("installFlags", installFlags);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 748fca2..8f3d90f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -201,12 +201,6 @@
public static final int MATCH_DEFAULT_ONLY = 0x00010000;
/**
- * Resolution and querying flag: do not resolve intents cross-profile.
- * @hide
- */
- public static final int NO_CROSS_PROFILE = 0x00020000;
-
- /**
* Flag for {@link addCrossProfileIntentFilter}: if this flag is set:
* when resolving an intent that matches the {@link CrossProfileIntentFilter}, the current
* profile will be skipped.
@@ -1531,6 +1525,22 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device supports verified boot.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device supports secure removal of users. When a user is deleted the data associated
+ * with that user is securely deleted and no longer available.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_SECURELY_REMOVES_USERS
+ = "android.software.securely_removes_users";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
* The device has a full implementation of the android.webkit.* APIs. Devices
* lacking this feature will not have a functioning WebView implementation.
*/
@@ -1554,6 +1564,15 @@
public static final String FEATURE_HDMI_CEC = "android.hardware.hdmi.cec";
/**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device has all of the inputs necessary to be considered a compatible game controller, or
+ * includes a compatible game controller in the box.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_GAMEPAD = "android.hardware.gamepad";
+
+
+ /**
* Action to external storage service to clean out removed apps.
* @hide
*/
@@ -2431,7 +2450,6 @@
* @see #MATCH_DEFAULT_ONLY
* @see #GET_INTENT_FILTERS
* @see #GET_RESOLVED_FILTER
- * @see #NO_CROSS_PROFILE
* @hide
*/
public abstract List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,
@@ -3875,22 +3893,6 @@
public abstract void clearCrossProfileIntentFilters(int sourceUserId);
/**
- * Forwards all intents for {@link packageName} for user {@link sourceUserId} to user
- * {@link targetUserId}.
- * @hide
- */
- public abstract void addCrossProfileIntentsForPackage(String packageName,
- int sourceUserId, int targetUserId);
-
- /**
- * Removes all intents for {@link packageName} for user {@link sourceUserId} to user
- * {@link targetUserId}.
- * @hide
- */
- public abstract void removeCrossProfileIntentsForPackage(String packageName,
- int sourceUserId, int targetUserId);
-
- /**
* @hide
*/
public abstract Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index e0fd532..ddb0a6d 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1099,9 +1099,12 @@
}
}
}
- } catch (GeneralSecurityException | IOException | RuntimeException e) {
+ } catch (GeneralSecurityException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING,
"Failed to collect certificates from " + apkPath, e);
+ } catch (IOException | RuntimeException e) {
+ throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
+ "Failed to collect certificates from " + apkPath, e);
} finally {
closeQuietly(jarFile);
}
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index c0383a3..c03be32 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -89,6 +89,7 @@
/** User is only partially created. */
public boolean partial;
+ public boolean guestToRemove;
public UserInfo(int id, String name, int flags) {
this(id, name, null, flags);
@@ -147,6 +148,7 @@
lastLoggedInTime = orig.lastLoggedInTime;
partial = orig.partial;
profileGroupId = orig.profileGroupId;
+ guestToRemove = orig.guestToRemove;
}
public UserHandle getUserHandle() {
@@ -172,6 +174,7 @@
dest.writeLong(lastLoggedInTime);
dest.writeInt(partial ? 1 : 0);
dest.writeInt(profileGroupId);
+ dest.writeInt(guestToRemove ? 1 : 0);
}
public static final Parcelable.Creator<UserInfo> CREATOR
@@ -194,5 +197,6 @@
lastLoggedInTime = source.readLong();
partial = source.readInt() != 0;
profileGroupId = source.readInt();
+ guestToRemove = source.readInt() != 0;
}
}
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index 29e42ea..ce83028 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -483,7 +483,9 @@
* and in the buffers sent to each output Surface. These buffer
* timestamps are accessible through, for example,
* {@link android.media.Image#getTimestamp() Image.getTimestamp()} or
- * {@link android.graphics.SurfaceTexture#getTimestamp()}.</p>
+ * {@link android.graphics.SurfaceTexture#getTimestamp()}.
+ * The frame number included is equal to the frame number that will be included in
+ * {@link CaptureResult#getFrameNumber}.</p>
*
* <p>For the simplest way to play a shutter sound camera shutter or a
* video recording start/stop sound, see the
@@ -494,10 +496,21 @@
* @param session the session returned by {@link CameraDevice#createCaptureSession}
* @param request the request for the capture that just begun
* @param timestamp the timestamp at start of capture, in nanoseconds.
+ * @param frameNumber the frame number for this capture
*
* @see android.media.MediaActionSound
*/
public void onCaptureStarted(CameraCaptureSession session,
+ CaptureRequest request, long timestamp, long frameNumber) {
+ // Temporary trampoline for API change transition
+ onCaptureStarted(session, request, timestamp);
+ }
+
+ /**
+ * Temporary for API change transition
+ * @hide
+ */
+ public void onCaptureStarted(CameraCaptureSession session,
CaptureRequest request, long timestamp) {
// default empty implementation
}
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 6d0d505..93eb3de 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -731,6 +731,8 @@
/**
* <p>List of areas to use for
* metering.</p>
+ * <p>Optional. Not available if {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AE android.control.maxRegionsAe} is 0.
+ * Otherwise will always be present.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
@@ -746,7 +748,9 @@
* outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
* the camera device will ignore the sections outside the region and output the
* used sections in the result metadata.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
+ * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
@@ -820,6 +824,8 @@
/**
* <p>List of areas to use for focus
* estimation.</p>
+ * <p>Optional. Not available if {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AF android.control.maxRegionsAf} is 0.
+ * Otherwise will always be present.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
@@ -835,7 +841,9 @@
* outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
* the camera device will ignore the sections outside the region and output the
* used sections in the result metadata.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
+ * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AF
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
@@ -921,6 +929,8 @@
/**
* <p>List of areas to use for illuminant
* estimation.</p>
+ * <p>Optional. Not available if {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AWB android.control.maxRegionsAwb} is 0.
+ * Otherwise will always be present.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
@@ -936,7 +946,9 @@
* outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
* the camera device will ignore the sections outside the region and output the
* used sections in the result metadata.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
+ * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AWB
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 754d83e..01276a2 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -582,6 +582,8 @@
/**
* <p>List of areas to use for
* metering.</p>
+ * <p>Optional. Not available if {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AE android.control.maxRegionsAe} is 0.
+ * Otherwise will always be present.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
@@ -597,7 +599,9 @@
* outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
* the camera device will ignore the sections outside the region and output the
* used sections in the result metadata.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
+ * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
@@ -870,6 +874,8 @@
/**
* <p>List of areas to use for focus
* estimation.</p>
+ * <p>Optional. Not available if {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AF android.control.maxRegionsAf} is 0.
+ * Otherwise will always be present.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
@@ -885,7 +891,9 @@
* outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
* the camera device will ignore the sections outside the region and output the
* used sections in the result metadata.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
+ * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AF
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
@@ -1369,6 +1377,8 @@
/**
* <p>List of areas to use for illuminant
* estimation.</p>
+ * <p>Optional. Not available if {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AWB android.control.maxRegionsAwb} is 0.
+ * Otherwise will always be present.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
@@ -1384,7 +1394,9 @@
* outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
* the camera device will ignore the sections outside the region and output the
* used sections in the result metadata.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
+ * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AWB
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
diff --git a/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java b/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java
index 02c3d87..c66a3a4 100644
--- a/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java
+++ b/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java
@@ -48,7 +48,8 @@
/**
* Invoke a method by its name.
*
- * <p>If more than one method exists in {@code targetClass}, the first method will be used.</p>
+ * <p>If more than one method exists in {@code targetClass}, the first method with the right
+ * number of arguments will be used, and later calls will all use that method.</p>
*
* @param methodName
* The name of the method, which will be matched 1:1 to the destination method
@@ -68,8 +69,9 @@
Method targetMethod = mMethods.get(methodName);
if (targetMethod == null) {
for (Method method : mTargetClass.getMethods()) {
- // TODO future: match by # of params and types of params if possible
- if (method.getName().equals(methodName)) {
+ // TODO future: match types of params if possible
+ if (method.getName().equals(methodName) &&
+ (params.length == method.getParameterTypes().length) ) {
targetMethod = method;
mMethods.put(methodName, targetMethod);
break;
diff --git a/core/java/android/hardware/camera2/impl/CallbackProxies.java b/core/java/android/hardware/camera2/impl/CallbackProxies.java
index e5ddb7a..f0217ac 100644
--- a/core/java/android/hardware/camera2/impl/CallbackProxies.java
+++ b/core/java/android/hardware/camera2/impl/CallbackProxies.java
@@ -98,8 +98,8 @@
@Override
public void onCaptureStarted(CameraDevice camera,
- CaptureRequest request, long timestamp) {
- mProxy.invoke("onCaptureStarted", camera, request, timestamp);
+ CaptureRequest request, long timestamp, long frameNumber) {
+ mProxy.invoke("onCaptureStarted", camera, request, timestamp, frameNumber);
}
@Override
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index 843f117..0057f61 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -143,7 +143,6 @@
}
checkNotClosed();
- checkLegalToCapture();
handler = checkHandler(handler, callback);
@@ -166,7 +165,6 @@
}
checkNotClosed();
- checkLegalToCapture();
handler = checkHandler(handler, callback);
@@ -188,7 +186,6 @@
}
checkNotClosed();
- checkLegalToCapture();
handler = checkHandler(handler, callback);
@@ -211,7 +208,6 @@
}
checkNotClosed();
- checkLegalToCapture();
handler = checkHandler(handler, callback);
@@ -542,13 +538,6 @@
}
}
- private void checkLegalToCapture() {
- if (mAborting) {
- throw new IllegalStateException(
- "Session is aborting captures; new captures are not permitted");
- }
- }
-
private void checkNotClosed() {
if (mClosed) {
throw new IllegalStateException(
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index d454092..f011d60 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -803,7 +803,7 @@
* @see android.media.MediaActionSound
*/
public void onCaptureStarted(CameraDevice camera,
- CaptureRequest request, long timestamp) {
+ CaptureRequest request, long timestamp, long frameNumber) {
// default empty implementation
}
@@ -1237,8 +1237,10 @@
@Override
public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
int requestId = resultExtras.getRequestId();
+ final long frameNumber = resultExtras.getFrameNumber();
+
if (DEBUG) {
- Log.d(TAG, "Capture started for id " + requestId);
+ Log.d(TAG, "Capture started for id " + requestId + " frame number " + frameNumber);
}
final CaptureCallbackHolder holder;
@@ -1263,7 +1265,7 @@
holder.getCallback().onCaptureStarted(
CameraDeviceImpl.this,
holder.getRequest(resultExtras.getSubsequenceId()),
- timestamp);
+ timestamp, frameNumber);
}
}
});
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index a8d1018..c36b63a 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -165,6 +165,12 @@
private static void mapCharacteristicsFromParameters(CameraMetadataNative m,
Camera.Parameters p) {
+
+ /*
+ * colorCorrection.*
+ */
+ m.set(COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
+ new int[] { COLOR_CORRECTION_ABERRATION_MODE_FAST });
/*
* control.ae*
*/
@@ -196,6 +202,12 @@
mapJpeg(m, p);
/*
+ * noiseReduction.*
+ */
+ m.set(NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
+ new int[] { NOISE_REDUCTION_MODE_FAST });
+
+ /*
* scaler.*
*/
mapScaler(m, p);
@@ -626,6 +638,7 @@
// Note: We only list public keys. Native HALs should list ALL keys regardless of visibility.
Key<?> availableKeys[] = new Key<?>[] {
+ CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES ,
CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES ,
CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES ,
CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES ,
@@ -642,6 +655,7 @@
CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES ,
CameraCharacteristics.LENS_FACING ,
CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS ,
+ CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES ,
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES ,
CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_STREAMS ,
CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT ,
@@ -653,6 +667,7 @@
CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE ,
CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE ,
CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE ,
+ CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE ,
CameraCharacteristics.SENSOR_ORIENTATION ,
CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES ,
CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT ,
@@ -675,15 +690,14 @@
* request.availableRequestKeys
*/
{
- CaptureRequest.Key<?> availableKeys[] = new CaptureRequest.Key<?>[] {
+ CaptureRequest.Key<?> defaultAvailableKeys[] = new CaptureRequest.Key<?>[] {
+ CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE,
CaptureRequest.CONTROL_AE_ANTIBANDING_MODE,
CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION,
CaptureRequest.CONTROL_AE_LOCK,
CaptureRequest.CONTROL_AE_MODE,
- CaptureRequest.CONTROL_AE_REGIONS,
CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,
CaptureRequest.CONTROL_AF_MODE,
- CaptureRequest.CONTROL_AF_REGIONS,
CaptureRequest.CONTROL_AF_TRIGGER,
CaptureRequest.CONTROL_AWB_LOCK,
CaptureRequest.CONTROL_AWB_MODE,
@@ -701,24 +715,37 @@
CaptureRequest.JPEG_THUMBNAIL_QUALITY,
CaptureRequest.JPEG_THUMBNAIL_SIZE,
CaptureRequest.LENS_FOCAL_LENGTH,
+ CaptureRequest.NOISE_REDUCTION_MODE,
CaptureRequest.SCALER_CROP_REGION,
CaptureRequest.STATISTICS_FACE_DETECT_MODE,
};
- m.set(REQUEST_AVAILABLE_REQUEST_KEYS, getTagsForKeys(availableKeys));
+ ArrayList<CaptureRequest.Key<?>> availableKeys =
+ new ArrayList<CaptureRequest.Key<?>>(Arrays.asList(defaultAvailableKeys));
+
+ if (p.getMaxNumMeteringAreas() > 0) {
+ availableKeys.add(CaptureRequest.CONTROL_AE_REGIONS);
+ }
+ if (p.getMaxNumFocusAreas() > 0) {
+ availableKeys.add(CaptureRequest.CONTROL_AF_REGIONS);
+ }
+
+ CaptureRequest.Key<?> availableRequestKeys[] =
+ new CaptureRequest.Key<?>[availableKeys.size()];
+ availableKeys.toArray(availableRequestKeys);
+ m.set(REQUEST_AVAILABLE_REQUEST_KEYS, getTagsForKeys(availableRequestKeys));
}
/*
* request.availableResultKeys
*/
{
- CaptureResult.Key<?> availableKeys[] = new CaptureResult.Key<?>[] {
+ CaptureResult.Key<?> defaultAvailableKeys[] = new CaptureResult.Key<?>[] {
+ CaptureResult.COLOR_CORRECTION_ABERRATION_MODE ,
CaptureResult.CONTROL_AE_ANTIBANDING_MODE ,
CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION ,
CaptureResult.CONTROL_AE_LOCK ,
CaptureResult.CONTROL_AE_MODE ,
- CaptureResult.CONTROL_AE_REGIONS ,
CaptureResult.CONTROL_AF_MODE ,
- CaptureResult.CONTROL_AF_REGIONS ,
CaptureResult.CONTROL_AF_STATE ,
CaptureResult.CONTROL_AWB_MODE ,
CaptureResult.CONTROL_AWB_LOCK ,
@@ -731,13 +758,27 @@
CaptureResult.JPEG_QUALITY ,
CaptureResult.JPEG_THUMBNAIL_QUALITY ,
CaptureResult.LENS_FOCAL_LENGTH ,
+ CaptureResult.NOISE_REDUCTION_MODE ,
CaptureResult.REQUEST_PIPELINE_DEPTH ,
CaptureResult.SCALER_CROP_REGION ,
CaptureResult.SENSOR_TIMESTAMP ,
CaptureResult.STATISTICS_FACE_DETECT_MODE ,
// CaptureResult.STATISTICS_FACES ,
};
- m.set(REQUEST_AVAILABLE_RESULT_KEYS, getTagsForKeys(availableKeys));
+ List<CaptureResult.Key<?>> availableKeys =
+ new ArrayList<CaptureResult.Key<?>>(Arrays.asList(defaultAvailableKeys));
+
+ if (p.getMaxNumMeteringAreas() > 0) {
+ availableKeys.add(CaptureResult.CONTROL_AE_REGIONS);
+ }
+ if (p.getMaxNumFocusAreas() > 0) {
+ availableKeys.add(CaptureResult.CONTROL_AF_REGIONS);
+ }
+
+ CaptureResult.Key<?> availableResultKeys[] =
+ new CaptureResult.Key<?>[availableKeys.size()];
+ availableKeys.toArray(availableResultKeys);
+ m.set(REQUEST_AVAILABLE_RESULT_KEYS, getTagsForKeys(availableResultKeys));
}
/*
@@ -822,6 +863,13 @@
m.set(SENSOR_INFO_PHYSICAL_SIZE, new SizeF(width, height)); // in mm
}
+
+ /*
+ * sensor.info.timestampSource
+ */
+ {
+ m.set(SENSOR_INFO_TIMESTAMP_SOURCE, SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN);
+ }
}
private static void mapStatistics(CameraMetadataNative m, Parameters p) {
diff --git a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
index 42ee4fa..42fe897 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
@@ -80,6 +80,20 @@
}
}
+ /*
+ * colorCorrection.*
+ */
+ // colorCorrection.aberrationMode
+ {
+ int aberrationMode = ParamsUtils.getOrDefault(request,
+ COLOR_CORRECTION_ABERRATION_MODE,
+ /*defaultValue*/COLOR_CORRECTION_ABERRATION_MODE_FAST);
+
+ if (aberrationMode != COLOR_CORRECTION_ABERRATION_MODE_FAST) {
+ Log.w(TAG, "convertRequestToMetadata - Ignoring unsupported " +
+ "colorCorrection.aberrationMode = " + aberrationMode);
+ }
+ }
/*
* control.ae*
@@ -419,6 +433,21 @@
}
}
}
+
+ /*
+ * noiseReduction.*
+ */
+ // noiseReduction.mode
+ {
+ int mode = ParamsUtils.getOrDefault(request,
+ NOISE_REDUCTION_MODE,
+ /*defaultValue*/NOISE_REDUCTION_MODE_FAST);
+
+ if (mode != NOISE_REDUCTION_MODE_FAST) {
+ Log.w(TAG, "convertRequestToMetadata - Ignoring unsupported " +
+ "noiseReduction.mode = " + mode);
+ }
+ }
}
private static boolean checkForCompleteGpsData(Location location) {
diff --git a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
index 090a822..bad1d28a 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
@@ -28,14 +28,12 @@
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.utils.ListUtils;
import android.hardware.camera2.utils.ParamsUtils;
-import android.location.Location;
import android.util.Log;
import android.util.Size;
import java.util.ArrayList;
import java.util.List;
-import static com.android.internal.util.Preconditions.*;
import static android.hardware.camera2.CaptureResult.*;
/**
@@ -73,7 +71,7 @@
result = new CameraMetadataNative(mCachedResult);
cached = true;
} else {
- result = convertResultMetadata(legacyRequest, timestamp);
+ result = convertResultMetadata(legacyRequest);
cached = false;
// Always cache a *copy* of the metadata result,
@@ -106,12 +104,9 @@
* Generate capture result metadata from the legacy camera request.
*
* @param legacyRequest a non-{@code null} legacy request containing the latest parameters
- * @param timestamp the timestamp to use for this result in nanoseconds.
- *
* @return a {@link CameraMetadataNative} object containing result metadata.
*/
- private static CameraMetadataNative convertResultMetadata(LegacyRequest legacyRequest,
- long timestamp) {
+ private static CameraMetadataNative convertResultMetadata(LegacyRequest legacyRequest) {
CameraCharacteristics characteristics = legacyRequest.characteristics;
CaptureRequest request = legacyRequest.captureRequest;
Size previewSize = legacyRequest.previewSize;
@@ -125,6 +120,15 @@
request.get(CaptureRequest.SCALER_CROP_REGION), previewSize, params);
/*
+ * colorCorrection
+ */
+ // colorCorrection.aberrationMode
+ {
+ // Always hardcoded to FAST
+ result.set(COLOR_CORRECTION_ABERRATION_MODE, COLOR_CORRECTION_ABERRATION_MODE_FAST);
+ }
+
+ /*
* control
*/
@@ -274,7 +278,12 @@
Log.w(TAG, "Null thumbnail size received from parameters.");
}
- // TODO: Remaining result metadata tags conversions.
+ /*
+ * noiseReduction.*
+ */
+ // noiseReduction.mode
+ result.set(NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_FAST);
+
return result;
}
@@ -322,7 +331,7 @@
}
// control.aeRegions
- {
+ if (p.getMaxNumMeteringAreas() > 0) {
if (VERBOSE) {
String meteringAreas = p.get("metering-areas");
Log.v(TAG, "mapAe - parameter dump; metering-areas: " + meteringAreas);
@@ -342,7 +351,7 @@
m.set(CaptureResult.CONTROL_AF_MODE, convertLegacyAfMode(p.getFocusMode()));
// control.afRegions
- {
+ if (p.getMaxNumFocusAreas() > 0) {
if (VERBOSE) {
String focusAreas = p.get("focus-areas");
Log.v(TAG, "mapAe - parameter dump; focus-areas: " + focusAreas);
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index e6ff17b..e6da670 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -374,6 +374,9 @@
}
mIntermediateBufferSize = bestPreviewDimen;
+ mParams.setPreviewSize(mIntermediateBufferSize.getWidth(),
+ mIntermediateBufferSize.getHeight());
+
if (DEBUG) {
Log.d(TAG, "Intermediate buffer selected with dimens: " +
bestPreviewDimen.toString());
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 70b402d..7c69a7d 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -48,6 +48,8 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.HashMap;
+import libcore.net.event.NetworkEventDispatcher;
+
/**
* Class that answers queries about the state of network connectivity. It also
* notifies applications when network connectivity changes. Get an instance
@@ -2467,7 +2469,20 @@
* @return {@code true} on success, {@code false} if the {@link Network} is no longer valid.
*/
public static boolean setProcessDefaultNetwork(Network network) {
- return NetworkUtils.bindProcessToNetwork(network == null ? NETID_UNSET : network.netId);
+ int netId = (network == null) ? NETID_UNSET : network.netId;
+ if (netId == NetworkUtils.getNetworkBoundToProcess()) {
+ return true;
+ }
+ if (NetworkUtils.bindProcessToNetwork(netId)) {
+ // Must flush DNS cache as new network may have different DNS resolutions.
+ InetAddress.clearDnsCache();
+ // Must flush socket pool as idle sockets will be bound to previous network and may
+ // cause subsequent fetches to be performed on old network.
+ NetworkEventDispatcher.getInstance().onNetworkConfigurationChanged();
+ return true;
+ } else {
+ return false;
+ }
}
/**
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index e686be7..58f0fc0 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -37,6 +37,8 @@
import com.android.okhttp.ConnectionPool;
import com.android.okhttp.HostResolver;
+import com.android.okhttp.HttpHandler;
+import com.android.okhttp.HttpsHandler;
import com.android.okhttp.OkHttpClient;
/**
@@ -58,7 +60,10 @@
// Objects used to perform per-network operations such as getSocketFactory
// and openConnection, and a lock to protect access to them.
private volatile NetworkBoundSocketFactory mNetworkBoundSocketFactory = null;
- private volatile OkHttpClient mOkHttpClient = null;
+ // mLock should be used to control write access to mConnectionPool and mHostResolver.
+ // maybeInitHttpClient() must be called prior to reading either variable.
+ private volatile ConnectionPool mConnectionPool = null;
+ private volatile HostResolver mHostResolver = null;
private Object mLock = new Object();
// Default connection pool values. These are evaluated at startup, just
@@ -195,37 +200,34 @@
return mNetworkBoundSocketFactory;
}
- // TODO: This creates an OkHttpClient with its own connection pool for
+ // TODO: This creates a connection pool and host resolver for
// every Network object, instead of one for every NetId. This is
// suboptimal, because an app could potentially have more than one
// Network object for the same NetId, causing increased memory footprint
// and performance penalties due to lack of connection reuse (connection
// setup time, congestion window growth time, etc.).
//
- // Instead, investigate only having one OkHttpClient for every NetId,
- // perhaps by using a static HashMap of NetIds to OkHttpClient objects. The
- // tricky part is deciding when to remove an OkHttpClient; a WeakHashMap
- // shouldn't be used because whether a Network is referenced doesn't
- // correlate with whether a new Network will be instantiated in the near
- // future with the same NetID. A good solution would involve purging empty
- // (or when all connections are timed out) ConnectionPools.
+ // Instead, investigate only having one connection pool and host resolver
+ // for every NetId, perhaps by using a static HashMap of NetIds to
+ // connection pools and host resolvers. The tricky part is deciding when
+ // to remove a map entry; a WeakHashMap shouldn't be used because whether
+ // a Network is referenced doesn't correlate with whether a new Network
+ // will be instantiated in the near future with the same NetID. A good
+ // solution would involve purging empty (or when all connections are timed
+ // out) ConnectionPools.
private void maybeInitHttpClient() {
- if (mOkHttpClient == null) {
- synchronized (mLock) {
- if (mOkHttpClient == null) {
- HostResolver hostResolver = new HostResolver() {
- @Override
- public InetAddress[] getAllByName(String host) throws UnknownHostException {
- return Network.this.getAllByName(host);
- }
- };
- ConnectionPool pool = new ConnectionPool(httpMaxConnections,
- httpKeepAliveDurationMs);
- mOkHttpClient = new OkHttpClient()
- .setSocketFactory(getSocketFactory())
- .setHostResolver(hostResolver)
- .setConnectionPool(pool);
- }
+ synchronized (mLock) {
+ if (mHostResolver == null) {
+ mHostResolver = new HostResolver() {
+ @Override
+ public InetAddress[] getAllByName(String host) throws UnknownHostException {
+ return Network.this.getAllByName(host);
+ }
+ };
+ }
+ if (mConnectionPool == null) {
+ mConnectionPool = new ConnectionPool(httpMaxConnections,
+ httpKeepAliveDurationMs);
}
}
}
@@ -242,13 +244,23 @@
public URLConnection openConnection(URL url) throws IOException {
maybeInitHttpClient();
String protocol = url.getProtocol();
- URLStreamHandler handler = mOkHttpClient.createURLStreamHandler(protocol);
- if (handler == null) {
+ OkHttpClient client;
+ // TODO: HttpHandler creates OkHttpClients that share the default ResponseCache.
+ // Could this cause unexpected behavior?
+ // TODO: Should the network's proxy be specified?
+ if (protocol.equals("http")) {
+ client = HttpHandler.createHttpOkHttpClient(null /* proxy */);
+ } else if (protocol.equals("https")) {
+ client = HttpsHandler.createHttpsOkHttpClient(null /* proxy */);
+ } else {
// OkHttpClient only supports HTTP and HTTPS and returns a null URLStreamHandler if
// passed another protocol.
throw new MalformedURLException("Invalid URL or unrecognized protocol " + protocol);
}
- return new URL(url, "", handler).openConnection();
+ return client.setSocketFactory(getSocketFactory())
+ .setHostResolver(mHostResolver)
+ .setConnectionPool(mConnectionPool)
+ .open(url);
}
/**
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 8df9916..80e5b91 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -223,6 +223,9 @@
* Called by the bearer code when it has a new score for this network.
*/
public void sendNetworkScore(int score) {
+ if (score < 0) {
+ throw new IllegalArgumentException("Score must be >= 0");
+ }
queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score));
}
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index 050be40..e6f5e32 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -212,6 +212,8 @@
*
* @return {@code true} on success.
* @see Builder#addAddress
+ *
+ * @hide
*/
public boolean addAddress(InetAddress address, int prefixLength) {
check(address, prefixLength);
@@ -240,6 +242,8 @@
* @param prefixLength The prefix length of the address.
*
* @return {@code true} on success.
+ *
+ * @hide
*/
public boolean removeAddress(InetAddress address, int prefixLength) {
check(address, prefixLength);
diff --git a/core/java/android/os/FileBridge.java b/core/java/android/os/FileBridge.java
index 022a106..0acf24b 100644
--- a/core/java/android/os/FileBridge.java
+++ b/core/java/android/os/FileBridge.java
@@ -75,6 +75,13 @@
return mClosed;
}
+ public void forceClose() {
+ IoUtils.closeQuietly(mTarget);
+ IoUtils.closeQuietly(mServer);
+ IoUtils.closeQuietly(mClient);
+ mClosed = true;
+ }
+
public void setTargetFile(FileDescriptor target) {
mTarget = target;
}
@@ -89,7 +96,6 @@
try {
while (IoBridge.read(mServer, temp, 0, MSG_LENGTH) == MSG_LENGTH) {
final int cmd = Memory.peekInt(temp, 0, ByteOrder.BIG_ENDIAN);
-
if (cmd == CMD_WRITE) {
// Shuttle data into local file
int len = Memory.peekInt(temp, 4, ByteOrder.BIG_ENDIAN);
@@ -118,15 +124,10 @@
}
}
- } catch (ErrnoException e) {
- Log.wtf(TAG, "Failed during bridge", e);
- } catch (IOException e) {
+ } catch (ErrnoException | IOException e) {
Log.wtf(TAG, "Failed during bridge", e);
} finally {
- IoUtils.closeQuietly(mTarget);
- IoUtils.closeQuietly(mServer);
- IoUtils.closeQuietly(mClient);
- mClosed = true;
+ forceClose();
}
}
@@ -151,6 +152,7 @@
writeCommandAndBlock(CMD_CLOSE, "close()");
} finally {
IoBridge.closeAndSignalBlockedThreads(mClient);
+ IoUtils.closeQuietly(mClientPfd);
}
}
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 3286627..b5295fb 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -41,6 +41,7 @@
int getUserSerialNumber(int userHandle);
int getUserHandle(int userSerialNumber);
Bundle getUserRestrictions(int userHandle);
+ boolean hasUserRestriction(in String restrictionKey, int userHandle);
void setUserRestrictions(in Bundle restrictions, int userHandle);
void setApplicationRestrictions(in String packageName, in Bundle restrictions,
int userHandle);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index c3ac012..b2ebc31 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -468,6 +468,7 @@
* @param targetSdkVersion The target SDK version for the app.
* @param seInfo null-ok SELinux information for the new process.
* @param abi non-null the ABI this app should be started with.
+ * @param instructionSet null-ok the instruction set to use.
* @param zygoteArgs Additional arguments to supply to the zygote process.
*
* @return An object that describes the result of the attempt to start the process.
@@ -482,11 +483,12 @@
int targetSdkVersion,
String seInfo,
String abi,
+ String instructionSet,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
- abi, zygoteArgs);
+ abi, instructionSet, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
@@ -589,6 +591,7 @@
* @param targetSdkVersion The target SDK version for the app.
* @param seInfo null-ok SELinux information for the new process.
* @param abi the ABI the process should use.
+ * @param instructionSet null-ok the instruction set to use.
* @param extraArgs Additional arguments to supply to the zygote process.
* @return An object that describes the result of the attempt to start the process.
* @throws ZygoteStartFailedEx if process start failed for any reason
@@ -601,6 +604,7 @@
int targetSdkVersion,
String seInfo,
String abi,
+ String instructionSet,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
@@ -660,6 +664,10 @@
argsForZygote.add("--seinfo=" + seInfo);
}
+ if (instructionSet != null) {
+ argsForZygote.add("--instruction-set=" + instructionSet);
+ }
+
argsForZygote.add(processClass);
if (extraArgs != null) {
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index ec77a5e..c76ff11 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -43,190 +43,208 @@
private final Context mContext;
/**
- * Key for user restrictions. Specifies if a user is disallowed from adding and removing
- * accounts.
+ * Specifies if a user is disallowed from adding and removing accounts.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
/**
- * Key for user restrictions. Specifies if a user is disallowed from changing Wi-Fi
+ * Specifies if a user is disallowed from changing Wi-Fi
* access points. The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CONFIG_WIFI = "no_config_wifi";
/**
- * Key for user restrictions. Specifies if a user is disallowed from installing applications.
+ * Specifies if a user is disallowed from installing applications.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_INSTALL_APPS = "no_install_apps";
/**
- * Key for user restrictions. Specifies if a user is disallowed from uninstalling applications.
+ * Specifies if a user is disallowed from uninstalling applications.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
/**
- * Key for user restrictions. Specifies if a user is disallowed from toggling location sharing.
+ * Specifies if a user is disallowed from toggling location sharing.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_SHARE_LOCATION = "no_share_location";
/**
- * Key for user restrictions. Specifies if a user is disallowed from enabling the
+ * Specifies if a user is disallowed from enabling the
* "Unknown Sources" setting, that allows installation of apps from unknown sources.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
/**
- * Key for user restrictions. Specifies if a user is disallowed from configuring bluetooth.
+ * Specifies if a user is disallowed from configuring bluetooth.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
/**
- * Key for user restrictions. Specifies if a user is disallowed from transferring files over
+ * Specifies if a user is disallowed from transferring files over
* USB. This can only be set by device owners. The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
/**
- * Key for user restrictions. Specifies if a user is disallowed from configuring user
+ * Specifies if a user is disallowed from configuring user
* credentials. The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
/**
- * Key for user restrictions. Specifies if a user is disallowed from removing itself and other
+ * Specifies if a user is disallowed from removing itself and other
* users. The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_REMOVE_USER = "no_remove_user";
/**
- * Key for user restrictions. Specifies if a user is disallowed from enabling or
+ * Specifies if a user is disallowed from enabling or
* accessing debugging features. The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_DEBUGGING_FEATURES = "no_debugging_features";
/**
- * Key for user restrictions. Specifies if a user is disallowed from configuring VPN.
+ * Specifies if a user is disallowed from configuring VPN.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CONFIG_VPN = "no_config_vpn";
/**
- * Key for user restrictions. Specifies if a user is disallowed from configuring Tethering
+ * Specifies if a user is disallowed from configuring Tethering
* & portable hotspots. This can only be set by device owners. The default value is
* <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CONFIG_TETHERING = "no_config_tethering";
/**
- * Key for user restrictions. Specifies if a user is disallowed from factory resetting
+ * Specifies if a user is disallowed from factory resetting
* from Settings. This can only be set by device owners. The default value is
* <code>false</code>.
- * <p>
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_FACTORY_RESET = "no_factory_reset";
/**
- * Key for user restrictions. Specifies if a user is disallowed from adding new users and
+ * Specifies if a user is disallowed from adding new users and
* profiles. This can only be set by device owners. The default value is <code>false</code>.
- * <p>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_ADD_USER = "no_add_user";
/**
- * Key for user restrictions. Specifies if a user is disallowed from disabling application
+ * Specifies if a user is disallowed from disabling application
* verification. The default value is <code>false</code>.
- * <p>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String ENSURE_VERIFY_APPS = "ensure_verify_apps";
/**
- * Key for user restrictions. Specifies if a user is disallowed from configuring cell
+ * Specifies if a user is disallowed from configuring cell
* broadcasts. This can only be set by device owners. The default value is <code>false</code>.
- * <p>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
/**
- * Key for user restrictions. Specifies if a user is disallowed from configuring mobile
+ * Specifies if a user is disallowed from configuring mobile
* networks. This can only be set by device owners. The default value is <code>false</code>.
- * <p>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CONFIG_MOBILE_NETWORKS = "no_config_mobile_networks";
/**
- * Key for user restrictions. Specifies if a user is disallowed from modifying
+ * Specifies if a user is disallowed from modifying
* applications in Settings or launchers. The following actions will not be allowed when this
* restriction is enabled:
* <li>uninstalling apps</li>
@@ -237,69 +255,75 @@
* <li>clearing app defaults</li>
* <p>
* The default value is <code>false</code>.
- * <p>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_APPS_CONTROL = "no_control_apps";
/**
- * Key for user restrictions. Specifies if a user is disallowed from mounting
+ * Specifies if a user is disallowed from mounting
* physical external media. This can only be set by device owners. The default value is
* <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
/**
- * Key for user restrictions. Specifies if a user is disallowed from adjusting microphone
+ * Specifies if a user is disallowed from adjusting microphone
* volume. If set, the microphone will be muted. This can only be set by device owners.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_UNMUTE_MICROPHONE = "no_unmute_microphone";
/**
- * Key for user restrictions. Specifies if a user is disallowed from adjusting the master
+ * Specifies if a user is disallowed from adjusting the master
* volume. If set, the master volume will be muted. This can only be set by device owners.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
/**
- * Key for user restrictions. Specifies that the user is not allowed to make outgoing
+ * Specifies that the user is not allowed to make outgoing
* phone calls. Emergency calls are still permitted.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
/**
- * Key for user restrictions. Specifies that the user is not allowed to send or receive
+ * Specifies that the user is not allowed to send or receive
* SMS messages. This can only be set by device owners. The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_SMS = "no_sms";
/**
- * Key for user restrictions. Specifies that windows besides app windows should not be
+ * Specifies that windows besides app windows should not be
* created. This will block the creation of the following types of windows.
* <li>{@link LayoutParams#TYPE_TOAST}</li>
* <li>{@link LayoutParams#TYPE_PHONE}</li>
@@ -309,25 +333,38 @@
* <li>{@link LayoutParams#TYPE_SYSTEM_OVERLAY}</li>
*
* <p>This can only be set by device owners. The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CREATE_WINDOWS = "no_create_windows";
/**
- * Key for user restrictions. Specifies if what is copied in the clipboard of this profile can
+ * Specifies if what is copied in the clipboard of this profile can
* be pasted in related profiles. Does not restrict if the clipboard of related profiles can be
* pasted in this profile.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CROSS_PROFILE_COPY_PASTE = "no_cross_profile_copy_paste";
+ /**
+ * Specifies if the user is not allowed to use NFC to beam out data from apps.
+ * The default value is <code>false</code>.
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
+ * @see #setUserRestrictions(Bundle)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
+
/** @hide */
public static final int PIN_VERIFICATION_FAILED_INCORRECT = -3;
/** @hide */
@@ -593,7 +630,13 @@
* @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
*/
public boolean hasUserRestriction(String restrictionKey, UserHandle userHandle) {
- return getUserRestrictions(userHandle).getBoolean(restrictionKey, false);
+ try {
+ return mService.hasUserRestriction(restrictionKey,
+ userHandle.getIdentifier());
+ } catch (RemoteException re) {
+ Log.w(TAG, "Could not check user restrictions", re);
+ return false;
+ }
}
/**
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 5fa1cc9..a5e86d8 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -167,8 +167,6 @@
*/
public static final String FEATURES = "features";
- /** Call had no associated features (e.g. voice-only). */
- public static final int FEATURES_NONE = 0x0;
/** Call had video. */
public static final int FEATURES_VIDEO = 0x1;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f4c2dc8..440b1ec 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3150,6 +3150,11 @@
/** @hide */
public static boolean putStringForUser(ContentResolver resolver, String name, String value,
int userHandle) {
+ if (LOCATION_MODE.equals(name)) {
+ // HACK ALERT: temporary hack to work around b/10491283.
+ // TODO: once b/10491283 fixed, remove this hack
+ return setLocationModeForUser(resolver, Integer.parseInt(value), userHandle);
+ }
if (MOVED_TO_GLOBAL.contains(name)) {
Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
+ " to android.provider.Settings.Global");
@@ -3265,11 +3270,6 @@
/** @hide */
public static boolean putIntForUser(ContentResolver cr, String name, int value,
int userHandle) {
- if (LOCATION_MODE.equals(name)) {
- // HACK ALERT: temporary hack to work around b/10491283.
- // TODO: once b/10491283 fixed, remove this hack
- return setLocationModeForUser(cr, value, userHandle);
- }
return putStringForUser(cr, name, Integer.toString(value), userHandle);
}
@@ -3739,6 +3739,13 @@
"show_note_about_notification_hiding";
/**
+ * Set to 1 by the system after trust agents have been initialized.
+ * @hide
+ */
+ public static final String TRUST_AGENTS_INITIALIZED =
+ "trust_agents_initialized";
+
+ /**
* The Logging ID (a unique 64-bit value) as a hex string.
* Used as a pseudonymous identifier for logging.
* @deprecated This identifier is poorly initialized and has
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index aa724f0..3a91d1a 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -16,6 +16,7 @@
package android.service.notification;
+import android.annotation.SystemApi;
import android.content.Context;
import android.net.Uri;
import android.os.Parcel;
@@ -28,6 +29,7 @@
*
* @hide
*/
+@SystemApi
public class Condition implements Parcelable {
public static final String SCHEME = "condition";
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
index 326412f..03ee726 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -17,6 +17,7 @@
package android.service.notification;
import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
import android.app.INotificationManager;
import android.app.Service;
import android.content.Context;
@@ -44,6 +45,7 @@
*
* @hide
*/
+@SystemApi
public abstract class ConditionProviderService extends Service {
private final String TAG = ConditionProviderService.class.getSimpleName()
+ "[" + getClass().getSimpleName() + "]";
diff --git a/core/java/android/service/notification/IStatusBarNotificationHolder.aidl b/core/java/android/service/notification/IStatusBarNotificationHolder.aidl
index fd6b59e..c25cdb2 100644
--- a/core/java/android/service/notification/IStatusBarNotificationHolder.aidl
+++ b/core/java/android/service/notification/IStatusBarNotificationHolder.aidl
@@ -20,5 +20,6 @@
/** @hide */
interface IStatusBarNotificationHolder {
+ /** Fetch the held StatusBarNotification. This method should only be called once per Holder */
StatusBarNotification get();
}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index d744070..b22fd9c 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -756,15 +756,6 @@
return mVisibilityOverride;
}
- /**
- * Returns whether the notification meets the user's interruption
- * filter.
- *
- * @removed
- */
- public boolean meetsInterruptionFilter() {
- return mMatchesInterruptionFilter;
- }
/**
* Returns whether the notification matches the user's interruption
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 872f911..9cbedab 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -17,6 +17,7 @@
package android.service.notification;
import android.content.ComponentName;
+import android.content.res.Resources;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -55,6 +56,11 @@
public static final int[] WEEKNIGHT_DAYS = { Calendar.SUNDAY, Calendar.MONDAY, Calendar.TUESDAY,
Calendar.WEDNESDAY, Calendar.THURSDAY };
+ public static final int[] MINUTE_BUCKETS = new int[] { 15, 30, 45, 60, 120, 180, 240, 480 };
+ private static final int SECONDS_MS = 1000;
+ private static final int MINUTES_MS = 60 * SECONDS_MS;
+ private static final int ZERO_VALUE_MS = 20 * SECONDS_MS;
+
private static final int XML_VERSION = 1;
private static final String ZEN_TAG = "zen";
private static final String ZEN_ATT_VERSION = "version";
@@ -445,6 +451,23 @@
return downtime;
}
+ public static Condition toTimeCondition(int minutesFromNow) {
+ final long now = System.currentTimeMillis();
+ final long millis = minutesFromNow == 0 ? ZERO_VALUE_MS : minutesFromNow * MINUTES_MS;
+ return toTimeCondition(now + millis, minutesFromNow);
+ }
+
+ public static Condition toTimeCondition(long time, int minutes) {
+ final int num = minutes < 60 ? minutes : Math.round(minutes / 60f);
+ final int resId = minutes < 60
+ ? com.android.internal.R.plurals.zen_mode_duration_minutes
+ : com.android.internal.R.plurals.zen_mode_duration_hours;
+ final String caption = Resources.getSystem().getQuantityString(resId, num, num);
+ final Uri id = toCountdownConditionId(time);
+ return new Condition(id, caption, "", "", 0, Condition.STATE_TRUE,
+ Condition.FLAG_RELEVANT_NOW);
+ }
+
// For built-in conditions
private static final String SYSTEM_AUTHORITY = "android";
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 4de5f41..8aa2689 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -468,19 +468,6 @@
}
/**
- * FIXME: Remove once the prebuilts are updated.
- *
- * @hide
- */
- @Deprecated
- public Intent createIntentToEnroll() {
- if (DBG) Slog.d(TAG, "createIntentToEnroll");
- synchronized (mLock) {
- return getManageIntentLocked(MANAGE_ACTION_ENROLL);
- }
- }
-
- /**
* Creates an intent to start the un-enrollment for the associated keyphrase.
* This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
* Starting re-enrollment is only valid if the keyphrase is already enrolled,
@@ -502,19 +489,6 @@
}
/**
- * FIXME: Remove once the prebuilts are updated.
- *
- * @hide
- */
- @Deprecated
- public Intent createIntentToUnEnroll() {
- if (DBG) Slog.d(TAG, "createIntentToUnEnroll");
- synchronized (mLock) {
- return getManageIntentLocked(MANAGE_ACTION_UN_ENROLL);
- }
- }
-
- /**
* Creates an intent to start the re-enrollment for the associated keyphrase.
* This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
* Starting re-enrollment is only valid if the keyphrase is already enrolled,
@@ -535,19 +509,6 @@
}
}
- /**
- * FIXME: Remove once the prebuilts are updated.
- *
- * @hide
- */
- @Deprecated
- public Intent createIntentToReEnroll() {
- if (DBG) Slog.d(TAG, "createIntentToReEnroll");
- synchronized (mLock) {
- return getManageIntentLocked(MANAGE_ACTION_RE_ENROLL);
- }
- }
-
private Intent getManageIntentLocked(int action) {
if (mAvailability == STATE_INVALID) {
throw new IllegalStateException("getManageIntent called on an invalid detector");
diff --git a/core/java/android/service/wallpaper/IWallpaperEngine.aidl b/core/java/android/service/wallpaper/IWallpaperEngine.aidl
index faccde2..de527e9 100644
--- a/core/java/android/service/wallpaper/IWallpaperEngine.aidl
+++ b/core/java/android/service/wallpaper/IWallpaperEngine.aidl
@@ -16,6 +16,7 @@
package android.service.wallpaper;
+import android.graphics.Rect;
import android.view.MotionEvent;
import android.os.Bundle;
@@ -24,6 +25,7 @@
*/
oneway interface IWallpaperEngine {
void setDesiredSize(int width, int height);
+ void setDisplayPadding(in Rect padding);
void setVisibility(boolean visible);
void dispatchPointer(in MotionEvent event);
void dispatchWallpaperCommand(String action, int x, int y,
diff --git a/core/java/android/service/wallpaper/IWallpaperService.aidl b/core/java/android/service/wallpaper/IWallpaperService.aidl
index bc7a1d7..5fd0157 100644
--- a/core/java/android/service/wallpaper/IWallpaperService.aidl
+++ b/core/java/android/service/wallpaper/IWallpaperService.aidl
@@ -16,6 +16,7 @@
package android.service.wallpaper;
+import android.graphics.Rect;
import android.service.wallpaper.IWallpaperConnection;
/**
@@ -24,5 +25,5 @@
oneway interface IWallpaperService {
void attach(IWallpaperConnection connection,
IBinder windowToken, int windowType, boolean isPreview,
- int reqWidth, int reqHeight);
+ int reqWidth, int reqHeight, in Rect padding);
}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index f3c26c8..26e9a30 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -16,6 +16,14 @@
package android.service.wallpaper;
+import android.content.res.TypedArray;
+import android.os.Build;
+import android.os.SystemProperties;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.ViewRootImpl;
+import android.view.WindowInsets;
+import com.android.internal.R;
import com.android.internal.os.HandlerCaller;
import com.android.internal.view.BaseIWindow;
import com.android.internal.view.BaseSurfaceHolder;
@@ -56,6 +64,8 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
+
/**
* A wallpaper service is responsible for showing a live wallpaper behind
* applications that would like to sit on top of it. This service object
@@ -90,7 +100,8 @@
private static final int DO_ATTACH = 10;
private static final int DO_DETACH = 20;
private static final int DO_SET_DESIRED_SIZE = 30;
-
+ private static final int DO_SET_DISPLAY_PADDING = 40;
+
private static final int MSG_UPDATE_SURFACE = 10000;
private static final int MSG_VISIBILITY_CHANGED = 10010;
private static final int MSG_WALLPAPER_OFFSETS = 10020;
@@ -150,13 +161,23 @@
WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
int mCurWindowFlags = mWindowFlags;
int mCurWindowPrivateFlags = mWindowPrivateFlags;
+ TypedValue mOutsetBottom;
final Rect mVisibleInsets = new Rect();
final Rect mWinFrame = new Rect();
final Rect mOverscanInsets = new Rect();
final Rect mContentInsets = new Rect();
final Rect mStableInsets = new Rect();
+ final Rect mDispatchedOverscanInsets = new Rect();
+ final Rect mDispatchedContentInsets = new Rect();
+ final Rect mDispatchedStableInsets = new Rect();
+ final Rect mFinalSystemInsets = new Rect();
+ final Rect mFinalStableInsets = new Rect();
final Configuration mConfiguration = new Configuration();
-
+
+ private boolean mIsEmulator;
+ private boolean mIsCircularEmulator;
+ private boolean mWindowIsRound;
+
final WindowManager.LayoutParams mLayout
= new WindowManager.LayoutParams();
IWindowSession mSession;
@@ -406,7 +427,7 @@
*/
public void onCreate(SurfaceHolder surfaceHolder) {
}
-
+
/**
* Called right before the engine is going away. After this the
* surface will be destroyed and this Engine object is no longer
@@ -414,7 +435,7 @@
*/
public void onDestroy() {
}
-
+
/**
* Called to inform you of the wallpaper becoming visible or
* hidden. <em>It is very important that a wallpaper only use
@@ -422,7 +443,17 @@
*/
public void onVisibilityChanged(boolean visible) {
}
-
+
+ /**
+ * Called with the current insets that are in effect for the wallpaper.
+ * This gives you the part of the overall wallpaper surface that will
+ * generally be visible to the user (ignoring position offsets applied to it).
+ *
+ * @param insets Insets to apply.
+ */
+ public void onApplyWindowInsets(WindowInsets insets) {
+ }
+
/**
* Called as the user performs touch-screen interaction with the
* window that is currently showing this wallpaper. Note that the
@@ -432,7 +463,7 @@
*/
public void onTouchEvent(MotionEvent event) {
}
-
+
/**
* Called to inform you of the wallpaper's offsets changing
* within its contain, corresponding to the container's
@@ -443,7 +474,7 @@
float xOffsetStep, float yOffsetStep,
int xPixelOffset, int yPixelOffset) {
}
-
+
/**
* Process a command that was sent to the wallpaper with
* {@link WallpaperManager#sendWallpaperCommand}.
@@ -465,14 +496,14 @@
Bundle extras, boolean resultRequested) {
return null;
}
-
+
/**
* Called when an application has changed the desired virtual size of
* the wallpaper.
*/
public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {
}
-
+
/**
* Convenience for {@link SurfaceHolder.Callback#surfaceChanged
* SurfaceHolder.Callback.surfaceChanged()}.
@@ -561,16 +592,20 @@
if (mDestroyed) {
Log.w(TAG, "Ignoring updateSurface: destroyed");
}
-
+
+ boolean fixedSize = false;
int myWidth = mSurfaceHolder.getRequestedWidth();
if (myWidth <= 0) myWidth = ViewGroup.LayoutParams.MATCH_PARENT;
+ else fixedSize = true;
int myHeight = mSurfaceHolder.getRequestedHeight();
if (myHeight <= 0) myHeight = ViewGroup.LayoutParams.MATCH_PARENT;
-
+ else fixedSize = true;
+
final boolean creating = !mCreated;
final boolean surfaceCreating = !mSurfaceCreated;
final boolean formatChanged = mFormat != mSurfaceHolder.getRequestedFormat();
boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
+ boolean insetsChanged = !mCreated;
final boolean typeChanged = mType != mSurfaceHolder.getRequestedType();
final boolean flagsChanged = mCurWindowFlags != mWindowFlags ||
mCurWindowPrivateFlags != mWindowPrivateFlags;
@@ -607,6 +642,32 @@
mLayout.token = mWindowToken;
if (!mCreated) {
+ // Retrieve watch round and outset info
+ final WindowManager windowService = (WindowManager)getSystemService(
+ Context.WINDOW_SERVICE);
+ TypedArray windowStyle = obtainStyledAttributes(
+ com.android.internal.R.styleable.Window);
+ final Display display = windowService.getDefaultDisplay();
+ final boolean shouldUseBottomOutset =
+ display.getDisplayId() == Display.DEFAULT_DISPLAY;
+ if (shouldUseBottomOutset && windowStyle.hasValue(
+ R.styleable.Window_windowOutsetBottom)) {
+ if (mOutsetBottom == null) mOutsetBottom = new TypedValue();
+ windowStyle.getValue(R.styleable.Window_windowOutsetBottom,
+ mOutsetBottom);
+ } else {
+ mOutsetBottom = null;
+ }
+ mWindowIsRound = getResources().getBoolean(
+ com.android.internal.R.bool.config_windowIsRound);
+ windowStyle.recycle();
+
+ // detect emulator
+ mIsEmulator = Build.HARDWARE.contains("goldfish");
+ mIsCircularEmulator = SystemProperties.getBoolean(
+ ViewRootImpl.PROPERTY_EMULATOR_CIRCULAR, false);
+
+ // Add window
mLayout.type = mIWallpaperEngine.mWindowType;
mLayout.gravity = Gravity.START|Gravity.TOP;
mLayout.setTitle(WallpaperService.this.getClass().getName());
@@ -627,6 +688,11 @@
mSurfaceHolder.mSurfaceLock.lock();
mDrawingAllowed = true;
+ if (!fixedSize) {
+ mLayout.surfaceInsets.set(mIWallpaperEngine.mDisplayPadding);
+ } else {
+ mLayout.surfaceInsets.set(0, 0, 0, 0);
+ }
final int relayoutResult = mSession.relayout(
mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets,
@@ -636,16 +702,39 @@
+ ", frame=" + mWinFrame);
int w = mWinFrame.width();
+ int h = mWinFrame.height();
+
+ if (!fixedSize) {
+ final Rect padding = mIWallpaperEngine.mDisplayPadding;
+ w += padding.left + padding.right;
+ h += padding.top + padding.bottom;
+ mOverscanInsets.left += padding.left;
+ mOverscanInsets.top += padding.top;
+ mOverscanInsets.right += padding.right;
+ mOverscanInsets.bottom += padding.bottom;
+ mContentInsets.left += padding.left;
+ mContentInsets.top += padding.top;
+ mContentInsets.right += padding.right;
+ mContentInsets.bottom += padding.bottom;
+ mStableInsets.left += padding.left;
+ mStableInsets.top += padding.top;
+ mStableInsets.right += padding.right;
+ mStableInsets.bottom += padding.bottom;
+ }
+
if (mCurWidth != w) {
sizeChanged = true;
mCurWidth = w;
}
- int h = mWinFrame.height();
if (mCurHeight != h) {
sizeChanged = true;
mCurHeight = h;
}
+ insetsChanged |= !mDispatchedOverscanInsets.equals(mOverscanInsets);
+ insetsChanged |= !mDispatchedContentInsets.equals(mContentInsets);
+ insetsChanged |= !mDispatchedStableInsets.equals(mStableInsets);
+
mSurfaceHolder.setSurfaceFrameSize(w, h);
mSurfaceHolder.mSurfaceLock.unlock();
@@ -702,6 +791,25 @@
}
}
+ if (insetsChanged) {
+ mDispatchedOverscanInsets.set(mOverscanInsets);
+ mDispatchedContentInsets.set(mContentInsets);
+ mDispatchedStableInsets.set(mStableInsets);
+ final boolean isRound = (mIsEmulator && mIsCircularEmulator)
+ || mWindowIsRound;
+ mFinalSystemInsets.set(mDispatchedOverscanInsets);
+ mFinalStableInsets.set(mDispatchedStableInsets);
+ if (mOutsetBottom != null) {
+ final DisplayMetrics metrics = getResources().getDisplayMetrics();
+ mFinalSystemInsets.bottom =
+ ( (int) mOutsetBottom.getDimension(metrics) )
+ + mIWallpaperEngine.mDisplayPadding.bottom;
+ }
+ WindowInsets insets = new WindowInsets(mFinalSystemInsets,
+ null, mFinalStableInsets, isRound);
+ onApplyWindowInsets(insets);
+ }
+
if (redrawNeeded) {
onSurfaceRedrawNeeded(mSurfaceHolder);
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
@@ -781,7 +889,7 @@
mReportedVisible = false;
updateSurface(false, false, false);
}
-
+
void doDesiredSizeChanged(int desiredWidth, int desiredHeight) {
if (!mDestroyed) {
if (DEBUG) Log.v(TAG, "onDesiredSizeChanged("
@@ -792,14 +900,24 @@
doOffsetsChanged(true);
}
}
-
+
+ void doDisplayPaddingChanged(Rect padding) {
+ if (!mDestroyed) {
+ if (DEBUG) Log.v(TAG, "onDisplayPaddingChanged(" + padding + "): " + this);
+ if (!mIWallpaperEngine.mDisplayPadding.equals(padding)) {
+ mIWallpaperEngine.mDisplayPadding.set(padding);
+ updateSurface(true, false, false);
+ }
+ }
+ }
+
void doVisibilityChanged(boolean visible) {
if (!mDestroyed) {
mVisible = visible;
reportVisibility();
}
}
-
+
void reportVisibility() {
if (!mDestroyed) {
boolean visible = mVisible && mScreenOn;
@@ -956,12 +1074,13 @@
boolean mShownReported;
int mReqWidth;
int mReqHeight;
-
+ final Rect mDisplayPadding = new Rect();
+
Engine mEngine;
-
+
IWallpaperEngineWrapper(WallpaperService context,
IWallpaperConnection conn, IBinder windowToken,
- int windowType, boolean isPreview, int reqWidth, int reqHeight) {
+ int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding) {
mCaller = new HandlerCaller(context, context.getMainLooper(), this, true);
mConnection = conn;
mWindowToken = windowToken;
@@ -969,16 +1088,22 @@
mIsPreview = isPreview;
mReqWidth = reqWidth;
mReqHeight = reqHeight;
+ mDisplayPadding.set(padding);
Message msg = mCaller.obtainMessage(DO_ATTACH);
mCaller.sendMessage(msg);
}
-
+
public void setDesiredSize(int width, int height) {
Message msg = mCaller.obtainMessageII(DO_SET_DESIRED_SIZE, width, height);
mCaller.sendMessage(msg);
}
-
+
+ public void setDisplayPadding(Rect padding) {
+ Message msg = mCaller.obtainMessageO(DO_SET_DISPLAY_PADDING, padding);
+ mCaller.sendMessage(msg);
+ }
+
public void setVisibility(boolean visible) {
Message msg = mCaller.obtainMessageI(MSG_VISIBILITY_CHANGED,
visible ? 1 : 0);
@@ -1041,6 +1166,9 @@
mEngine.doDesiredSizeChanged(message.arg1, message.arg2);
return;
}
+ case DO_SET_DISPLAY_PADDING: {
+ mEngine.doDisplayPaddingChanged((Rect) message.obj);
+ }
case MSG_UPDATE_SURFACE:
mEngine.updateSurface(true, false, false);
break;
@@ -1102,9 +1230,9 @@
@Override
public void attach(IWallpaperConnection conn, IBinder windowToken,
- int windowType, boolean isPreview, int reqWidth, int reqHeight) {
+ int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding) {
new IWallpaperEngineWrapper(mTarget, conn, windowToken,
- windowType, isPreview, reqWidth, reqHeight);
+ windowType, isPreview, reqWidth, reqHeight, padding);
}
}
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 7245975..9be220e 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -46,7 +46,6 @@
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;
-import java.util.TreeSet;
/**
*
@@ -578,7 +577,7 @@
*
* @deprecated Starting from API level 20, to select network synthesis, call
* ({@link TextToSpeech#getVoices()}, find a suitable network voice
- * ({@link Voice#getRequiresNetworkConnection()}) and pass it
+ * ({@link Voice#isNetworkConnectionRequired()}) and pass it
* to {@link TextToSpeech#setVoice(Voice)}).
*/
@Deprecated
@@ -596,7 +595,7 @@
* @deprecated Starting from API level 20, to select embedded synthesis, call
* ({@link TextToSpeech#getVoices()}, find a suitable embedded voice
- * ({@link Voice#getRequiresNetworkConnection()}) and pass it
+ * ({@link Voice#isNetworkConnectionRequired()}) and pass it
* to {@link TextToSpeech#setVoice(Voice)}).
*/
@Deprecated
@@ -957,20 +956,18 @@
*
* @param text
* The string of text. Example: <code>"south_south_east"</code>
- * @param filename
- * The full path to the sound file (for example:
- * "/sdcard/mysounds/hello.wav")
+ * @param file
+ * File object pointing to the sound file.
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
- public int addSpeech(CharSequence text, String filename) {
+ public int addSpeech(CharSequence text, File file) {
synchronized (mStartLock) {
- mUtterances.put(text, Uri.parse(filename));
+ mUtterances.put(text, Uri.fromFile(file));
return SUCCESS;
}
}
-
/**
* Adds a mapping between a string of text and a sound resource in a
* package. Use this to add custom earcons.
@@ -1017,7 +1014,11 @@
* "/sdcard/mysounds/tick.wav")
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
+ *
+ * @deprecated As of API level 20, replaced by
+ * {@link #addEarcon(String, File)}.
*/
+ @Deprecated
public int addEarcon(String earcon, String filename) {
synchronized(mStartLock) {
mEarcons.put(earcon, Uri.parse(filename));
@@ -1025,6 +1026,27 @@
}
}
+ /**
+ * Adds a mapping between a string of text and a sound file.
+ * Use this to add custom earcons.
+ *
+ * @see #playEarcon(String, int, HashMap)
+ *
+ * @param earcon
+ * The name of the earcon.
+ * Example: <code>"[tick]"</code>
+ * @param file
+ * File object pointing to the sound file.
+ *
+ * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
+ */
+ public int addEarcon(String earcon, File file) {
+ synchronized(mStartLock) {
+ mEarcons.put(earcon, Uri.fromFile(file));
+ return SUCCESS;
+ }
+ }
+
private Uri makeResourceUri(String packageName, int resourceId) {
return new Uri.Builder()
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
@@ -1061,7 +1083,7 @@
*/
public int speak(final CharSequence text,
final int queueMode,
- final HashMap<String, String> params,
+ final Bundle params,
final String utteranceId) {
return runAction(new Action<Integer>() {
@Override
@@ -1103,11 +1125,11 @@
*
* @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the speak operation.
* @deprecated As of API level 20, replaced by
- * {@link #speak(CharSequence, int, HashMap, String)}.
+ * {@link #speak(CharSequence, int, Bundle, String)}.
*/
@Deprecated
public int speak(final String text, final int queueMode, final HashMap<String, String> params) {
- return speak(text, queueMode, params,
+ return speak(text, queueMode, convertParamsHashMaptoBundle(params),
params == null ? null : params.get(Engine.KEY_PARAM_UTTERANCE_ID));
}
@@ -1135,7 +1157,7 @@
* @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playEarcon operation.
*/
public int playEarcon(final String earcon, final int queueMode,
- final HashMap<String, String> params, final String utteranceId) {
+ final Bundle params, final String utteranceId) {
return runAction(new Action<Integer>() {
@Override
public Integer run(ITextToSpeechService service) throws RemoteException {
@@ -1173,12 +1195,12 @@
*
* @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playEarcon operation.
* @deprecated As of API level 20, replaced by
- * {@link #playEarcon(String, int, HashMap, String)}.
+ * {@link #playEarcon(String, int, Bundle, String)}.
*/
@Deprecated
public int playEarcon(final String earcon, final int queueMode,
final HashMap<String, String> params) {
- return playEarcon(earcon, queueMode, params,
+ return playEarcon(earcon, queueMode, convertParamsHashMaptoBundle(params),
params == null ? null : params.get(Engine.KEY_PARAM_UTTERANCE_ID));
}
@@ -1544,10 +1566,10 @@
@Override
public Set<Locale> run(ITextToSpeechService service) throws RemoteException {
List<Voice> voices = service.getVoices();
- if (voices != null) {
- return new TreeSet<Locale>();
+ if (voices == null) {
+ return new HashSet<Locale>();
}
- TreeSet<Locale> locales = new TreeSet<Locale>();
+ HashSet<Locale> locales = new HashSet<Locale>();
for (Voice voice : voices) {
locales.add(voice.getLocale());
}
@@ -1570,7 +1592,7 @@
@Override
public Set<Voice> run(ITextToSpeechService service) throws RemoteException {
List<Voice> voices = service.getVoices();
- return (voices != null) ? new TreeSet<Voice>(voices) : new TreeSet<Voice>();
+ return (voices != null) ? new HashSet<Voice>(voices) : new HashSet<Voice>();
}
}, null, "getVoices");
}
@@ -1757,22 +1779,20 @@
* must be prefixed by the name of the engine they are intended for. For example
* the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the
* engine named "com.svox.pico" if it is being used.
- * @param filename Absolute file filename to write the generated audio data to.It should be
- * something like "/sdcard/myappsounds/mysound.wav".
+ * @param file File to write the generated audio data to.
* @param utteranceId An unique identifier for this request.
* @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the synthesizeToFile operation.
*/
- public int synthesizeToFile(final CharSequence text, final HashMap<String, String> params,
- final String filename, final String utteranceId) {
+ public int synthesizeToFile(final CharSequence text, final Bundle params,
+ final File file, final String utteranceId) {
return runAction(new Action<Integer>() {
@Override
public Integer run(ITextToSpeechService service) throws RemoteException {
ParcelFileDescriptor fileDescriptor;
int returnValue;
try {
- File file = new File(filename);
if(file.exists() && !file.canWrite()) {
- Log.e(TAG, "Can't write to " + filename);
+ Log.e(TAG, "Can't write to " + file);
return ERROR;
}
fileDescriptor = ParcelFileDescriptor.open(file,
@@ -1784,10 +1804,10 @@
fileDescriptor.close();
return returnValue;
} catch (FileNotFoundException e) {
- Log.e(TAG, "Opening file " + filename + " failed", e);
+ Log.e(TAG, "Opening file " + file + " failed", e);
return ERROR;
} catch (IOException e) {
- Log.e(TAG, "Closing file " + filename + " failed", e);
+ Log.e(TAG, "Closing file " + file + " failed", e);
return ERROR;
}
}
@@ -1817,16 +1837,18 @@
*
* @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the synthesizeToFile operation.
* @deprecated As of API level 20, replaced by
- * {@link #synthesizeToFile(CharSequence, HashMap, String, String)}.
+ * {@link #synthesizeToFile(CharSequence, Bundle, File, String)}.
*/
+ @Deprecated
public int synthesizeToFile(final String text, final HashMap<String, String> params,
final String filename) {
- return synthesizeToFile(text, params, filename, params.get(Engine.KEY_PARAM_UTTERANCE_ID));
+ return synthesizeToFile(text, convertParamsHashMaptoBundle(params),
+ new File(filename), params.get(Engine.KEY_PARAM_UTTERANCE_ID));
}
- private Bundle getParams(HashMap<String, String> params) {
+ private Bundle convertParamsHashMaptoBundle(HashMap<String, String> params) {
if (params != null && !params.isEmpty()) {
- Bundle bundle = new Bundle(mParams);
+ Bundle bundle = new Bundle();
copyIntParam(bundle, params, Engine.KEY_PARAM_STREAM);
copyIntParam(bundle, params, Engine.KEY_PARAM_SESSION_ID);
copyStringParam(bundle, params, Engine.KEY_PARAM_UTTERANCE_ID);
@@ -1852,11 +1874,85 @@
}
return bundle;
+ }
+ return null;
+ }
+
+ private Bundle getParams(Bundle params) {
+ if (params != null && !params.isEmpty()) {
+ Bundle bundle = new Bundle(mParams);
+ bundle.putAll(params);
+
+ verifyIntegerBundleParam(bundle, Engine.KEY_PARAM_STREAM);
+ verifyIntegerBundleParam(bundle, Engine.KEY_PARAM_SESSION_ID);
+ verifyStringBundleParam(bundle, Engine.KEY_PARAM_UTTERANCE_ID);
+ verifyFloatBundleParam(bundle, Engine.KEY_PARAM_VOLUME);
+ verifyFloatBundleParam(bundle, Engine.KEY_PARAM_PAN);
+
+ // Copy feature strings defined by the framework.
+ verifyBooleanBundleParam(bundle, Engine.KEY_FEATURE_NETWORK_SYNTHESIS);
+ verifyBooleanBundleParam(bundle, Engine.KEY_FEATURE_EMBEDDED_SYNTHESIS);
+ verifyIntegerBundleParam(bundle, Engine.KEY_FEATURE_NETWORK_TIMEOUT_MS);
+ verifyIntegerBundleParam(bundle, Engine.KEY_FEATURE_NETWORK_RETRIES_COUNT);
+
+ return bundle;
} else {
return mParams;
}
}
+ private static boolean verifyIntegerBundleParam(Bundle bundle, String key) {
+ if (bundle.containsKey(key)) {
+ if (!(bundle.get(key) instanceof Integer ||
+ bundle.get(key) instanceof Long)) {
+ bundle.remove(key);
+ Log.w(TAG, "Synthesis request paramter " + key + " containst value "
+ + " with invalid type. Should be an Integer or a Long");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean verifyStringBundleParam(Bundle bundle, String key) {
+ if (bundle.containsKey(key)) {
+ if (!(bundle.get(key) instanceof String)) {
+ bundle.remove(key);
+ Log.w(TAG, "Synthesis request paramter " + key + " containst value "
+ + " with invalid type. Should be a String");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean verifyBooleanBundleParam(Bundle bundle, String key) {
+ if (bundle.containsKey(key)) {
+ if (!(bundle.get(key) instanceof Boolean ||
+ bundle.get(key) instanceof String)) {
+ bundle.remove(key);
+ Log.w(TAG, "Synthesis request paramter " + key + " containst value "
+ + " with invalid type. Should be a Boolean or String");
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ private static boolean verifyFloatBundleParam(Bundle bundle, String key) {
+ if (bundle.containsKey(key)) {
+ if (!(bundle.get(key) instanceof Float ||
+ bundle.get(key) instanceof Double)) {
+ bundle.remove(key);
+ Log.w(TAG, "Synthesis request paramter " + key + " containst value "
+ + " with invalid type. Should be a Float or a Double");
+ return false;
+ }
+ }
+ return true;
+ }
+
private void copyStringParam(Bundle bundle, HashMap<String, String> params, String key) {
String value = params.get(key);
if (value != null) {
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 4fea109..d00a433 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -84,7 +84,7 @@
* the following methods:
* <ul>
* <li>{@link #onGetVoices()}</li>
- * <li>{@link #isValidVoiceName(String)}</li>
+ * <li>{@link #onIsValidVoiceName(String)}</li>
* <li>{@link #onLoadVoice(String)}</li>
* <li>{@link #onGetDefaultVoiceNameFor(String, String, String)}</li>
* </ul>
@@ -278,7 +278,7 @@
*
* @return A list of voices supported.
*/
- protected List<Voice> onGetVoices() {
+ public List<Voice> onGetVoices() {
// Enumerate all locales and check if they are available
ArrayList<Voice> voices = new ArrayList<Voice>();
for (Locale locale : Locale.getAvailableLocales()) {
@@ -335,7 +335,7 @@
}
Locale properLocale = TtsEngines.normalizeTTSLocale(iso3Locale);
String voiceName = properLocale.toLanguageTag();
- if (isValidVoiceName(voiceName) == TextToSpeech.SUCCESS) {
+ if (onIsValidVoiceName(voiceName) == TextToSpeech.SUCCESS) {
return voiceName;
} else {
return null;
@@ -357,7 +357,7 @@
* @param voiceName Name of the voice.
* @return {@link TextToSpeech#ERROR} or {@link TextToSpeech#SUCCESS}.
*/
- protected int onLoadVoice(String voiceName) {
+ public int onLoadVoice(String voiceName) {
Locale locale = Locale.forLanguageTag(voiceName);
if (locale == null) {
return TextToSpeech.ERROR;
@@ -388,7 +388,7 @@
* @param voiceName Name of the voice.
* @return {@link TextToSpeech#ERROR} or {@link TextToSpeech#SUCCESS}.
*/
- protected int isValidVoiceName(String voiceName) {
+ public int onIsValidVoiceName(String voiceName) {
Locale locale = Locale.forLanguageTag(voiceName);
if (locale == null) {
return TextToSpeech.ERROR;
@@ -1275,7 +1275,7 @@
if (!checkNonNull(voiceName)) {
return TextToSpeech.ERROR;
}
- int retVal = isValidVoiceName(voiceName);
+ int retVal = onIsValidVoiceName(voiceName);
if (retVal == TextToSpeech.SUCCESS) {
SpeechItem item = new LoadVoiceItem(caller, Binder.getCallingUid(),
diff --git a/core/java/android/speech/tts/Voice.java b/core/java/android/speech/tts/Voice.java
index a97141c..a1fa51d 100644
--- a/core/java/android/speech/tts/Voice.java
+++ b/core/java/android/speech/tts/Voice.java
@@ -162,7 +162,7 @@
/**
* @return Does the Voice require a network connection to work.
*/
- public boolean getRequiresNetworkConnection() {
+ public boolean isNetworkConnectionRequired() {
return mRequiresNetworkConnection;
}
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 0d1b568..40bb6ec 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -1417,9 +1417,9 @@
}
capturePropagationValues(values);
if (start) {
- addViewValues(mStartValues, view, values);
+ addViewValues(mStartValues, view, values, true);
} else {
- addViewValues(mEndValues, view, values);
+ addViewValues(mEndValues, view, values, true);
}
}
}
@@ -1460,7 +1460,7 @@
}
static void addViewValues(TransitionValuesMaps transitionValuesMaps,
- View view, TransitionValues transitionValues) {
+ View view, TransitionValues transitionValues, boolean setTransientState) {
transitionValuesMaps.viewValues.put(view, transitionValues);
int id = view.getId();
if (id >= 0) {
@@ -1489,11 +1489,15 @@
// Duplicate item IDs: cannot match by item ID.
View alreadyMatched = transitionValuesMaps.itemIdValues.get(itemId);
if (alreadyMatched != null) {
- alreadyMatched.setHasTransientState(false);
+ if (setTransientState) {
+ alreadyMatched.setHasTransientState(false);
+ }
transitionValuesMaps.itemIdValues.put(itemId, null);
}
} else {
- view.setHasTransientState(true);
+ if (setTransientState) {
+ view.setHasTransientState(true);
+ }
transitionValuesMaps.itemIdValues.put(itemId, view);
}
}
@@ -1560,9 +1564,9 @@
}
capturePropagationValues(values);
if (start) {
- addViewValues(mStartValues, view, values);
+ addViewValues(mStartValues, view, values, true);
} else {
- addViewValues(mEndValues, view, values);
+ addViewValues(mEndValues, view, values, true);
}
}
if (view instanceof ViewGroup) {
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index f6499ae..56db674 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -408,7 +408,7 @@
for (int i = 0; i < numValues; i++) {
View view = values.viewValues.keyAt(i);
if (isValidTarget(view)) {
- addViewValues(included, view, values.viewValues.valueAt(i));
+ addViewValues(included, view, values.viewValues.valueAt(i), false);
}
}
return included;
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 0b02552..d87d0f9 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -277,6 +277,18 @@
if ((mMode & MODE_IN) != MODE_IN || endValues == null) {
return null;
}
+ if (startValues == null) {
+ VisibilityInfo parentVisibilityInfo = null;
+ View endParent = (View) endValues.view.getParent();
+ TransitionValues startParentValues = getMatchedTransitionValues(endParent,
+ false);
+ TransitionValues endParentValues = getTransitionValues(endParent, false);
+ parentVisibilityInfo =
+ getVisibilityChangeInfo(startParentValues, endParentValues);
+ if (parentVisibilityInfo.visibilityChange) {
+ return null;
+ }
+ }
return onAppear(sceneRoot, endValues.view, startValues, endValues);
}
@@ -358,12 +370,16 @@
overlayView = startView;
} else if (startView.getParent() instanceof View) {
View startParent = (View) startView.getParent();
- if (!isValidTarget(startParent)) {
- if (startView.isAttachedToWindow()) {
- overlayView = copyViewImage(startView);
- } else {
- overlayView = startView;
- }
+ VisibilityInfo parentVisibilityInfo = null;
+ TransitionValues endParentValues = getMatchedTransitionValues(startParent,
+ true);
+ if (endParentValues != null) {
+ TransitionValues startParentValues = getTransitionValues(startParent, true);
+ parentVisibilityInfo =
+ getVisibilityChangeInfo(startParentValues, endParentValues);
+ }
+ if (parentVisibilityInfo == null || !parentVisibilityInfo.visibilityChange) {
+ overlayView = copyViewImage(startView);
} else if (startParent.getParent() == null) {
int id = startParent.getId();
if (id != View.NO_ID && sceneRoot.findViewById(id) != null
diff --git a/core/java/android/util/SizeF.java b/core/java/android/util/SizeF.java
index ac4f187..2edc4a7f 100644
--- a/core/java/android/util/SizeF.java
+++ b/core/java/android/util/SizeF.java
@@ -16,6 +16,7 @@
package android.util;
+import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.Preconditions.checkArgumentFinite;
/**
@@ -95,6 +96,61 @@
return mWidth + "x" + mHeight;
}
+ private static NumberFormatException invalidSizeF(String s) {
+ throw new NumberFormatException("Invalid SizeF: \"" + s + "\"");
+ }
+
+ /**
+ * Parses the specified string as a size value.
+ * <p>
+ * The ASCII characters {@code \}{@code u002a} ('*') and
+ * {@code \}{@code u0078} ('x') are recognized as separators between
+ * the width and height.</p>
+ * <p>
+ * For any {@code SizeF s}: {@code SizeF.parseSizeF(s.toString()).equals(s)}.
+ * However, the method also handles sizes expressed in the
+ * following forms:</p>
+ * <p>
+ * "<i>width</i>{@code x}<i>height</i>" or
+ * "<i>width</i>{@code *}<i>height</i>" {@code => new SizeF(width, height)},
+ * where <i>width</i> and <i>height</i> are string floats potentially
+ * containing a sign, such as "-10.3", "+7" or "5.2", but not containing
+ * an {@code 'x'} (such as a float in hexadecimal string format).</p>
+ *
+ * <pre>{@code
+ * SizeF.parseSizeF("3.2*+6").equals(new SizeF(3.2f, 6.0f)) == true
+ * SizeF.parseSizeF("-3x-6").equals(new SizeF(-3.0f, -6.0f)) == true
+ * SizeF.parseSizeF("4 by 3") => throws NumberFormatException
+ * }</pre>
+ *
+ * @param string the string representation of a size value.
+ * @return the size value represented by {@code string}.
+ *
+ * @throws NumberFormatException if {@code string} cannot be parsed
+ * as a size value.
+ * @throws NullPointerException if {@code string} was {@code null}
+ */
+ public static SizeF parseSizeF(String string)
+ throws NumberFormatException {
+ checkNotNull(string, "string must not be null");
+
+ int sep_ix = string.indexOf('*');
+ if (sep_ix < 0) {
+ sep_ix = string.indexOf('x');
+ }
+ if (sep_ix < 0) {
+ throw invalidSizeF(string);
+ }
+ try {
+ return new SizeF(Float.parseFloat(string.substring(0, sep_ix)),
+ Float.parseFloat(string.substring(sep_ix + 1)));
+ } catch (NumberFormatException e) {
+ throw invalidSizeF(string);
+ } catch (IllegalArgumentException e) {
+ throw invalidSizeF(string);
+ }
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index a10dda3..a283b91 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -19,7 +19,6 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
-import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -101,7 +100,7 @@
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
- message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID;
+ message.what = PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID;
message.arg1 = flags;
SomeArgs args = SomeArgs.obtain();
@@ -176,7 +175,7 @@
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
- message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID;
+ message.what = PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID;
message.arg1 = flags;
message.arg2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
@@ -261,7 +260,7 @@
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
- message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT;
+ message.what = PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT;
message.arg1 = flags;
SomeArgs args = SomeArgs.obtain();
@@ -637,6 +636,95 @@
}
}
+ public void computeClickPointInScreenClientThread(long accessibilityNodeId,
+ Region interactiveRegion, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, int interrogatingPid,
+ long interrogatingTid, MagnificationSpec spec) {
+ Message message = mHandler.obtainMessage();
+ message.what = PrivateHandler.MSG_COMPUTE_CLICK_POINT_IN_SCREEN;
+
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
+ args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
+ args.argi3 = interactionId;
+ args.arg1 = callback;
+ args.arg2 = spec;
+ args.arg3 = interactiveRegion;
+
+ message.obj = args;
+
+ // If the interrogation is performed by the same thread as the main UI
+ // thread in this process, set the message as a static reference so
+ // after this call completes the same thread but in the interrogating
+ // client can handle the message to generate the result.
+ if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
+ AccessibilityInteractionClient.getInstanceForThread(
+ interrogatingTid).setSameThreadMessage(message);
+ } else {
+ mHandler.sendMessage(message);
+ }
+ }
+
+ private void computeClickPointInScreenUiThread(Message message) {
+ SomeArgs args = (SomeArgs) message.obj;
+ final int accessibilityViewId = args.argi1;
+ final int virtualDescendantId = args.argi2;
+ final int interactionId = args.argi3;
+ final IAccessibilityInteractionConnectionCallback callback =
+ (IAccessibilityInteractionConnectionCallback) args.arg1;
+ final MagnificationSpec spec = (MagnificationSpec) args.arg2;
+ final Region interactiveRegion = (Region) args.arg3;
+ args.recycle();
+
+ boolean succeeded = false;
+ Point point = mTempPoint;
+ try {
+ if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
+ return;
+ }
+ View target = null;
+ if (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ target = findViewByAccessibilityId(accessibilityViewId);
+ } else {
+ target = mViewRootImpl.mView;
+ }
+ if (target != null && isShown(target)) {
+ AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
+ if (provider != null) {
+ // For virtual views just use the center of the bounds in screen.
+ AccessibilityNodeInfo node = null;
+ if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ node = provider.createAccessibilityNodeInfo(virtualDescendantId);
+ } else {
+ node = provider.createAccessibilityNodeInfo(
+ AccessibilityNodeProvider.HOST_VIEW_ID);
+ }
+ if (node != null) {
+ succeeded = true;
+ Rect boundsInScreen = mTempRect;
+ node.getBoundsInScreen(boundsInScreen);
+ point.set(boundsInScreen.centerX(), boundsInScreen.centerY());
+ }
+ } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ // For a real view, ask the view to compute the click point.
+ succeeded = target.computeClickPointInScreenForAccessibility(
+ interactiveRegion, point);
+ }
+ }
+ } finally {
+ try {
+ Point result = null;
+ if (succeeded) {
+ applyAppScaleAndMagnificationSpecIfNeeded(point, spec);
+ result = point;
+ }
+ callback.setComputeClickPointInScreenActionResult(result, interactionId);
+ } catch (RemoteException re) {
+ /* ignore - the other side will time out */
+ }
+ }
+ }
+
private View findViewByAccessibilityId(int accessibilityId) {
View root = mViewRootImpl.mView;
if (root == null) {
@@ -688,6 +776,26 @@
}
}
+ private void applyAppScaleAndMagnificationSpecIfNeeded(Point point,
+ MagnificationSpec spec) {
+ final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale;
+ if (!shouldApplyAppScaleAndMagnificationSpec(applicationScale, spec)) {
+ return;
+ }
+
+ if (applicationScale != 1.0f) {
+ point.x *= applicationScale;
+ point.y *= applicationScale;
+ }
+
+ if (spec != null) {
+ point.x *= spec.scale;
+ point.y *= spec.scale;
+ point.x += (int) spec.offsetX;
+ point.y += (int) spec.offsetY;
+ }
+ }
+
private void applyAppScaleAndMagnificationSpecIfNeeded(AccessibilityNodeInfo info,
MagnificationSpec spec) {
if (info == null) {
@@ -1080,11 +1188,12 @@
private class PrivateHandler extends Handler {
private final static int MSG_PERFORM_ACCESSIBILITY_ACTION = 1;
- private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID = 2;
- private final static int MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID = 3;
- private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT = 4;
+ private final static int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID = 2;
+ private final static int MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID = 3;
+ private final static int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT = 4;
private final static int MSG_FIND_FOCUS = 5;
private final static int MSG_FOCUS_SEARCH = 6;
+ private final static int MSG_COMPUTE_CLICK_POINT_IN_SCREEN = 7;
public PrivateHandler(Looper looper) {
super(looper);
@@ -1096,16 +1205,18 @@
switch (type) {
case MSG_PERFORM_ACCESSIBILITY_ACTION:
return "MSG_PERFORM_ACCESSIBILITY_ACTION";
- case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID:
- return "MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID";
- case MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID:
- return "MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID";
- case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT:
- return "MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT";
+ case MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID:
+ return "MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID";
+ case MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID:
+ return "MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID";
+ case MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT:
+ return "MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT";
case MSG_FIND_FOCUS:
return "MSG_FIND_FOCUS";
case MSG_FOCUS_SEARCH:
return "MSG_FOCUS_SEARCH";
+ case MSG_COMPUTE_CLICK_POINT_IN_SCREEN:
+ return "MSG_COMPUTE_CLICK_POINT_IN_SCREEN";
default:
throw new IllegalArgumentException("Unknown message type: " + type);
}
@@ -1115,16 +1226,16 @@
public void handleMessage(Message message) {
final int type = message.what;
switch (type) {
- case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID: {
+ case MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID: {
findAccessibilityNodeInfoByAccessibilityIdUiThread(message);
} break;
case MSG_PERFORM_ACCESSIBILITY_ACTION: {
perfromAccessibilityActionUiThread(message);
} break;
- case MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID: {
+ case MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID: {
findAccessibilityNodeInfosByViewIdUiThread(message);
} break;
- case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT: {
+ case MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT: {
findAccessibilityNodeInfosByTextUiThread(message);
} break;
case MSG_FIND_FOCUS: {
@@ -1133,6 +1244,9 @@
case MSG_FOCUS_SEARCH: {
focusSearchUiThread(message);
} break;
+ case MSG_COMPUTE_CLICK_POINT_IN_SCREEN: {
+ computeClickPointInScreenUiThread(message);
+ } break;
default:
throw new IllegalArgumentException("Unknown message type: " + type);
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index edb3798..d23e115 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -339,7 +339,8 @@
* @param attachInfo AttachInfo tied to the specified view.
* @param callbacks Callbacks invoked when drawing happens.
*/
- abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks);
+ abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
+ boolean isStartingWindow);
/**
* Creates a new hardware layer. A hardware layer built by calling this
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 5d6d998..6aa86c7 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -94,7 +94,8 @@
void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
IRemoteCallback startedCallback, boolean scaleUp);
void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX,
- int startY, IRemoteCallback startedCallback, boolean scaleUp);
+ int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
+ boolean scaleUp);
void executeAppTransition();
void setAppStartingWindow(IBinder token, String pkg, int theme,
in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 0f3f182..037ed28 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -177,6 +177,11 @@
void wallpaperOffsetsComplete(IBinder window);
+ /**
+ * Apply a raw offset to the wallpaper service when shown behind this window.
+ */
+ void setWallpaperDisplayOffset(IBinder windowToken, int x, int y);
+
Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
int z, in Bundle extras, boolean sync);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 1e28e33..4074529 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -39,7 +39,7 @@
private static native Bitmap nativeScreenshot(IBinder displayToken,
Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
- boolean allLayers, boolean useIdentityTransform);
+ boolean allLayers, boolean useIdentityTransform, int rotation);
private static native void nativeScreenshot(IBinder displayToken, Surface consumer,
Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
boolean allLayers, boolean useIdentityTransform);
@@ -688,17 +688,23 @@
* @param useIdentityTransform Replace whatever transformation (rotation,
* scaling, translation) the surface layers are currently using with the
* identity transformation while taking the screenshot.
+ * @param rotation Apply a custom clockwise rotation to the screenshot, i.e.
+ * Surface.ROTATION_0,90,180,270. Surfaceflinger will always take
+ * screenshots in its native portrait orientation by default, so this is
+ * useful for returning screenshots that are independent of device
+ * orientation.
* @return Returns a Bitmap containing the screen contents, or null
* if an error occurs. Make sure to call Bitmap.recycle() as soon as
* possible, once its content is not needed anymore.
*/
public static Bitmap screenshot(Rect sourceCrop, int width, int height,
- int minLayer, int maxLayer, boolean useIdentityTransform) {
+ int minLayer, int maxLayer, boolean useIdentityTransform,
+ int rotation) {
// TODO: should take the display as a parameter
IBinder displayToken = SurfaceControl.getBuiltInDisplay(
SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
return nativeScreenshot(displayToken, sourceCrop, width, height,
- minLayer, maxLayer, false, useIdentityTransform);
+ minLayer, maxLayer, false, useIdentityTransform, rotation);
}
/**
@@ -717,7 +723,8 @@
// TODO: should take the display as a parameter
IBinder displayToken = SurfaceControl.getBuiltInDisplay(
SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
- return nativeScreenshot(displayToken, new Rect(), width, height, 0, 0, true, false);
+ return nativeScreenshot(displayToken, new Rect(), width, height, 0, 0, true,
+ false, Surface.ROTATION_0);
}
private static void screenshot(IBinder display, Surface consumer, Rect sourceCrop,
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 5d2822d..3d1332c 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -16,6 +16,7 @@
package android.view;
+import android.graphics.Color;
import com.android.internal.R;
import android.content.Context;
@@ -267,7 +268,8 @@
view.mRecreateDisplayList = false;
}
- private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks) {
+ private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks,
+ boolean isStartingWindow) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
updateViewTreeDisplayList(view);
@@ -279,6 +281,12 @@
callbacks.onHardwarePreDraw(canvas);
canvas.insertReorderBarrier();
+ if (isStartingWindow) {
+ // Compensate for some situations in which a hw-accelerated surface
+ // will not be filled with anything by default; this is equivalent
+ // to the old behavior when the system process was not hw-accelerated
+ canvas.drawColor(Color.BLACK);
+ }
canvas.drawRenderNode(view.getDisplayList());
canvas.insertInorderBarrier();
@@ -298,7 +306,8 @@
}
@Override
- void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks) {
+ void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
+ boolean isStartingWindow) {
attachInfo.mIgnoreDirtyState = true;
long frameTimeNanos = mChoreographer.getFrameTimeNanos();
attachInfo.mDrawingTime = frameTimeNanos / TimeUtils.NANOS_PER_MS;
@@ -308,7 +317,7 @@
recordDuration = System.nanoTime();
}
- updateRootDisplayList(view, callbacks);
+ updateRootDisplayList(view, callbacks, isStartingWindow);
if (mProfilingEnabled) {
recordDuration = System.nanoTime() - recordDuration;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 770e78c..82c5425 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -35,6 +35,8 @@
import android.graphics.Matrix;
import android.graphics.Outline;
import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
@@ -5731,6 +5733,136 @@
}
/**
+ * Computes a point on which a sequence of a down/up event can be sent to
+ * trigger clicking this view. This method is for the exclusive use by the
+ * accessibility layer to determine where to send a click event in explore
+ * by touch mode.
+ *
+ * @param interactiveRegion The interactive portion of this window.
+ * @param outPoint The point to populate.
+ * @return True of such a point exists.
+ */
+ boolean computeClickPointInScreenForAccessibility(Region interactiveRegion,
+ Point outPoint) {
+ // Since the interactive portion of the view is a region but as a view
+ // may have a transformation matrix which cannot be applied to a
+ // region we compute the view bounds rectangle and all interactive
+ // predecessor's and sibling's (siblings of predecessors included)
+ // rectangles that intersect the view bounds. At the
+ // end if the view was partially covered by another interactive
+ // view we compute the view's interactive region and pick a point
+ // on its boundary path as regions do not offer APIs to get inner
+ // points. Note that the the code is optimized to fail early and
+ // avoid unnecessary allocations plus computations.
+
+ // The current approach has edge cases that may produce false
+ // positives or false negatives. For example, a portion of the
+ // view may be covered by an interactive descendant of a
+ // predecessor, which we do not compute. Also a view may be handling
+ // raw touch events instead registering click listeners, which
+ // we cannot compute. Despite these limitations this approach will
+ // work most of the time and it is a huge improvement over just
+ // blindly sending the down and up events in the center of the
+ // view.
+
+ // Cannot click on an unattached view.
+ if (mAttachInfo == null) {
+ return false;
+ }
+
+ // Attached to an invisible window means this view is not visible.
+ if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
+ return false;
+ }
+
+ RectF bounds = mAttachInfo.mTmpTransformRect;
+ bounds.set(0, 0, getWidth(), getHeight());
+ List<RectF> intersections = mAttachInfo.mTmpRectList;
+ intersections.clear();
+
+ if (mParent instanceof ViewGroup) {
+ ViewGroup parentGroup = (ViewGroup) mParent;
+ if (!parentGroup.translateBoundsAndIntersectionsInWindowCoordinates(
+ this, bounds, intersections)) {
+ intersections.clear();
+ return false;
+ }
+ }
+
+ // Take into account the window location.
+ final int dx = mAttachInfo.mWindowLeft;
+ final int dy = mAttachInfo.mWindowTop;
+ bounds.offset(dx, dy);
+ offsetRects(intersections, dx, dy);
+
+ if (intersections.isEmpty() && interactiveRegion == null) {
+ outPoint.set((int) bounds.centerX(), (int) bounds.centerY());
+ } else {
+ // This view is partially covered by other views, then compute
+ // the not covered region and pick a point on its boundary.
+ Region region = new Region();
+ region.set((int) bounds.left, (int) bounds.top,
+ (int) bounds.right, (int) bounds.bottom);
+
+ final int intersectionCount = intersections.size();
+ for (int i = intersectionCount - 1; i >= 0; i--) {
+ RectF intersection = intersections.remove(i);
+ region.op((int) intersection.left, (int) intersection.top,
+ (int) intersection.right, (int) intersection.bottom,
+ Region.Op.DIFFERENCE);
+ }
+
+ // If the view is completely covered, done.
+ if (region.isEmpty()) {
+ return false;
+ }
+
+ // Take into account the interactive portion of the window
+ // as the rest is covered by other windows. If no such a region
+ // then the whole window is interactive.
+ if (interactiveRegion != null) {
+ region.op(interactiveRegion, Region.Op.INTERSECT);
+ }
+
+ // If the view is completely covered, done.
+ if (region.isEmpty()) {
+ return false;
+ }
+
+ // Try a shortcut here.
+ if (region.isRect()) {
+ Rect regionBounds = mAttachInfo.mTmpInvalRect;
+ region.getBounds(regionBounds);
+ outPoint.set(regionBounds.centerX(), regionBounds.centerY());
+ return true;
+ }
+
+ // Get the a point on the region boundary path.
+ Path path = region.getBoundaryPath();
+ PathMeasure pathMeasure = new PathMeasure(path, false);
+ final float[] coordinates = mAttachInfo.mTmpTransformLocation;
+
+ // Without loss of generality pick a point.
+ final float point = pathMeasure.getLength() * 0.01f;
+ if (!pathMeasure.getPosTan(point, coordinates, null)) {
+ return false;
+ }
+
+ outPoint.set(Math.round(coordinates[0]), Math.round(coordinates[1]));
+ }
+
+ return true;
+ }
+
+ static void offsetRects(List<RectF> rects, float offsetX, float offsetY) {
+ final int rectCount = rects.size();
+ for (int i = 0; i < rectCount; i++) {
+ RectF intersection = rects.get(i);
+ intersection.offset(offsetX, offsetY);
+ }
+ }
+
+ /**
* Returns the delegate for implementing accessibility support via
* composition. For more details see {@link AccessibilityDelegate}.
*
@@ -20154,6 +20286,16 @@
final RectF mTmpTransformRect = new RectF();
/**
+ * Temporary for use in computing hit areas with transformed views
+ */
+ final RectF mTmpTransformRect1 = new RectF();
+
+ /**
+ * Temporary list of rectanges.
+ */
+ final List<RectF> mTmpRectList = new ArrayList<>();
+
+ /**
* Temporary for use in transforming invalidation rect
*/
final Matrix mTmpMatrix = new Matrix();
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index a94f973..12a49d5 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -875,6 +875,11 @@
data[i + 1] = theme.resolveAttribute(attributeId, outValue, true) ?
outValue.coerceToString().toString() : nullString;
i += 2;
+
+ // attempt to replace reference data with its name
+ if (outValue.type == TypedValue.TYPE_REFERENCE) {
+ data[i - 1] = resources.getResourceName(outValue.resourceId);
+ }
} catch (Resources.NotFoundException e) {
// ignore resources we can't resolve
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index c1e66de..4e1db90 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -771,6 +771,112 @@
}
/**
+ * Translates the given bounds and intersections from child coordinates to
+ * local coordinates. In case any interactive sibling of the calling child
+ * covers the latter, a new intersections is added to the intersection list.
+ * This method is for the exclusive use by the accessibility layer to compute
+ * a point where a sequence of down and up events would click on a view.
+ *
+ * @param child The child making the call.
+ * @param bounds The bounds to translate in child coordinates.
+ * @param intersections The intersections of interactive views covering the child.
+ * @return True if the bounds and intersections were computed, false otherwise.
+ */
+ boolean translateBoundsAndIntersectionsInWindowCoordinates(View child,
+ RectF bounds, List<RectF> intersections) {
+ // Not attached, done.
+ if (mAttachInfo == null) {
+ return false;
+ }
+
+ if (getAlpha() <= 0 || getTransitionAlpha() <= 0 ||
+ getVisibility() != VISIBLE) {
+ // Cannot click on a view with an invisible predecessor.
+ return false;
+ }
+
+ // Compensate for the child transformation.
+ if (!child.hasIdentityMatrix()) {
+ Matrix matrix = child.getMatrix();
+ matrix.mapRect(bounds);
+ final int intersectionCount = intersections.size();
+ for (int i = 0; i < intersectionCount; i++) {
+ RectF intersection = intersections.get(i);
+ matrix.mapRect(intersection);
+ }
+ }
+
+ // Translate the bounds from child to parent coordinates.
+ final int dx = child.mLeft - mScrollX;
+ final int dy = child.mTop - mScrollY;
+ bounds.offset(dx, dy);
+ offsetRects(intersections, dx, dy);
+
+ // If the bounds do not intersect our bounds, done.
+ if (!bounds.intersects(0, 0, getWidth(), getHeight())) {
+ return false;
+ }
+
+ // Check whether any clickable siblings cover the child
+ // view and if so keep track of the intersections. Also
+ // respect Z ordering when iterating over children.
+ ArrayList<View> orderedList = buildOrderedChildList();
+ final boolean useCustomOrder = orderedList == null
+ && isChildrenDrawingOrderEnabled();
+
+ final int childCount = mChildrenCount;
+ for (int i = childCount - 1; i >= 0; i--) {
+ final int childIndex = useCustomOrder
+ ? getChildDrawingOrder(childCount, i) : i;
+ final View sibling = (orderedList == null)
+ ? mChildren[childIndex] : orderedList.get(childIndex);
+
+ // We care only about siblings over the child.
+ if (sibling == child) {
+ break;
+ }
+
+ // If sibling is not interactive we do not care.
+ if (!sibling.isClickable() && !sibling.isLongClickable()) {
+ continue;
+ }
+
+ // Compute the sibling bounds in its coordinates.
+ RectF siblingBounds = mAttachInfo.mTmpTransformRect1;
+ siblingBounds.set(0, 0, sibling.getWidth(), sibling.getHeight());
+
+ // Take into account the sibling transformation matrix.
+ if (!sibling.hasIdentityMatrix()) {
+ sibling.getMatrix().mapRect(siblingBounds);
+ }
+
+ // Offset the sibling to our coordinates.
+ final int siblingDx = sibling.mLeft - mScrollX;
+ final int siblingDy = sibling.mTop - mScrollY;
+ siblingBounds.offset(siblingDx, siblingDy);
+
+ // Compute the intersection between the child and the sibling.
+ if (siblingBounds.intersect(bounds)) {
+ // If an interactive sibling completely covers the child, done.
+ if (siblingBounds.equals(bounds)) {
+ return false;
+ }
+ // Keep track of the intersection rectangle.
+ RectF intersection = new RectF(siblingBounds);
+ intersections.add(intersection);
+ }
+ }
+
+ if (mParent instanceof ViewGroup) {
+ ViewGroup parentGroup = (ViewGroup) mParent;
+ return parentGroup.translateBoundsAndIntersectionsInWindowCoordinates(
+ this, bounds, intersections);
+ }
+
+ return true;
+ }
+
+ /**
* Called when a child view has changed whether or not it is tracking transient state.
*/
public void childHasTransientStateChanged(View child, boolean childHasTransientState) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4299e2e..ae6e4e7 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -121,7 +121,7 @@
private static final String PROPERTY_MEDIA_DISABLED = "config.disable_media";
// property used by emulator to determine display shape
- private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
+ public static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
/**
* Maximum time we allow the user to roll the trackball enough to generate
@@ -711,17 +711,10 @@
// can be used by code on the system process to escape that and enable
// HW accelerated drawing. (This is basically for the lock screen.)
- final boolean fakeHwAccelerated = (attrs.privateFlags &
- WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED) != 0;
final boolean forceHwAccelerated = (attrs.privateFlags &
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED) != 0;
- if (fakeHwAccelerated) {
- // This is exclusively for the preview windows the window manager
- // shows for launching applications, so they will look more like
- // the app being launched.
- mAttachInfo.mHardwareAccelerationRequested = true;
- } else if (!HardwareRenderer.sRendererDisabled
+ if (!HardwareRenderer.sRendererDisabled
|| (HardwareRenderer.sSystemRendererDisabled && forceHwAccelerated)) {
if (mAttachInfo.mHardwareRenderer != null) {
mAttachInfo.mHardwareRenderer.destroy();
@@ -2486,7 +2479,8 @@
dirty.setEmpty();
mBlockResizeBuffer = false;
- mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
+ mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this,
+ params.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
} else {
// If we get here with a disabled & requested hardware renderer, something went
// wrong (an invalidate posted right before we destroyed the hardware surface
@@ -6679,12 +6673,12 @@
public void performAccessibilityAction(long accessibilityNodeId, int action,
Bundle arguments, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags,
- int interogatingPid, long interrogatingTid) {
+ int interrogatingPid, long interrogatingTid) {
ViewRootImpl viewRootImpl = mViewRootImpl.get();
if (viewRootImpl != null && viewRootImpl.mView != null) {
viewRootImpl.getAccessibilityInteractionController()
.performAccessibilityActionClientThread(accessibilityNodeId, action, arguments,
- interactionId, callback, flags, interogatingPid, interrogatingTid);
+ interactionId, callback, flags, interrogatingPid, interrogatingTid);
} else {
// We cannot make the call and notify the caller so it does not wait.
try {
@@ -6696,6 +6690,26 @@
}
@Override
+ public void computeClickPointInScreen(long accessibilityNodeId, Region interactiveRegion,
+ int interactionId, IAccessibilityInteractionConnectionCallback callback,
+ int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
+ ViewRootImpl viewRootImpl = mViewRootImpl.get();
+ if (viewRootImpl != null && viewRootImpl.mView != null) {
+ viewRootImpl.getAccessibilityInteractionController()
+ .computeClickPointInScreenClientThread(accessibilityNodeId,
+ interactiveRegion, interactionId, callback, interrogatingPid,
+ interrogatingTid, spec);
+ } else {
+ // We cannot make the call and notify the caller so it does not wait.
+ try {
+ callback.setComputeClickPointInScreenActionResult(null, interactionId);
+ } catch (RemoteException re) {
+ /* best effort - ignore */
+ }
+ }
+ }
+
+ @Override
public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId,
String viewId, Region interactiveRegion, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags,
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 571a8f0..24c3c1a 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -378,35 +378,75 @@
}
/**
- * @hide
+ * Returns the top stable inset in pixels.
+ *
+ * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
+ * partially or fully obscured by the system UI elements. This value does not change
+ * based on the visibility state of those elements; for example, if the status bar is
+ * normally shown, but temporarily hidden, the stable inset will still provide the inset
+ * associated with the status bar being shown.</p>
+ *
+ * @return The top stable inset
*/
public int getStableInsetTop() {
return mStableInsets.top;
}
/**
- * @hide
+ * Returns the left stable inset in pixels.
+ *
+ * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
+ * partially or fully obscured by the system UI elements. This value does not change
+ * based on the visibility state of those elements; for example, if the status bar is
+ * normally shown, but temporarily hidden, the stable inset will still provide the inset
+ * associated with the status bar being shown.</p>
+ *
+ * @return The left stable inset
*/
public int getStableInsetLeft() {
return mStableInsets.left;
}
/**
- * @hide
+ * Returns the right stable inset in pixels.
+ *
+ * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
+ * partially or fully obscured by the system UI elements. This value does not change
+ * based on the visibility state of those elements; for example, if the status bar is
+ * normally shown, but temporarily hidden, the stable inset will still provide the inset
+ * associated with the status bar being shown.</p>
+ *
+ * @return The right stable inset
*/
public int getStableInsetRight() {
return mStableInsets.right;
}
/**
- * @hide
+ * Returns the bottom stable inset in pixels.
+ *
+ * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
+ * partially or fully obscured by the system UI elements. This value does not change
+ * based on the visibility state of those elements; for example, if the status bar is
+ * normally shown, but temporarily hidden, the stable inset will still provide the inset
+ * associated with the status bar being shown.</p>
+ *
+ * @return The bottom stable inset
*/
public int getStableInsetBottom() {
return mStableInsets.bottom;
}
/**
- * @hide
+ * Returns true if this WindowInsets has nonzero stable insets.
+ *
+ * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
+ * partially or fully obscured by the system UI elements. This value does not change
+ * based on the visibility state of those elements; for example, if the status bar is
+ * normally shown, but temporarily hidden, the stable inset will still provide the inset
+ * associated with the status bar being shown.</p>
+ *
+ * @return true if any of the stable inset values are nonzero
*/
public boolean hasStableInsets() {
return mStableInsets.top != 0 || mStableInsets.left != 0 || mStableInsets.right != 0
@@ -414,7 +454,9 @@
}
/**
- * @hide
+ * Returns a copy of this WindowInsets with the stable insets fully consumed.
+ *
+ * @return A modified copy of this WindowInsets
*/
public WindowInsets consumeStableInsets() {
final WindowInsets result = new WindowInsets(this);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 47ee52e..273ec9d 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1024,26 +1024,6 @@
public int flags;
/**
- * If the window has requested hardware acceleration, but this is not
- * allowed in the process it is in, then still render it as if it is
- * hardware accelerated. This is used for the starting preview windows
- * in the system process, which don't need to have the overhead of
- * hardware acceleration (they are just a static rendering), but should
- * be rendered as such to match the actual window of the app even if it
- * is hardware accelerated.
- * Even if the window isn't hardware accelerated, still do its rendering
- * as if it was.
- * Like {@link #FLAG_HARDWARE_ACCELERATED} except for trusted system windows
- * that need hardware acceleration (e.g. LockScreen), where hardware acceleration
- * is generally disabled. This flag must be specified in addition to
- * {@link #FLAG_HARDWARE_ACCELERATED} to enable hardware acceleration for system
- * windows.
- *
- * @hide
- */
- public static final int PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED = 0x00000001;
-
- /**
* In the system process, we globally do not use hardware acceleration
* because there are many threads doing UI there and they conflict.
* If certain parts of the UI that really do want to use hardware
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index db78ec5..374f7e0 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -17,6 +17,7 @@
package android.view.accessibility;
import android.accessibilityservice.IAccessibilityServiceConnection;
+import android.graphics.Point;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -98,6 +99,8 @@
private boolean mPerformAccessibilityActionResult;
+ private Point mComputeClickPointResult;
+
private Message mSameThreadMessage;
private static final SparseArray<IAccessibilityServiceConnection> sConnectionCache =
@@ -519,6 +522,43 @@
return false;
}
+ /**
+ * Computes a point in screen coordinates where sending a down/up events would
+ * perform a click on an {@link AccessibilityNodeInfo}.
+ *
+ * @param connectionId The id of a connection for interacting with the system.
+ * @param accessibilityWindowId A unique window id. Use
+ * {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+ * to query the currently active window.
+ * @param accessibilityNodeId A unique view id or virtual descendant id from
+ * where to start the search. Use
+ * {@link android.view.accessibility.AccessibilityNodeInfo#ROOT_NODE_ID}
+ * to start from the root.
+ * @return Point the click point of null if no such point.
+ */
+ public Point computeClickPointInScreen(int connectionId, int accessibilityWindowId,
+ long accessibilityNodeId) {
+ try {
+ IAccessibilityServiceConnection connection = getConnection(connectionId);
+ if (connection != null) {
+ final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final boolean success = connection.computeClickPointInScreen(
+ accessibilityWindowId, accessibilityNodeId,
+ interactionId, this, Thread.currentThread().getId());
+ if (success) {
+ return getComputeClickPointInScreenResultAndClear(interactionId);
+ }
+ } else {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+ }
+ }
+ } catch (RemoteException re) {
+ Log.w(LOG_TAG, "Error while calling remote computeClickPointInScreen", re);
+ }
+ return null;
+ }
+
public void clearCache() {
sAccessibilityCache.clear();
}
@@ -634,6 +674,34 @@
}
/**
+ * Gets the result of a request to compute a point in screen for clicking on a node.
+ *
+ * @param interactionId The interaction id to match the result with the request.
+ * @return The point or null if no such point.
+ */
+ private Point getComputeClickPointInScreenResultAndClear(int interactionId) {
+ synchronized (mInstanceLock) {
+ final boolean success = waitForResultTimedLocked(interactionId);
+ Point result = success ? mComputeClickPointResult : null;
+ clearResultLocked();
+ return result;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setComputeClickPointInScreenActionResult(Point point, int interactionId) {
+ synchronized (mInstanceLock) {
+ if (interactionId > mInteractionId) {
+ mComputeClickPointResult = point;
+ mInteractionId = interactionId;
+ }
+ mInstanceLock.notifyAll();
+ }
+ }
+
+ /**
* Clears the result state.
*/
private void clearResultLocked() {
@@ -641,6 +709,7 @@
mFindAccessibilityNodeInfoResult = null;
mFindAccessibilityNodeInfosResult = null;
mPerformAccessibilityActionResult = false;
+ mComputeClickPointResult = null;
}
/**
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index faf7789..66a3f46 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -17,6 +17,7 @@
package android.view.accessibility;
import android.graphics.Region;
+import android.graphics.Point;
import android.os.Bundle;
import android.view.MagnificationSpec;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -53,4 +54,8 @@
void performAccessibilityAction(long accessibilityNodeId, int action, in Bundle arguments,
int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
int interrogatingPid, long interrogatingTid);
+
+ void computeClickPointInScreen(long accessibilityNodeId, in Region bounds, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, int interrogatingPid,
+ long interrogatingTid, in MagnificationSpec spec);
}
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
index c1a3ab7..f480216 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
@@ -16,6 +16,7 @@
package android.view.accessibility;
+import android.graphics.Point;
import android.view.accessibility.AccessibilityNodeInfo;
import java.util.List;
@@ -51,4 +52,12 @@
* @param interactionId The interaction id to match the result with the request.
*/
void setPerformAccessibilityActionResult(boolean succeeded, int interactionId);
+
+ /**
+ * Sets the result of a request to compute a point for clicking in a view.
+ *
+ * @param point The point of null if no such point.
+ * @param interactionId The interaction id to match the result with the request.
+ */
+ void setComputeClickPointInScreenActionResult(in Point point, int interactionId);
}
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java
index fe0f5b9..600fffe 100644
--- a/core/java/android/view/inputmethod/CursorAnchorInfo.java
+++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java
@@ -35,9 +35,21 @@
* actually inserted.</p>
*/
public final class CursorAnchorInfo implements Parcelable {
+ /**
+ * The index of the first character of the selected text (inclusive). {@code -1} when there is
+ * no text selection.
+ */
private final int mSelectionStart;
+ /**
+ * The index of the first character of the selected text (exclusive). {@code -1} when there is
+ * no text selection.
+ */
private final int mSelectionEnd;
+ /**
+ * The index of the first character of the composing text (inclusive). {@code -1} when there is
+ * no composing text.
+ */
private final int mComposingTextStart;
/**
* The text, tracked as a composing region.
@@ -82,7 +94,7 @@
* Java chars, in the local coordinates that will be transformed with the transformation matrix
* when rendered on the screen.
*/
- private final SparseRectFArray mCharacterRects;
+ private final SparseRectFArray mCharacterBoundsArray;
/**
* Transformation matrix that is applied to any positional information of this class to
@@ -91,18 +103,24 @@
private final Matrix mMatrix;
/**
- * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterRectFlags(int)}: the
+ * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
* insertion marker or character bounds have at least one visible region.
*/
public static final int FLAG_HAS_VISIBLE_REGION = 0x01;
/**
- * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterRectFlags(int)}: the
+ * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
* insertion marker or character bounds have at least one invisible (clipped) region.
*/
public static final int FLAG_HAS_INVISIBLE_REGION = 0x02;
/**
+ * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
+ * insertion marker or character bounds is placed at right-to-left (RTL) character.
+ */
+ public static final int FLAG_IS_RTL = 0x04;
+
+ /**
* @removed
*/
public static final int CHARACTER_RECT_TYPE_MASK = 0x0f;
@@ -144,7 +162,7 @@
mInsertionMarkerTop = source.readFloat();
mInsertionMarkerBaseline = source.readFloat();
mInsertionMarkerBottom = source.readFloat();
- mCharacterRects = source.readParcelable(SparseRectFArray.class.getClassLoader());
+ mCharacterBoundsArray = source.readParcelable(SparseRectFArray.class.getClassLoader());
mMatrix = new Matrix();
mMatrix.setValues(source.createFloatArray());
}
@@ -166,7 +184,7 @@
dest.writeFloat(mInsertionMarkerTop);
dest.writeFloat(mInsertionMarkerBaseline);
dest.writeFloat(mInsertionMarkerBottom);
- dest.writeParcelable(mCharacterRects, flags);
+ dest.writeParcelable(mCharacterBoundsArray, flags);
final float[] matrixArray = new float[9];
mMatrix.getValues(matrixArray);
dest.writeFloatArray(matrixArray);
@@ -174,7 +192,6 @@
@Override
public int hashCode(){
- // TODO: Improve the hash function.
final float floatHash = mInsertionMarkerHorizontal + mInsertionMarkerTop
+ mInsertionMarkerBaseline + mInsertionMarkerBottom;
int hash = floatHash > 0 ? (int) floatHash : (int)(-floatHash);
@@ -185,7 +202,7 @@
hash *= 31;
hash += Objects.hashCode(mComposingText);
hash *= 31;
- hash += Objects.hashCode(mCharacterRects);
+ hash += Objects.hashCode(mCharacterBoundsArray);
hash *= 31;
hash += Objects.hashCode(mMatrix);
return hash;
@@ -231,7 +248,7 @@
|| !areSameFloatImpl(mInsertionMarkerBottom, that.mInsertionMarkerBottom)) {
return false;
}
- if (!Objects.equals(mCharacterRects, that.mCharacterRects)) {
+ if (!Objects.equals(mCharacterBoundsArray, that.mCharacterBoundsArray)) {
return false;
}
if (!Objects.equals(mMatrix, that.mMatrix)) {
@@ -250,7 +267,7 @@
+ " mInsertionMarkerTop=" + mInsertionMarkerTop
+ " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline
+ " mInsertionMarkerBottom=" + mInsertionMarkerBottom
- + " mCharacterRects=" + Objects.toString(mCharacterRects)
+ + " mCharacterBoundsArray=" + Objects.toString(mCharacterBoundsArray)
+ " mMatrix=" + Objects.toString(mMatrix)
+ "}";
}
@@ -259,6 +276,19 @@
* Builder for {@link CursorAnchorInfo}. This class is not designed to be thread-safe.
*/
public static final class Builder {
+ private int mSelectionStart = -1;
+ private int mSelectionEnd = -1;
+ private int mComposingTextStart = -1;
+ private CharSequence mComposingText = null;
+ private float mInsertionMarkerHorizontal = Float.NaN;
+ private float mInsertionMarkerTop = Float.NaN;
+ private float mInsertionMarkerBaseline = Float.NaN;
+ private float mInsertionMarkerBottom = Float.NaN;
+ private int mInsertionMarkerFlags = 0;
+ private SparseRectFArrayBuilder mCharacterBoundsArrayBuilder = null;
+ private final Matrix mMatrix = new Matrix(Matrix.IDENTITY_MATRIX);
+ private boolean mMatrixInitialized = false;
+
/**
* Sets the text range of the selection. Calling this can be skipped if there is no
* selection.
@@ -268,8 +298,6 @@
mSelectionEnd = newEnd;
return this;
}
- private int mSelectionStart = -1;
- private int mSelectionEnd = -1;
/**
* Sets the text range of the composing text. Calling this can be skipped if there is
@@ -288,8 +316,6 @@
}
return this;
}
- private int mComposingTextStart = -1;
- private CharSequence mComposingText = null;
/**
* @removed
@@ -335,11 +361,33 @@
mInsertionMarkerFlags = flags;
return this;
}
- private float mInsertionMarkerHorizontal = Float.NaN;
- private float mInsertionMarkerTop = Float.NaN;
- private float mInsertionMarkerBaseline = Float.NaN;
- private float mInsertionMarkerBottom = Float.NaN;
- private int mInsertionMarkerFlags = 0;
+
+ /**
+ * Adds the bounding box of the character specified with the index.
+ *
+ * @param index index of the character in Java chars units. Must be specified in
+ * ascending order across successive calls.
+ * @param left x coordinate of the left edge of the character in local coordinates.
+ * @param top y coordinate of the top edge of the character in local coordinates.
+ * @param right x coordinate of the right edge of the character in local coordinates.
+ * @param bottom y coordinate of the bottom edge of the character in local coordinates.
+ * @param flags flags for this character bounds. See {@link #FLAG_HAS_VISIBLE_REGION},
+ * {@link #FLAG_HAS_INVISIBLE_REGION} and {@link #FLAG_IS_RTL}. These flags must be
+ * specified when necessary.
+ * @throws IllegalArgumentException If the index is a negative value, or not greater than
+ * all of the previously called indices.
+ */
+ public Builder addCharacterBounds(final int index, final float left, final float top,
+ final float right, final float bottom, final int flags) {
+ if (index < 0) {
+ throw new IllegalArgumentException("index must not be a negative integer.");
+ }
+ if (mCharacterBoundsArrayBuilder == null) {
+ mCharacterBoundsArrayBuilder = new SparseRectFArrayBuilder();
+ }
+ mCharacterBoundsArrayBuilder.append(index, left, top, right, bottom, flags);
+ return this;
+ }
/**
* Adds the bounding box of the character specified with the index.
@@ -358,21 +406,25 @@
* example.
* @throws IllegalArgumentException If the index is a negative value, or not greater than
* all of the previously called indices.
+ * @removed
*/
public Builder addCharacterRect(final int index, final float leadingEdgeX,
final float leadingEdgeY, final float trailingEdgeX, final float trailingEdgeY,
final int flags) {
- if (index < 0) {
- throw new IllegalArgumentException("index must not be a negative integer.");
+ final int newFlags;
+ final float left;
+ final float right;
+ if (leadingEdgeX <= trailingEdgeX) {
+ newFlags = flags;
+ left = leadingEdgeX;
+ right = trailingEdgeX;
+ } else {
+ newFlags = flags | FLAG_IS_RTL;
+ left = trailingEdgeX;
+ right = leadingEdgeX;
}
- if (mCharacterRectBuilder == null) {
- mCharacterRectBuilder = new SparseRectFArrayBuilder();
- }
- mCharacterRectBuilder.append(index, leadingEdgeX, leadingEdgeY, trailingEdgeX,
- trailingEdgeY, flags);
- return this;
+ return addCharacterBounds(index, left, leadingEdgeY, right, trailingEdgeY, newFlags);
}
- private SparseRectFArrayBuilder mCharacterRectBuilder = null;
/**
* Sets the matrix that transforms local coordinates into screen coordinates.
@@ -384,8 +436,6 @@
mMatrixInitialized = true;
return this;
}
- private final Matrix mMatrix = new Matrix(Matrix.IDENTITY_MATRIX);
- private boolean mMatrixInitialized = false;
/**
* @return {@link CursorAnchorInfo} using parameters in this {@link Builder}.
@@ -394,13 +444,15 @@
*/
public CursorAnchorInfo build() {
if (!mMatrixInitialized) {
- // Coordinate transformation matrix is mandatory when positional parameters are
- // specified.
- if ((mCharacterRectBuilder != null && !mCharacterRectBuilder.isEmpty()) ||
- !Float.isNaN(mInsertionMarkerHorizontal) ||
- !Float.isNaN(mInsertionMarkerTop) ||
- !Float.isNaN(mInsertionMarkerBaseline) ||
- !Float.isNaN(mInsertionMarkerBottom)) {
+ // Coordinate transformation matrix is mandatory when at least one positional
+ // parameter is specified.
+ final boolean hasCharacterBounds = (mCharacterBoundsArrayBuilder != null
+ && !mCharacterBoundsArrayBuilder.isEmpty());
+ if (hasCharacterBounds
+ || !Float.isNaN(mInsertionMarkerHorizontal)
+ || !Float.isNaN(mInsertionMarkerTop)
+ || !Float.isNaN(mInsertionMarkerBaseline)
+ || !Float.isNaN(mInsertionMarkerBottom)) {
throw new IllegalArgumentException("Coordinate transformation matrix is " +
"required when positional parameters are specified.");
}
@@ -424,8 +476,8 @@
mInsertionMarkerBottom = Float.NaN;
mMatrix.set(Matrix.IDENTITY_MATRIX);
mMatrixInitialized = false;
- if (mCharacterRectBuilder != null) {
- mCharacterRectBuilder.reset();
+ if (mCharacterBoundsArrayBuilder != null) {
+ mCharacterBoundsArrayBuilder.reset();
}
}
}
@@ -440,8 +492,8 @@
mInsertionMarkerTop = builder.mInsertionMarkerTop;
mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline;
mInsertionMarkerBottom = builder.mInsertionMarkerBottom;
- mCharacterRects = builder.mCharacterRectBuilder != null ?
- builder.mCharacterRectBuilder.build() : null;
+ mCharacterBoundsArray = builder.mCharacterBoundsArrayBuilder != null ?
+ builder.mCharacterBoundsArrayBuilder.build() : null;
mMatrix = new Matrix(builder.mMatrix);
}
@@ -539,6 +591,19 @@
/**
* Returns a new instance of {@link RectF} that indicates the location of the character
* specified with the index.
+ * @param index index of the character in a Java chars.
+ * @return the character bounds in local coordinates as a new instance of {@link RectF}.
+ */
+ public RectF getCharacterBounds(final int index) {
+ if (mCharacterBoundsArray == null) {
+ return null;
+ }
+ return mCharacterBoundsArray.get(index);
+ }
+
+ /**
+ * Returns a new instance of {@link RectF} that indicates the location of the character
+ * specified with the index.
* <p>
* Note that coordinates are not necessarily contiguous or even monotonous, especially when
* RTL text and LTR text are mixed.
@@ -549,28 +614,32 @@
* the location. Note that the {@code left} field can be greater than the {@code right} field
* if the character is in RTL text. Returns {@code null} if no location information is
* available.
+ * @removed
*/
- // TODO: Prepare a document about the expected behavior for surrogate pairs, combining
- // characters, and non-graphical chars.
public RectF getCharacterRect(final int index) {
- if (mCharacterRects == null) {
- return null;
+ return getCharacterBounds(index);
+ }
+
+ /**
+ * Returns the flags associated with the character bounds specified with the index.
+ * @param index index of the character in a Java chars.
+ * @return {@code 0} if no flag is specified.
+ */
+ public int getCharacterBoundsFlags(final int index) {
+ if (mCharacterBoundsArray == null) {
+ return 0;
}
- return mCharacterRects.get(index);
+ return mCharacterBoundsArray.getFlags(index, 0);
}
/**
* Returns the flags associated with the character rect specified with the index.
* @param index index of the character in a Java chars.
* @return {@code 0} if no flag is specified.
+ * @removed
*/
- // TODO: Prepare a document about the expected behavior for surrogate pairs, combining
- // characters, and non-graphical chars.
public int getCharacterRectFlags(final int index) {
- if (mCharacterRects == null) {
- return 0;
- }
- return mCharacterRects.getFlags(index, 0);
+ return getCharacterBoundsFlags(index);
}
/**
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index e7ada27..1671faa 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -211,18 +211,6 @@
}
/**
- * Constructor with no subtype ID specified, overridesImplicitlyEnabledSubtype not specified.
- * Arguments for this constructor have the same meanings as
- * {@link InputMethodSubtype#InputMethodSubtype(int, int, String, String, String, boolean,
- * boolean, int)} except "id" and "overridesImplicitlyEnabledSubtype".
- * @hide
- */
- public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
- boolean isAuxiliary) {
- this(nameId, iconId, locale, mode, extraValue, isAuxiliary, false);
- }
-
- /**
* Constructor with no subtype ID specified.
* @deprecated use {@link InputMethodSubtypeBuilder} instead.
* Arguments for this constructor have the same meanings as
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 547acfa..46a7fd0 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -416,38 +416,6 @@
}
/**
- * UploadHelper simplifies file upload operations by providing helper methods that
- * would handle most common file picker/media capture requests. The application
- * can use the helper to build an intent to start a file picker, and then parse
- * the result returned by the activity.
- *
- * How to use:
- * 1. Create a helper using {@link FileChooserParams#getUploadHelper}
- * 2. Build an intent using {@link UploadHelper#buildIntent}
- * 3. Fire the intent using {@link android.app.Activity#startActivityForResult}.
- * 4. Check for ActivityNotFoundException and take a user friendly action if thrown.
- * 5. Listen the result using {@link android.app.Activity#onActivityResult}
- * 6. Parse the result using {@link UploadHelper#parseResult}
- * 7. Send the result using filePathCallback of {@link WebChromeClient#onShowFileChooser}
- */
- public static abstract class UploadHelper {
- /**
- * Returns an intent that would start a file picker for file selection/media capture.
- */
- public abstract Intent buildIntent();
-
- /**
- * Parses the result returned by the file picker activity.
- *
- * @param resultCode the integer result code returned by the file picker activity.
- * @param data the intent returned by the file picker activity.
- * @return the Uris of selected file(s) or null if the resultCode indicates
- * activity canceled or any other error.
- */
- public abstract Uri[] parseResult(int resultCode, Intent data);
- }
-
- /**
* Parameters used in the {@link #onShowFileChooser} method.
*/
public static abstract class FileChooserParams {
@@ -464,11 +432,17 @@
public static final int MODE_SAVE = 3;
/**
- * Returns a helper to simplify choosing and uploading files. The helper builds a default
- * intent that the application can send using startActivityForResult and processes the
- * results.
+ * Parse the result returned by the file picker activity. This method should be used with
+ * {@link #createIntent}. Refer to {@link #createIntent} for how to use it.
+ *
+ * @param resultCode the integer result code returned by the file picker activity.
+ * @param data the intent returned by the file picker activity.
+ * @return the Uris of selected file(s) or null if the resultCode indicates
+ * activity canceled or any other error.
*/
- public abstract UploadHelper getUploadHelper();
+ public static Uri[] parseResult(int resultCode, Intent data) {
+ return WebViewFactory.getProvider().getStatics().parseFileChooserResult(resultCode, data);
+ }
/**
* Returns file chooser mode.
@@ -500,7 +474,28 @@
* The file name of a default selection if specified, or null.
*/
public abstract String getFilenameHint();
- };
+
+ /**
+ * Creates an intent that would start a file picker for file selection.
+ * The Intent supports choosing files from simple file sources available
+ * on the device. Some advanced sources (for example, live media capture)
+ * may not be supported and applications wishing to support these sources
+ * or more advanced file operations should build their own Intent.
+ *
+ * <pre>
+ * How to use:
+ * 1. Build an intent using {@link #createIntent}
+ * 2. Fire the intent using {@link android.app.Activity#startActivityForResult}.
+ * 3. Check for ActivityNotFoundException and take a user friendly action if thrown.
+ * 4. Listen the result using {@link android.app.Activity#onActivityResult}
+ * 5. Parse the result using {@link #parseResult} only if media capture was not requested.
+ * 6. Send the result using filePathCallback of {@link WebChromeClient#onShowFileChooser}
+ * </pre>
+ *
+ * @return an Intent that supports basic file chooser sources.
+ */
+ public abstract Intent createIntent();
+ }
/**
* Tell the client to open a file chooser.
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index 20bb932..d37d217 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -17,6 +17,8 @@
package android.webkit;
import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
/**
* This is the main entry-point into the WebView back end implementations, which the WebView
@@ -64,6 +66,12 @@
* {@link android.webkit.WebView#setSlowWholeDocumentDrawEnabled(boolean) }
*/
void enableSlowWholeDocumentDraw();
+
+ /**
+ * Implement the API method
+ * {@link android.webkit.WebChromeClient.FileChooserParams#parseResult(int, Intent)}
+ */
+ Uri[] parseFileChooserResult(int resultCode, Intent intent);
}
Statics getStatics();
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index eef8554..94d52d5 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -3325,8 +3325,8 @@
}
if (dispatchNestedPreScroll(0, -rawDeltaY, mScrollConsumed, mScrollOffset)) {
rawDeltaY += mScrollConsumed[1];
- scrollOffsetCorrection -= mScrollOffset[1];
- scrollConsumedCorrection -= mScrollConsumed[1];
+ scrollOffsetCorrection = -mScrollOffset[1];
+ scrollConsumedCorrection = mScrollConsumed[1];
if (vtev != null) {
vtev.offsetLocation(0, mScrollOffset[1]);
}
@@ -3437,7 +3437,7 @@
}
}
}
- mMotionY = y + scrollOffsetCorrection;
+ mMotionY = y + lastYCorrection + scrollOffsetCorrection;
}
mLastY = y + lastYCorrection + scrollOffsetCorrection;
}
@@ -3505,10 +3505,10 @@
mMotionCorrection = 0;
View motionView = getChildAt(motionPosition - mFirstPosition);
mMotionViewOriginalTop = motionView != null ? motionView.getTop() : 0;
- mMotionY = y;
+ mMotionY = y + scrollOffsetCorrection;
mMotionPosition = motionPosition;
}
- mLastY = y;
+ mLastY = y + lastYCorrection + scrollOffsetCorrection;
mDirection = newDirection;
}
}
@@ -3876,7 +3876,7 @@
if (mPositionScroller != null) {
mPositionScroller.stop();
}
- if (flingVelocity) {
+ if (flingVelocity && !dispatchNestedPreFling(0, -initialVelocity)) {
dispatchNestedFling(0, -initialVelocity, false);
}
}
@@ -4001,14 +4001,15 @@
* <p>Applications can use this method to manually initiate a fling as if the user
* initiated it via touch interaction.</p>
*
- * @param velocityY Vertical velocity in pixels per second
+ * @param velocityY Vertical velocity in pixels per second. Note that this is velocity of
+ * content, not velocity of a touch that initiated the fling.
*/
public void fling(int velocityY) {
if (mFlingRunnable == null) {
mFlingRunnable = new FlingRunnable();
}
reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
- mFlingRunnable.start(-velocityY);
+ mFlingRunnable.start(velocityY);
}
@Override
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index 6ca4a9e..7198e52 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -611,6 +611,7 @@
mMenu = new MenuBuilder(context);
mMenu.setCallback(new MenuBuilderCallback());
mPresenter = new ActionMenuPresenter(context);
+ mPresenter.setReserveOverflow(true);
mPresenter.setCallback(mActionMenuPresenterCallback != null
? mActionMenuPresenterCallback : new ActionMenuPresenterCallback());
mMenu.addMenuPresenter(mPresenter, mPopupContext);
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 2729bd0..d77f0b2 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -125,6 +125,7 @@
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker,
defStyleAttr, defStyleRes);
final int mode = a.getInt(R.styleable.DatePicker_datePickerMode, MODE_SPINNER);
+ final int firstDayOfWeek = a.getInt(R.styleable.DatePicker_firstDayOfWeek, 0);
a.recycle();
switch (mode) {
@@ -136,6 +137,10 @@
mDelegate = createSpinnerUIDelegate(context, attrs, defStyleAttr, defStyleRes);
break;
}
+
+ if (firstDayOfWeek != 0) {
+ setFirstDayOfWeek(firstDayOfWeek);
+ }
}
private DatePickerDelegate createSpinnerUIDelegate(Context context, AttributeSet attrs,
@@ -300,6 +305,47 @@
}
/**
+ * Sets the first day of week.
+ *
+ * @param firstDayOfWeek The first day of the week conforming to the
+ * {@link CalendarView} APIs.
+ * @see Calendar#SUNDAY
+ * @see Calendar#MONDAY
+ * @see Calendar#TUESDAY
+ * @see Calendar#WEDNESDAY
+ * @see Calendar#THURSDAY
+ * @see Calendar#FRIDAY
+ * @see Calendar#SATURDAY
+ *
+ * @attr ref android.R.styleable#DatePicker_firstDayOfWeek
+ */
+ public void setFirstDayOfWeek(int firstDayOfWeek) {
+ if (firstDayOfWeek < Calendar.SUNDAY || firstDayOfWeek > Calendar.SATURDAY) {
+ throw new IllegalArgumentException("firstDayOfWeek must be between 1 and 7");
+ }
+ mDelegate.setFirstDayOfWeek(firstDayOfWeek);
+ }
+
+ /**
+ * Gets the first day of week.
+ *
+ * @return The first day of the week conforming to the {@link CalendarView}
+ * APIs.
+ * @see Calendar#SUNDAY
+ * @see Calendar#MONDAY
+ * @see Calendar#TUESDAY
+ * @see Calendar#WEDNESDAY
+ * @see Calendar#THURSDAY
+ * @see Calendar#FRIDAY
+ * @see Calendar#SATURDAY
+ *
+ * @attr ref android.R.styleable#DatePicker_firstDayOfWeek
+ */
+ public int getFirstDayOfWeek() {
+ return mDelegate.getFirstDayOfWeek();
+ }
+
+ /**
* Gets whether the {@link CalendarView} is shown.
*
* @return True if the calendar view is shown.
@@ -315,7 +361,7 @@
* @return The calendar view.
* @see #getCalendarViewShown()
*/
- public CalendarView getCalendarView () {
+ public CalendarView getCalendarView() {
return mDelegate.getCalendarView();
}
@@ -382,6 +428,9 @@
int getMonth();
int getDayOfMonth();
+ void setFirstDayOfWeek(int firstDayOfWeek);
+ int getFirstDayOfWeek();
+
void setMinDate(long minDate);
Calendar getMinDate();
@@ -699,6 +748,16 @@
}
@Override
+ public void setFirstDayOfWeek(int firstDayOfWeek) {
+ mCalendarView.setFirstDayOfWeek(firstDayOfWeek);
+ }
+
+ @Override
+ public int getFirstDayOfWeek() {
+ return mCalendarView.getFirstDayOfWeek();
+ }
+
+ @Override
public void setMinDate(long minDate) {
mTempDate.setTimeInMillis(minDate);
if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index eed49bf..b962962 100644
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -49,6 +49,7 @@
*/
class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate implements
View.OnClickListener, DatePickerController {
+ private static final int USE_LOCALE = 0;
private static final int UNINITIALIZED = -1;
private static final int MONTH_AND_DAY_VIEW = 0;
@@ -99,6 +100,8 @@
private Calendar mMinDate;
private Calendar mMaxDate;
+ private int mFirstDayOfWeek = USE_LOCALE;
+
private HashSet<OnDateChangedListener> mListeners = new HashSet<OnDateChangedListener>();
public DatePickerCalendarDelegate(DatePicker delegator, Context context, AttributeSet attrs,
@@ -438,7 +441,15 @@
}
@Override
+ public void setFirstDayOfWeek(int firstDayOfWeek) {
+ mFirstDayOfWeek = firstDayOfWeek;
+ }
+
+ @Override
public int getFirstDayOfWeek() {
+ if (mFirstDayOfWeek != USE_LOCALE) {
+ return mFirstDayOfWeek;
+ }
return mCurrentDate.getFirstDayOfWeek();
}
diff --git a/core/java/android/widget/DatePickerController.java b/core/java/android/widget/DatePickerController.java
index 6a074da..059709d 100644
--- a/core/java/android/widget/DatePickerController.java
+++ b/core/java/android/widget/DatePickerController.java
@@ -35,6 +35,7 @@
Calendar getSelectedDay();
+ void setFirstDayOfWeek(int firstDayOfWeek);
int getFirstDayOfWeek();
int getMinYear();
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 22138d0..128a06c 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1860,9 +1860,8 @@
}
final int originalLength = mTextView.getText().length();
- long minMax = mTextView.prepareSpacesAroundPaste(offset, offset, content);
- int min = TextUtils.unpackRangeStartFromLong(minMax);
- int max = TextUtils.unpackRangeEndFromLong(minMax);
+ int min = offset;
+ int max = offset;
Selection.setSelection((Spannable) mTextView.getText(), max);
mTextView.replaceText_internal(min, max, content);
@@ -3060,47 +3059,69 @@
final CharSequence composingText = text.subSequence(composingTextStart,
composingTextEnd);
builder.setComposingText(composingTextStart, composingText);
- }
- // TODO: Optimize this loop by caching the result.
- for (int offset = composingTextStart; offset < composingTextEnd; offset++) {
- if (offset < 0) {
- continue;
+
+ final int minLine = layout.getLineForOffset(composingTextStart);
+ final int maxLine = layout.getLineForOffset(composingTextEnd - 1);
+ for (int line = minLine; line <= maxLine; ++line) {
+ final int lineStart = layout.getLineStart(line);
+ final int lineEnd = layout.getLineEnd(line);
+ final int offsetStart = Math.max(lineStart, composingTextStart);
+ final int offsetEnd = Math.min(lineEnd, composingTextEnd);
+ final boolean ltrLine =
+ layout.getParagraphDirection(line) == Layout.DIR_LEFT_TO_RIGHT;
+ final float[] widths = new float[offsetEnd - offsetStart];
+ layout.getPaint().getTextWidths(text, offsetStart, offsetEnd, widths);
+ final float top = layout.getLineTop(line);
+ final float bottom = layout.getLineBottom(line);
+ for (int offset = offsetStart; offset < offsetEnd; ++offset) {
+ final float charWidth = widths[offset - offsetStart];
+ final boolean isRtl = layout.isRtlCharAt(offset);
+ final float primary = layout.getPrimaryHorizontal(offset);
+ final float secondary = layout.getSecondaryHorizontal(offset);
+ // TODO: This doesn't work perfectly for text with custom styles and
+ // TAB chars.
+ final float left;
+ final float right;
+ if (ltrLine) {
+ if (isRtl) {
+ left = secondary - charWidth;
+ right = secondary;
+ } else {
+ left = primary;
+ right = primary + charWidth;
+ }
+ } else {
+ if (!isRtl) {
+ left = secondary;
+ right = secondary + charWidth;
+ } else {
+ left = primary - charWidth;
+ right = primary;
+ }
+ }
+ // TODO: Check top-right and bottom-left as well.
+ final float localLeft = left + viewportToContentHorizontalOffset;
+ final float localRight = right + viewportToContentHorizontalOffset;
+ final float localTop = top + viewportToContentVerticalOffset;
+ final float localBottom = bottom + viewportToContentVerticalOffset;
+ final boolean isTopLeftVisible = isPositionVisible(localLeft, localTop);
+ final boolean isBottomRightVisible =
+ isPositionVisible(localRight, localBottom);
+ int characterBoundsFlags = 0;
+ if (isTopLeftVisible || isBottomRightVisible) {
+ characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
+ }
+ if (!isTopLeftVisible || !isTopLeftVisible) {
+ characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
+ }
+ if (isRtl) {
+ characterBoundsFlags |= CursorAnchorInfo.FLAG_IS_RTL;
+ }
+ // Here offset is the index in Java chars.
+ builder.addCharacterBounds(offset, localLeft, localTop, localRight,
+ localBottom, characterBoundsFlags);
+ }
}
- final boolean isRtl = layout.isRtlCharAt(offset);
- final int line = layout.getLineForOffset(offset);
- final int nextCharIndex = offset + 1;
- final float localLeadingEdgeX = layout.getPrimaryHorizontal(offset);
- final float localTrailingEdgeX;
- if (nextCharIndex != layout.getLineEnd(line)) {
- localTrailingEdgeX = layout.getPrimaryHorizontal(nextCharIndex);
- } else if (isRtl) {
- localTrailingEdgeX = layout.getLineLeft(line);
- } else {
- localTrailingEdgeX = layout.getLineRight(line);
- }
- final float leadingEdgeX = localLeadingEdgeX
- + viewportToContentHorizontalOffset;
- final float trailingEdgeX = localTrailingEdgeX
- + viewportToContentHorizontalOffset;
- final float top = layout.getLineTop(line) + viewportToContentVerticalOffset;
- final float bottom = layout.getLineBottom(line)
- + viewportToContentVerticalOffset;
- // TODO: Check right-top and left-bottom as well.
- final boolean isLeadingEdgeTopVisible = isPositionVisible(leadingEdgeX, top);
- final boolean isTrailingEdgeBottomVisible =
- isPositionVisible(trailingEdgeX, bottom);
- int characterRectFlags = 0;
- if (isLeadingEdgeTopVisible || isTrailingEdgeBottomVisible) {
- characterRectFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
- }
- if (!isLeadingEdgeTopVisible || !isTrailingEdgeBottomVisible) {
- characterRectFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
- }
- // Here offset is the index in Java chars.
- // TODO: We must have a well-defined specification. For example, how
- // surrogate pairs and composition letters are handled must be documented.
- builder.addCharacterRect(offset, leadingEdgeX, top, trailingEdgeX, bottom,
- characterRectFlags);
}
}
@@ -3127,6 +3148,9 @@
if (!isTopVisible || !isBottomVisible) {
insertionMarkerFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
}
+ if (layout.isRtlCharAt(offset)) {
+ insertionMarkerFlags |= CursorAnchorInfo.FLAG_IS_RTL;
+ }
builder.setInsertionMarkerLocation(insertionMarkerX, insertionMarkerTop,
insertionMarkerBaseline, insertionMarkerBottom, insertionMarkerFlags);
}
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index d263625..efd6fc0 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -2356,7 +2356,7 @@
final int rowsCount = getCount() / columnsCount;
final int selectionMode = getSelectionModeForAccessibility();
final CollectionInfo collectionInfo = CollectionInfo.obtain(
- columnsCount, rowsCount, false, selectionMode);
+ rowsCount, columnsCount, false, selectionMode);
info.setCollectionInfo(collectionInfo);
}
@@ -2385,7 +2385,7 @@
final boolean isHeading = lp != null && lp.viewType != ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
final boolean isSelected = isItemChecked(position);
final CollectionItemInfo itemInfo = CollectionItemInfo.obtain(
- column, 1, row, 1, isHeading, isSelected);
+ row, 1, column, 1, isHeading, isSelected);
info.setCollectionItemInfo(itemInfo);
}
}
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 1368cd3..2e9858c 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3882,9 +3882,10 @@
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(ListView.class.getName());
- final int count = getCount();
+ final int rowsCount = getCount();
final int selectionMode = getSelectionModeForAccessibility();
- final CollectionInfo collectionInfo = CollectionInfo.obtain(1, count, false, selectionMode);
+ final CollectionInfo collectionInfo = CollectionInfo.obtain(
+ rowsCount, 1, false, selectionMode);
info.setCollectionInfo(collectionInfo);
}
@@ -3897,7 +3898,7 @@
final boolean isHeading = lp != null && lp.viewType != ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
final boolean isSelected = isItemChecked(position);
final CollectionItemInfo itemInfo = CollectionItemInfo.obtain(
- 0, 1, position, 1, isHeading, isSelected);
+ position, 1, 0, 1, isHeading, isSelected);
info.setCollectionItemInfo(itemInfo);
}
}
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 0289ccc..dfdf606 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -262,7 +262,7 @@
attrs, R.styleable.SearchView, defStyleAttr, defStyleRes);
final LayoutInflater inflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
- final int layoutResId = a.getResourceId(R.styleable.SearchView_layout, 0);
+ final int layoutResId = a.getResourceId(R.styleable.SearchView_layout, R.layout.search_view);
inflater.inflate(layoutResId, this, true);
mQueryTextView = (SearchAutoComplete) findViewById(R.id.search_src_text);
@@ -288,7 +288,8 @@
mSearchHintIcon.setImageDrawable(a.getDrawable(R.styleable.SearchView_searchIcon));
// Extract dropdown layout resource IDs for later use.
- mSuggestionRowLayout = a.getResourceId(R.styleable.SearchView_suggestionRowLayout, 0);
+ mSuggestionRowLayout = a.getResourceId(R.styleable.SearchView_suggestionRowLayout,
+ R.layout.search_dropdown_item_icons_2line);
mSuggestionCommitIconResId = a.getResourceId(R.styleable.SearchView_commitIcon, 0);
mSearchButton.setOnClickListener(mOnClickListener);
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index 27763eb..a76241e 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -31,6 +31,7 @@
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.AttributeSet;
+import android.util.MathUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
@@ -300,7 +301,11 @@
}
private static boolean isValidDayOfWeek(int day) {
- return (day >= Time.SUNDAY && day <= Time.SATURDAY);
+ return day >= Calendar.SUNDAY && day <= Calendar.SATURDAY;
+ }
+
+ private static boolean isValidMonth(int month) {
+ return month >= Calendar.JANUARY && month <= Calendar.DECEMBER;
}
/**
@@ -312,8 +317,8 @@
* @param selectedDay the selected day of the month, or -1 for no selection.
* @param month the month.
* @param year the year.
- * @param weekStart which day the week should start on. {@link Time#SUNDAY} through
- * {@link Time#SATURDAY}.
+ * @param weekStart which day the week should start on. {@link Calendar#SUNDAY} through
+ * {@link Calendar#SATURDAY}.
* @param enabledDayStart the first enabled day.
* @param enabledDayEnd the last enabled day.
*/
@@ -325,7 +330,7 @@
mSelectedDay = selectedDay;
- if (month >= Calendar.JANUARY && month <= Calendar.DECEMBER) {
+ if (isValidMonth(month)) {
mMonth = month;
}
mYear = year;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3e1b674..a81ff97 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -17,6 +17,7 @@
package android.widget;
import android.R;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ClipData;
import android.content.ClipboardManager;
@@ -1976,23 +1977,34 @@
}
/**
- * Sets the Drawables (if any) to appear to the left of, above,
- * to the right of, and below the text. Use null if you do not
- * want a Drawable there. The Drawables must already have had
+ * Sets the Drawables (if any) to appear to the left of, above, to the
+ * right of, and below the text. Use {@code null} if you do not want a
+ * Drawable there. The Drawables must already have had
* {@link Drawable#setBounds} called.
+ * <p>
+ * Calling this method will overwrite any Drawables previously set using
+ * {@link #setCompoundDrawablesRelative} or related methods.
*
* @attr ref android.R.styleable#TextView_drawableLeft
* @attr ref android.R.styleable#TextView_drawableTop
* @attr ref android.R.styleable#TextView_drawableRight
* @attr ref android.R.styleable#TextView_drawableBottom
*/
- public void setCompoundDrawables(Drawable left, Drawable top,
- Drawable right, Drawable bottom) {
+ public void setCompoundDrawables(@Nullable Drawable left, @Nullable Drawable top,
+ @Nullable Drawable right, @Nullable Drawable bottom) {
Drawables dr = mDrawables;
- final boolean drawables = left != null || top != null
- || right != null || bottom != null;
+ // We're switching to absolute, discard relative.
+ if (dr != null) {
+ if (dr.mDrawableStart != null) dr.mDrawableStart.setCallback(null);
+ dr.mDrawableStart = null;
+ if (dr.mDrawableEnd != null) dr.mDrawableEnd.setCallback(null);
+ dr.mDrawableEnd = null;
+ dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0;
+ dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0;
+ }
+ final boolean drawables = left != null || top != null || right != null || bottom != null;
if (!drawables) {
// Clearing drawables... can we free the data structure?
if (dr != null) {
@@ -2101,10 +2113,12 @@
}
/**
- * Sets the Drawables (if any) to appear to the left of, above,
- * to the right of, and below the text. Use 0 if you do not
- * want a Drawable there. The Drawables' bounds will be set to
- * their intrinsic bounds.
+ * Sets the Drawables (if any) to appear to the left of, above, to the
+ * right of, and below the text. Use 0 if you do not want a Drawable there.
+ * The Drawables' bounds will be set to their intrinsic bounds.
+ * <p>
+ * Calling this method will overwrite any Drawables previously set using
+ * {@link #setCompoundDrawablesRelative} or related methods.
*
* @param left Resource identifier of the left Drawable.
* @param top Resource identifier of the top Drawable.
@@ -2126,18 +2140,21 @@
}
/**
- * Sets the Drawables (if any) to appear to the left of, above,
- * to the right of, and below the text. Use null if you do not
- * want a Drawable there. The Drawables' bounds will be set to
- * their intrinsic bounds.
+ * Sets the Drawables (if any) to appear to the left of, above, to the
+ * right of, and below the text. Use {@code null} if you do not want a
+ * Drawable there. The Drawables' bounds will be set to their intrinsic
+ * bounds.
+ * <p>
+ * Calling this method will overwrite any Drawables previously set using
+ * {@link #setCompoundDrawablesRelative} or related methods.
*
* @attr ref android.R.styleable#TextView_drawableLeft
* @attr ref android.R.styleable#TextView_drawableTop
* @attr ref android.R.styleable#TextView_drawableRight
* @attr ref android.R.styleable#TextView_drawableBottom
*/
- public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top,
- Drawable right, Drawable bottom) {
+ public void setCompoundDrawablesWithIntrinsicBounds(@Nullable Drawable left,
+ @Nullable Drawable top, @Nullable Drawable right, @Nullable Drawable bottom) {
if (left != null) {
left.setBounds(0, 0, left.getIntrinsicWidth(), left.getIntrinsicHeight());
@@ -2155,20 +2172,33 @@
}
/**
- * Sets the Drawables (if any) to appear to the start of, above,
- * to the end of, and below the text. Use null if you do not
- * want a Drawable there. The Drawables must already have had
- * {@link Drawable#setBounds} called.
+ * Sets the Drawables (if any) to appear to the start of, above, to the end
+ * of, and below the text. Use {@code null} if you do not want a Drawable
+ * there. The Drawables must already have had {@link Drawable#setBounds}
+ * called.
+ * <p>
+ * Calling this method will overwrite any Drawables previously set using
+ * {@link #setCompoundDrawables} or related methods.
*
* @attr ref android.R.styleable#TextView_drawableStart
* @attr ref android.R.styleable#TextView_drawableTop
* @attr ref android.R.styleable#TextView_drawableEnd
* @attr ref android.R.styleable#TextView_drawableBottom
*/
- public void setCompoundDrawablesRelative(Drawable start, Drawable top,
- Drawable end, Drawable bottom) {
+ public void setCompoundDrawablesRelative(@Nullable Drawable start, @Nullable Drawable top,
+ @Nullable Drawable end, @Nullable Drawable bottom) {
Drawables dr = mDrawables;
+ // We're switching to relative, discard absolute.
+ if (dr != null) {
+ if (dr.mDrawableLeft != null) dr.mDrawableLeft.setCallback(null);
+ dr.mDrawableLeft = dr.mDrawableLeftInitial = null;
+ if (dr.mDrawableRight != null) dr.mDrawableRight.setCallback(null);
+ dr.mDrawableRight = dr.mDrawableRightInitial = null;
+ dr.mDrawableSizeLeft = dr.mDrawableHeightLeft = 0;
+ dr.mDrawableSizeRight = dr.mDrawableHeightRight = 0;
+ }
+
final boolean drawables = start != null || top != null
|| end != null || bottom != null;
@@ -2274,10 +2304,12 @@
}
/**
- * Sets the Drawables (if any) to appear to the start of, above,
- * to the end of, and below the text. Use 0 if you do not
- * want a Drawable there. The Drawables' bounds will be set to
- * their intrinsic bounds.
+ * Sets the Drawables (if any) to appear to the start of, above, to the end
+ * of, and below the text. Use 0 if you do not want a Drawable there. The
+ * Drawables' bounds will be set to their intrinsic bounds.
+ * <p>
+ * Calling this method will overwrite any Drawables previously set using
+ * {@link #setCompoundDrawables} or related methods.
*
* @param start Resource identifier of the start Drawable.
* @param top Resource identifier of the top Drawable.
@@ -2301,18 +2333,20 @@
}
/**
- * Sets the Drawables (if any) to appear to the start of, above,
- * to the end of, and below the text. Use null if you do not
- * want a Drawable there. The Drawables' bounds will be set to
- * their intrinsic bounds.
+ * Sets the Drawables (if any) to appear to the start of, above, to the end
+ * of, and below the text. Use {@code null} if you do not want a Drawable
+ * there. The Drawables' bounds will be set to their intrinsic bounds.
+ * <p>
+ * Calling this method will overwrite any Drawables previously set using
+ * {@link #setCompoundDrawables} or related methods.
*
* @attr ref android.R.styleable#TextView_drawableStart
* @attr ref android.R.styleable#TextView_drawableTop
* @attr ref android.R.styleable#TextView_drawableEnd
* @attr ref android.R.styleable#TextView_drawableBottom
*/
- public void setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top,
- Drawable end, Drawable bottom) {
+ public void setCompoundDrawablesRelativeWithIntrinsicBounds(@Nullable Drawable start,
+ @Nullable Drawable top, @Nullable Drawable end, @Nullable Drawable bottom) {
if (start != null) {
start.setBounds(0, 0, start.getIntrinsicWidth(), start.getIntrinsicHeight());
@@ -2337,6 +2371,7 @@
* @attr ref android.R.styleable#TextView_drawableRight
* @attr ref android.R.styleable#TextView_drawableBottom
*/
+ @NonNull
public Drawable[] getCompoundDrawables() {
final Drawables dr = mDrawables;
if (dr != null) {
@@ -2356,6 +2391,7 @@
* @attr ref android.R.styleable#TextView_drawableEnd
* @attr ref android.R.styleable#TextView_drawableBottom
*/
+ @NonNull
public Drawable[] getCompoundDrawablesRelative() {
final Drawables dr = mDrawables;
if (dr != null) {
@@ -8423,6 +8459,33 @@
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
switch (action) {
+ case AccessibilityNodeInfo.ACTION_CLICK: {
+ boolean handled = false;
+
+ // Simulate View.onTouchEvent for an ACTION_UP event.
+ if (isClickable() || isLongClickable()) {
+ if (isFocusable() && !isFocused()) {
+ requestFocus();
+ }
+
+ performClick();
+ handled = true;
+ }
+
+ // Simulate TextView.onTouchEvent for an ACTION_UP event.
+ if ((mMovement != null || onCheckIsTextEditor()) && isEnabled()
+ && mText instanceof Spannable && mLayout != null
+ && (isTextEditable() || isTextSelectable()) && isFocused()) {
+ // Show the IME, except when selecting in read-only text.
+ final InputMethodManager imm = InputMethodManager.peekInstance();
+ viewClicked(imm);
+ if (!isTextSelectable() && mEditor.mShowSoftInputOnFocus && imm != null) {
+ handled |= imm.showSoftInput(this, 0);
+ }
+ }
+
+ return handled;
+ }
case AccessibilityNodeInfo.ACTION_COPY: {
if (isFocused() && canCopy()) {
if (onTextContextMenuItem(ID_COPY)) {
@@ -8727,57 +8790,6 @@
}
/**
- * Prepare text so that there are not zero or two spaces at beginning and end of region defined
- * by [min, max] when replacing this region by paste.
- * Note that if there were two spaces (or more) at that position before, they are kept. We just
- * make sure we do not add an extra one from the paste content.
- */
- long prepareSpacesAroundPaste(int min, int max, CharSequence paste) {
- if (paste.length() > 0) {
- if (min > 0) {
- final char charBefore = mTransformed.charAt(min - 1);
- final char charAfter = paste.charAt(0);
-
- if (Character.isSpaceChar(charBefore) && Character.isSpaceChar(charAfter)) {
- // Two spaces at beginning of paste: remove one
- final int originalLength = mText.length();
- deleteText_internal(min - 1, min);
- // Due to filters, there is no guarantee that exactly one character was
- // removed: count instead.
- final int delta = mText.length() - originalLength;
- min += delta;
- max += delta;
- } else if (!Character.isSpaceChar(charBefore) && charBefore != '\n' &&
- !Character.isSpaceChar(charAfter) && charAfter != '\n') {
- // No space at beginning of paste: add one
- final int originalLength = mText.length();
- replaceText_internal(min, min, " ");
- // Taking possible filters into account as above.
- final int delta = mText.length() - originalLength;
- min += delta;
- max += delta;
- }
- }
-
- if (max < mText.length()) {
- final char charBefore = paste.charAt(paste.length() - 1);
- final char charAfter = mTransformed.charAt(max);
-
- if (Character.isSpaceChar(charBefore) && Character.isSpaceChar(charAfter)) {
- // Two spaces at end of paste: remove one
- deleteText_internal(max, max + 1);
- } else if (!Character.isSpaceChar(charBefore) && charBefore != '\n' &&
- !Character.isSpaceChar(charAfter) && charAfter != '\n') {
- // No space at end of paste: add one
- replaceText_internal(max, max, " ");
- }
- }
- }
-
- return TextUtils.packRangeInLong(min, max);
- }
-
- /**
* Paste clipboard content between min and max positions.
*/
private void paste(int min, int max) {
@@ -8790,9 +8802,6 @@
CharSequence paste = clip.getItemAt(i).coerceToStyledText(getContext());
if (paste != null) {
if (!didFirst) {
- long minMax = prepareSpacesAroundPaste(min, max, paste);
- min = TextUtils.unpackRangeStartFromLong(minMax);
- max = TextUtils.unpackRangeEndFromLong(minMax);
Selection.setSelection((Spannable) mText, max);
((Editable) mText).replace(min, max, paste);
didFirst = true;
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index b6e7353..107e8c6 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -90,7 +90,7 @@
private boolean mSafeForwardingMode;
private boolean mAlwaysUseOption;
private boolean mShowExtended;
- private GridView mGridView;
+ private ListView mListView;
private Button mAlwaysButton;
private Button mOnceButton;
private int mIconDpi;
@@ -228,10 +228,13 @@
mLaunchedFromUid, alwaysUseOption);
final int layoutId;
+ final boolean useHeader;
if (mAdapter.hasFilteredItem()) {
layoutId = R.layout.resolver_list_with_default;
alwaysUseOption = false;
+ useHeader = true;
} else {
+ useHeader = false;
layoutId = R.layout.resolver_list;
}
mAlwaysUseOption = alwaysUseOption;
@@ -243,16 +246,19 @@
return;
} else if (count > 1) {
setContentView(layoutId);
- mGridView = (GridView) findViewById(R.id.resolver_list);
- mGridView.setAdapter(mAdapter);
- mGridView.setOnItemClickListener(this);
- mGridView.setOnItemLongClickListener(new ItemLongClickListener());
+ mListView = (ListView) findViewById(R.id.resolver_list);
+ mListView.setAdapter(mAdapter);
+ mListView.setOnItemClickListener(this);
+ mListView.setOnItemLongClickListener(new ItemLongClickListener());
if (alwaysUseOption) {
- mGridView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
}
- resizeGrid();
+ if (useHeader) {
+ mListView.addHeaderView(LayoutInflater.from(this).inflate(
+ R.layout.resolver_different_item_header, mListView, false));
+ }
} else if (count == 1) {
safelyStartActivity(mAdapter.intentForPosition(0, false));
mPackageMonitor.unregister();
@@ -265,8 +271,8 @@
final TextView empty = (TextView) findViewById(R.id.empty);
empty.setVisibility(View.VISIBLE);
- mGridView = (GridView) findViewById(R.id.resolver_list);
- mGridView.setVisibility(View.GONE);
+ mListView = (ListView) findViewById(R.id.resolver_list);
+ mListView.setVisibility(View.GONE);
}
final ResolverDrawerLayout rdl = (ResolverDrawerLayout) findViewById(R.id.contentPanel);
@@ -340,11 +346,6 @@
}
}
- void resizeGrid() {
- final int itemCount = mAdapter.getCount();
- mGridView.setNumColumns(Math.min(itemCount, mMaxColumns));
- }
-
void dismiss() {
if (!isFinishing()) {
finish();
@@ -419,19 +420,24 @@
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (mAlwaysUseOption) {
- final int checkedPos = mGridView.getCheckedItemPosition();
+ final int checkedPos = mListView.getCheckedItemPosition();
final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
mLastSelected = checkedPos;
setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
mOnceButton.setEnabled(hasValidSelection);
if (hasValidSelection) {
- mGridView.setSelection(checkedPos);
+ mListView.setSelection(checkedPos);
}
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ position -= mListView.getHeaderViewsCount();
+ if (position < 0) {
+ // Header views don't count.
+ return;
+ }
ResolveInfo resolveInfo = mAdapter.resolveInfoForPosition(position, true);
if (mResolvingHome && hasManagedProfile()
&& !supportsManagedProfiles(resolveInfo)) {
@@ -441,13 +447,13 @@
Toast.LENGTH_LONG).show();
return;
}
- final int checkedPos = mGridView.getCheckedItemPosition();
+ final int checkedPos = mListView.getCheckedItemPosition();
final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
if (mAlwaysUseOption && (!hasValidSelection || mLastSelected != checkedPos)) {
setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
mOnceButton.setEnabled(hasValidSelection);
if (hasValidSelection) {
- mGridView.smoothScrollToPosition(checkedPos);
+ mListView.smoothScrollToPosition(checkedPos);
}
mLastSelected = checkedPos;
} else {
@@ -504,7 +510,7 @@
public void onButtonClick(View v) {
final int id = v.getId();
startSelected(mAlwaysUseOption ?
- mGridView.getCheckedItemPosition() : mAdapter.getFilteredPosition(),
+ mListView.getCheckedItemPosition() : mAdapter.getFilteredPosition(),
id == R.id.button_always,
mAlwaysUseOption);
dismiss();
@@ -714,8 +720,6 @@
if (newItemCount == 0) {
// We no longer have any items... just finish the activity.
finish();
- } else if (newItemCount != oldItemCount) {
- resizeGrid();
}
}
@@ -957,19 +961,13 @@
}
public View getView(int position, View convertView, ViewGroup parent) {
- View view;
- if (convertView == null) {
+ View view = convertView;
+ if (view == null) {
view = mInflater.inflate(
com.android.internal.R.layout.resolve_list_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
view.setTag(holder);
-
- // Fix the icon size even if we have different sized resources
- ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
- lp.width = lp.height = mIconSize;
- } else {
- view = convertView;
}
bindView(view, getItem(position));
return view;
@@ -1007,6 +1005,11 @@
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
+ position -= mListView.getHeaderViewsCount();
+ if (position < 0) {
+ // Header views don't count.
+ return false;
+ }
ResolveInfo ri = mAdapter.resolveInfoForPosition(position, true);
showAppDetails(ri);
return true;
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index c17f4ee..7bdb4be 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -390,7 +390,10 @@
if (!emulated && (checkBoth || prefer == RECOMMEND_INSTALL_EXTERNAL)) {
final File target = new UserEnvironment(UserHandle.USER_OWNER)
.getExternalStorageDirectory();
- fitsOnExternal = (sizeBytes <= storage.getStorageBytesUntilLow(target));
+ // External is only an option when size is known
+ if (sizeBytes > 0) {
+ fitsOnExternal = (sizeBytes <= storage.getStorageBytesUntilLow(target));
+ }
}
if (prefer == RECOMMEND_INSTALL_INTERNAL) {
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index e58d68f..86f580d 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -64,7 +64,9 @@
/** Stores user time and system time in 100ths of a second. */
private final long[] mProcessStatsData = new long[4];
- /** Stores user time and system time in 100ths of a second. */
+
+ /** Stores user time and system time in 100ths of a second. Used for
+ * public API to retrieve CPU use for a process. Must lock while in use. */
private final long[] mSinglePidStatsData = new long[4];
private static final int[] PROCESS_FULL_STATS_FORMAT = new int[] {
@@ -533,18 +535,20 @@
/**
* Returns the total time (in clock ticks, or 1/100 sec) spent executing in
- * both user and system code.
+ * both user and system code. Safe to call without lock held.
*/
public long getCpuTimeForPid(int pid) {
- final String statFile = "/proc/" + pid + "/stat";
- final long[] statsData = mSinglePidStatsData;
- if (Process.readProcFile(statFile, PROCESS_STATS_FORMAT,
- null, statsData, null)) {
- long time = statsData[PROCESS_STAT_UTIME]
- + statsData[PROCESS_STAT_STIME];
- return time;
+ synchronized (mSinglePidStatsData) {
+ final String statFile = "/proc/" + pid + "/stat";
+ final long[] statsData = mSinglePidStatsData;
+ if (Process.readProcFile(statFile, PROCESS_STATS_FORMAT,
+ null, statsData, null)) {
+ long time = statsData[PROCESS_STAT_UTIME]
+ + statsData[PROCESS_STAT_STIME];
+ return time;
+ }
+ return 0;
}
- return 0;
}
/**
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index c5211bb..c579a15 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -78,17 +78,20 @@
* file descriptor numbers that are to be closed by the child
* (and replaced by /dev/null) after forking. An integer value
* of -1 in any entry in the array means "ignore this one".
+ * @param instructionSet null-ok the instruction set to use.
*
* @return 0 if this is the child, pid of the child
* if this is the parent, or -1 on error.
*/
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
- int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose) {
+ int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
+ String instructionSet) {
long startTime = SystemClock.elapsedRealtime();
VM_HOOKS.preFork();
checkTime(startTime, "Zygote.preFork");
int pid = nativeForkAndSpecialize(
- uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose);
+ uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
+ instructionSet);
checkTime(startTime, "Zygote.nativeForkAndSpecialize");
VM_HOOKS.postForkCommon();
checkTime(startTime, "Zygote.postForkCommon");
@@ -96,7 +99,8 @@
}
native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,
- int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose);
+ int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
+ String instructionSet);
/**
* Temporary hack: check time since start time and log if over a fixed threshold.
@@ -145,9 +149,9 @@
native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
- private static void callPostForkChildHooks(int debugFlags) {
+ private static void callPostForkChildHooks(int debugFlags, String instructionSet) {
long startTime = SystemClock.elapsedRealtime();
- VM_HOOKS.postForkChild(debugFlags);
+ VM_HOOKS.postForkChild(debugFlags, instructionSet);
checkTime(startTime, "Zygote.callPostForkChildHooks");
}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index b4c4da6..fb50b25 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -245,7 +245,7 @@
checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize");
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
- parsedArgs.niceName, fdsToClose);
+ parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet);
checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize");
} catch (IOException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
@@ -335,6 +335,7 @@
* [--] <args for RuntimeInit >
* <li> If <code>--runtime-init</code> is absent:
* [--] <classname> [args...]
+ * <li> --instruction-set=<i>instruction-set-string</i> which instruction set to use/emulate.
* </ul>
*/
static class Arguments {
@@ -398,6 +399,11 @@
boolean abiListQuery;
/**
+ * The instruction set to use, or null when not important.
+ */
+ String instructionSet;
+
+ /**
* Constructs instance and parses args
* @param args zygote command-line args
* @throws IllegalArgumentException
@@ -552,6 +558,8 @@
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
} else if (arg.equals("--query-abi-list")) {
abiListQuery = true;
+ } else if (arg.startsWith("--instruction-set=")) {
+ instructionSet = arg.substring(arg.indexOf('=') + 1);
} else {
break;
}
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 3ed4d51..8e786da 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -107,7 +107,7 @@
return (T[]) EmptyArray.OBJECT;
}
- int bucket = ((System.identityHashCode(kind) / 8) & 0x7FFFFFFF) % CACHE_SIZE;
+ int bucket = (kind.hashCode() & 0x7FFFFFFF) % CACHE_SIZE;
Object cache = sCache[bucket];
if (cache == null || cache.getClass().getComponentType() != kind) {
diff --git a/core/java/com/android/internal/util/ParcelableString.java b/core/java/com/android/internal/util/ParcelableString.java
new file mode 100644
index 0000000..6bd856f
--- /dev/null
+++ b/core/java/com/android/internal/util/ParcelableString.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 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.util;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Helper class to adapt a simple String to cases where a Parcelable is expected.
+ * @hide
+ */
+public class ParcelableString implements Parcelable {
+ public String string;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(string);
+ }
+
+ public static final Parcelable.Creator<ParcelableString> CREATOR =
+ new Parcelable.Creator<ParcelableString>() {
+ @Override
+ public ParcelableString createFromParcel(Parcel in) {
+ ParcelableString ret = new ParcelableString();
+ ret.string = in.readString();
+ return ret;
+ }
+ @Override
+ public ParcelableString[] newArray(int size) {
+ return new ParcelableString[size];
+ }
+ };
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index 7db70ba..45d790b 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -1440,6 +1440,16 @@
return Boolean.parseBoolean(value);
}
+ public static boolean readBooleanAttribute(XmlPullParser in, String name,
+ boolean defaultValue) {
+ final String value = in.getAttributeValue(null, name);
+ if (value == null) {
+ return defaultValue;
+ } else {
+ return Boolean.parseBoolean(value);
+ }
+ }
+
public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value)
throws IOException {
out.attribute(null, name, Boolean.toString(value));
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index e53f9dd..375822f 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -20,15 +20,15 @@
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
-import android.view.Gravity;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
-
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.view.animation.AnimationUtils;
@@ -68,6 +68,7 @@
private boolean mIsDragging;
private boolean mOpenOnClick;
+ private boolean mOpenOnLayout;
private final int mTouchSlop;
private final float mMinFlingVelocity;
private final OverScroller mScroller;
@@ -202,6 +203,8 @@
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getActionMasked();
+ mVelocityTracker.addMovement(ev);
+
boolean handled = false;
switch (action) {
case MotionEvent.ACTION_DOWN: {
@@ -288,6 +291,10 @@
break;
case MotionEvent.ACTION_CANCEL: {
+ if (mIsDragging) {
+ smoothScrollTo(
+ mCollapseOffset < mCollapsibleHeight / 2 ? 0 : mCollapsibleHeight, 0);
+ }
resetTouch();
return true;
}
@@ -498,28 +505,39 @@
@Override
public void onStopNestedScroll(View child) {
super.onStopNestedScroll(child);
- smoothScrollTo(mCollapseOffset < mCollapsibleHeight / 2 ? 0 : mCollapsibleHeight, 0);
+ if (mScroller.isFinished()) {
+ smoothScrollTo(mCollapseOffset < mCollapsibleHeight / 2 ? 0 : mCollapsibleHeight, 0);
+ }
}
@Override
public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
int dxUnconsumed, int dyUnconsumed) {
- if (dyUnconsumed > 0) {
+ if (dyUnconsumed < 0) {
performDrag(-dyUnconsumed);
}
}
@Override
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
- if (dy < 0) {
- consumed[1] = (int) performDrag(-dy);
+ if (dy > 0) {
+ consumed[1] = (int) -performDrag(-dy);
}
}
@Override
+ public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
+ if (velocityY > mMinFlingVelocity && mCollapseOffset != 0) {
+ smoothScrollTo(0, velocityY);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
if (!consumed && Math.abs(velocityY) > mMinFlingVelocity) {
- smoothScrollTo(velocityY < 0 ? 0 : mCollapsibleHeight, velocityY);
+ smoothScrollTo(velocityY > 0 ? 0 : mCollapsibleHeight, velocityY);
return true;
}
return false;
@@ -571,8 +589,8 @@
if (isLaidOut()) {
mCollapseOffset = Math.min(mCollapseOffset, mCollapsibleHeight);
} else {
- // Start out collapsed at first
- mCollapseOffset = mCollapsibleHeight;
+ // Start out collapsed at first unless we restored state for otherwise
+ mCollapseOffset = mOpenOnLayout ? 0 : mCollapsibleHeight;
}
mTopOffset = Math.max(0, heightSize - heightUsed) + (int) mCollapseOffset;
@@ -634,6 +652,20 @@
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ final SavedState ss = new SavedState(super.onSaveInstanceState());
+ ss.open = mCollapsibleHeight > 0 && mCollapseOffset == 0;
+ return ss;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ final SavedState ss = (SavedState) state;
+ super.onRestoreInstanceState(ss.getSuperState());
+ mOpenOnLayout = ss.open;
+ }
+
public static class LayoutParams extends MarginLayoutParams {
public boolean alwaysShow;
public boolean ignoreOffset;
@@ -670,4 +702,36 @@
super(source);
}
}
+
+ static class SavedState extends BaseSavedState {
+ boolean open;
+
+ SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ private SavedState(Parcel in) {
+ super(in);
+ open = in.readInt() != 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ super.writeToParcel(out, flags);
+ out.writeInt(open ? 1 : 0);
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+ @Override
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ @Override
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
}
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index 7249985..468d7f1 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -123,8 +123,15 @@
}
if (SystemProperties.getLong("ro.runtime.firstboot", 0) == 0) {
- String now = Long.toString(System.currentTimeMillis());
- SystemProperties.set("ro.runtime.firstboot", now);
+ if ("encrypted".equals(SystemProperties.get("ro.crypto.state"))
+ && "trigger_restart_min_framework".equals(SystemProperties.get("vold.decrypt"))){
+ // Encrypted, first boot to get PIN/pattern/password so data is tmpfs
+ // Don't set ro.runtime.firstboot so that we will do this again
+ // when data is properly mounted
+ } else {
+ String now = Long.toString(System.currentTimeMillis());
+ SystemProperties.set("ro.runtime.firstboot", now);
+ }
if (db != null) db.addText("SYSTEM_BOOT", headers);
// Negative sizes mean to take the *tail* of the file (see FileUtils.readTextFile())
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 2106d38..dbaa4b8 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -129,6 +129,7 @@
android/graphics/Xfermode.cpp \
android/graphics/YuvToJpegEncoder.cpp \
android/graphics/pdf/PdfDocument.cpp \
+ android/graphics/pdf/PdfEditor.cpp \
android/graphics/pdf/PdfRenderer.cpp \
android_media_AudioRecord.cpp \
android_media_AudioSystem.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 62d8036..a63258c 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -126,6 +126,7 @@
extern int register_android_graphics_SurfaceTexture(JNIEnv* env);
extern int register_android_graphics_Xfermode(JNIEnv* env);
extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env);
+extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env);
extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env);
extern int register_android_view_DisplayEventReceiver(JNIEnv* env);
extern int register_android_view_RenderNode(JNIEnv* env);
@@ -1305,6 +1306,7 @@
REG_JNI(register_android_graphics_Xfermode),
REG_JNI(register_android_graphics_YuvImage),
REG_JNI(register_android_graphics_pdf_PdfDocument),
+ REG_JNI(register_android_graphics_pdf_PdfEditor),
REG_JNI(register_android_graphics_pdf_PdfRenderer),
REG_JNI(register_android_database_CursorWindow),
diff --git a/core/jni/android/graphics/pdf/PdfEditor.cpp b/core/jni/android/graphics/pdf/PdfEditor.cpp
new file mode 100644
index 0000000..5f60c9e
--- /dev/null
+++ b/core/jni/android/graphics/pdf/PdfEditor.cpp
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "fpdfview.h"
+#include "fpdfedit.h"
+#include "fpdfsave.h"
+
+#include <android_runtime/AndroidRuntime.h>
+#include <vector>
+#include <utils/Log.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+namespace android {
+
+static Mutex sLock;
+
+static int sUnmatchedInitRequestCount = 0;
+
+static void initializeLibraryIfNeeded() {
+ Mutex::Autolock _l(sLock);
+ if (sUnmatchedInitRequestCount == 0) {
+ FPDF_InitLibrary(NULL);
+ }
+ sUnmatchedInitRequestCount++;
+}
+
+static void destroyLibraryIfNeeded() {
+ Mutex::Autolock _l(sLock);
+ sUnmatchedInitRequestCount--;
+ if (sUnmatchedInitRequestCount == 0) {
+ FPDF_DestroyLibrary();
+ }
+}
+
+static int getBlock(void* param, unsigned long position, unsigned char* outBuffer,
+ unsigned long size) {
+ const int fd = reinterpret_cast<intptr_t>(param);
+ const int readCount = pread(fd, outBuffer, size, position);
+ if (readCount < 0) {
+ ALOGE("Cannot read from file descriptor. Error:%d", errno);
+ return 0;
+ }
+ return 1;
+}
+
+static jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size) {
+ initializeLibraryIfNeeded();
+
+ FPDF_FILEACCESS loader;
+ loader.m_FileLen = size;
+ loader.m_Param = reinterpret_cast<void*>(intptr_t(fd));
+ loader.m_GetBlock = &getBlock;
+
+ FPDF_DOCUMENT document = FPDF_LoadCustomDocument(&loader, NULL);
+
+ if (!document) {
+ const long error = FPDF_GetLastError();
+ jniThrowException(env, "java/io/IOException",
+ "cannot create document. Error:" + error);
+ destroyLibraryIfNeeded();
+ return -1;
+ }
+
+ return reinterpret_cast<jlong>(document);
+}
+
+static void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr) {
+ FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
+ FPDF_CloseDocument(document);
+ destroyLibraryIfNeeded();
+}
+
+static jint nativeGetPageCount(JNIEnv* env, jclass thiz, jlong documentPtr) {
+ FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
+ return FPDF_GetPageCount(document);
+}
+
+static jint nativeRemovePage(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex) {
+ FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
+ FPDFPage_Delete(document, pageIndex);
+ return FPDF_GetPageCount(document);
+}
+
+struct PdfToFdWriter : FPDF_FILEWRITE {
+ int dstFd;
+};
+
+static bool writeAllBytes(const int fd, const void* buffer, const size_t byteCount) {
+ char* writeBuffer = static_cast<char*>(const_cast<void*>(buffer));
+ size_t remainingBytes = byteCount;
+ while (remainingBytes > 0) {
+ ssize_t writtenByteCount = write(fd, writeBuffer, remainingBytes);
+ if (writtenByteCount == -1) {
+ if (errno == EINTR) {
+ continue;
+ }
+ __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
+ "Error writing to buffer: %d", errno);
+ return false;
+ }
+ remainingBytes -= writtenByteCount;
+ writeBuffer += writtenByteCount;
+ }
+ return true;
+}
+
+static int writeBlock(FPDF_FILEWRITE* owner, const void* buffer, unsigned long size) {
+ const PdfToFdWriter* writer = reinterpret_cast<PdfToFdWriter*>(owner);
+ const bool success = writeAllBytes(writer->dstFd, buffer, size);
+ if (success < 0) {
+ ALOGE("Cannot write to file descriptor. Error:%d", errno);
+ return 0;
+ }
+ return 1;
+}
+
+static void nativeWrite(JNIEnv* env, jclass thiz, jlong documentPtr, jint fd) {
+ FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
+ PdfToFdWriter writer;
+ writer.dstFd = fd;
+ writer.WriteBlock = &writeBlock;
+ const bool success = FPDF_SaveAsCopy(document, &writer, FPDF_NO_INCREMENTAL);
+ if (!success) {
+ jniThrowException(env, "java/io/IOException",
+ "cannot write to fd. Error:" + errno);
+ destroyLibraryIfNeeded();
+ }
+}
+
+static JNINativeMethod gPdfEditor_Methods[] = {
+ {"nativeOpen", "(IJ)J", (void*) nativeOpen},
+ {"nativeClose", "(J)V", (void*) nativeClose},
+ {"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount},
+ {"nativeRemovePage", "(JI)I", (void*) nativeRemovePage},
+ {"nativeWrite", "(JI)V", (void*) nativeWrite}
+};
+
+int register_android_graphics_pdf_PdfEditor(JNIEnv* env) {
+ return android::AndroidRuntime::registerNativeMethods(
+ env, "android/graphics/pdf/PdfEditor", gPdfEditor_Methods,
+ NELEM(gPdfEditor_Methods));
+};
+
+};
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 8f30f5d..06c22ae 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -117,7 +117,8 @@
static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
- jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) {
+ jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform,
+ int rotation) {
sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
if (displayToken == NULL) {
return NULL;
@@ -131,17 +132,13 @@
SkAutoTDelete<ScreenshotClient> screenshot(new ScreenshotClient());
status_t res;
- if (width > 0 && height > 0) {
- if (allLayers) {
- res = screenshot->update(displayToken, sourceCrop, width, height,
- useIdentityTransform);
- } else {
- res = screenshot->update(displayToken, sourceCrop, width, height,
- minLayer, maxLayer, useIdentityTransform);
- }
- } else {
- res = screenshot->update(displayToken, sourceCrop, useIdentityTransform);
+ if (allLayers) {
+ minLayer = 0;
+ maxLayer = -1UL;
}
+
+ res = screenshot->update(displayToken, sourceCrop, width, height,
+ minLayer, maxLayer, useIdentityTransform, static_cast<uint32_t>(rotation));
if (res != NO_ERROR) {
return NULL;
}
@@ -588,7 +585,7 @@
(void*)nativeRelease },
{"nativeDestroy", "(J)V",
(void*)nativeDestroy },
- {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZ)Landroid/graphics/Bitmap;",
+ {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/Bitmap;",
(void*)nativeScreenshotBitmap },
{"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V",
(void*)nativeScreenshot },
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index c84a466..2e2d0c7 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -175,17 +175,23 @@
continue;
}
}
- // Skip whitespace.
- while (*pos == ' ') {
- pos++;
- }
- // Next field is tag.
- rawTag = strtoll(pos, &endPos, 16);
- //ALOGI("Index #%d: %s", idx, buffer);
- if (pos == endPos) {
- ALOGE("bad tag: %s", pos);
- fclose(fp);
- return -1;
+
+ // Ignore whitespace
+ while (*pos == ' ') pos++;
+
+ // Find end of tag field
+ endPos = pos;
+ while (*endPos != ' ') endPos++;
+
+ // Three digit field is always 0x0, otherwise parse
+ if (endPos - pos == 3) {
+ rawTag = 0;
+ } else {
+ if (sscanf(pos, "%llx", &rawTag) != 1) {
+ ALOGE("bad tag: %s", pos);
+ fclose(fp);
+ return -1;
+ }
}
s.tag = rawTag >> 32;
if (limitTag != -1 && s.tag != limitTag) {
@@ -193,10 +199,10 @@
continue;
}
pos = endPos;
- // Skip whitespace.
- while (*pos == ' ') {
- pos++;
- }
+
+ // Ignore whitespace
+ while (*pos == ' ') pos++;
+
// Parse remaining fields.
if (sscanf(pos, "%u %u %llu %llu %llu %llu",
&s.uid, &s.set, &s.rxBytes, &s.rxPackets,
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 3d2d471..451d97a 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -421,7 +421,8 @@
jlong permittedCapabilities, jlong effectiveCapabilities,
jint mount_external,
jstring java_se_info, jstring java_se_name,
- bool is_system_server, jintArray fdsToClose) {
+ bool is_system_server, jintArray fdsToClose,
+ jstring instructionSet) {
uint64_t start = MsTime();
SetSigChldHandler();
ckTime(start, "ForkAndSpecializeCommon:SetSigChldHandler");
@@ -542,7 +543,8 @@
ckTime(start, "ForkAndSpecializeCommon:child process setup");
- env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags);
+ env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
+ is_system_server ? NULL : instructionSet);
ckTime(start, "ForkAndSpecializeCommon:PostForkChildHooks returns");
if (env->ExceptionCheck()) {
ALOGE("Error calling post fork hooks.");
@@ -561,7 +563,7 @@
JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
jint debug_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring se_name,
- jintArray fdsToClose) {
+ jintArray fdsToClose, jstring instructionSet) {
// Grant CAP_WAKE_ALARM to the Bluetooth process.
jlong capabilities = 0;
if (uid == AID_BLUETOOTH) {
@@ -570,7 +572,7 @@
return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
rlimits, capabilities, capabilities, mount_external, se_info,
- se_name, false, fdsToClose);
+ se_name, false, fdsToClose, instructionSet);
}
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
@@ -580,7 +582,7 @@
pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
debug_flags, rlimits,
permittedCapabilities, effectiveCapabilities,
- MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL);
+ MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL, NULL);
if (pid > 0) {
// The zygote process checks whether the child process has died or not.
ALOGI("System server process %d has been created", pid);
@@ -598,7 +600,8 @@
}
static JNINativeMethod gMethods[] = {
- { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;[I)I",
+ { "nativeForkAndSpecialize",
+ "(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;)I",
(void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
{ "nativeForkSystemServer", "(II[II[[IJJ)I",
(void *) com_android_internal_os_Zygote_nativeForkSystemServer }
@@ -609,7 +612,8 @@
if (gZygoteClass == NULL) {
RuntimeAbort(env);
}
- gCallPostForkChildHooks = env->GetStaticMethodID(gZygoteClass, "callPostForkChildHooks", "(I)V");
+ gCallPostForkChildHooks = env->GetStaticMethodID(gZygoteClass, "callPostForkChildHooks",
+ "(ILjava/lang/String;)V");
return AndroidRuntime::registerNativeMethods(env, "com/android/internal/os/Zygote",
gMethods, NELEM(gMethods));
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 72dd930..bf2d09b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2502,7 +2502,7 @@
<permission android:name="android.permission.PACKAGE_USAGE_STATS"
android:label="@string/permlab_pkgUsageStats"
android:description="@string/permdesc_pkgUsageStats"
- android:protectionLevel="signature|system|development|appop" />
+ android:protectionLevel="signature|development|appop" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<!-- @SystemApi Allows an application to collect battery statistics -->
@@ -2773,7 +2773,7 @@
android:description="@string/permdesc_bindNotificationListenerService"
android:protectionLevel="signature" />
- <!-- Must be required by an {@link
+ <!-- @SystemApi Must be required by a {@link
android.service.notification.ConditionProviderService},
to ensure that only the system can bind to it.
@hide -->
diff --git a/core/res/res/drawable/emulator_circular_window_overlay.xml b/core/res/res/drawable/emulator_circular_window_overlay.xml
new file mode 100644
index 0000000..7616b37
--- /dev/null
+++ b/core/res/res/drawable/emulator_circular_window_overlay.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Default to an empty shape drawable -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+</shape>
diff --git a/core/res/res/drawable/ic_corp_icon_badge.xml b/core/res/res/drawable/ic_corp_icon_badge.xml
index 834ae68..0021a8f 100644
--- a/core/res/res/drawable/ic_corp_icon_badge.xml
+++ b/core/res/res/drawable/ic_corp_icon_badge.xml
@@ -20,11 +20,13 @@
android:viewportHeight="64.0">
<path
- android:fillColor="#33000000"
- android:pathData="M49.062,50.0m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0"/>
+ android:fillColor="#FF000000"
+ android:pathData="M49.062,50.0m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0"
+ android:fillAlpha="0.2"/>
<path
- android:fillColor="#33000000"
- android:pathData="M49.0,49.5m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0"/>
+ android:fillColor="#FF000000"
+ android:pathData="M49.0,49.5m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0"
+ android:fillAlpha="0.2"/>
<path
android:pathData="M49.0,49.0m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0"
android:fillColor="#FF5722"/>
diff --git a/core/res/res/drawable/vector_drawable_progress_indeterminate_horizontal.xml b/core/res/res/drawable/vector_drawable_progress_indeterminate_horizontal.xml
index 7ceb772..cd999d5 100644
--- a/core/res/res/drawable/vector_drawable_progress_indeterminate_horizontal.xml
+++ b/core/res/res/drawable/vector_drawable_progress_indeterminate_horizontal.xml
@@ -26,11 +26,11 @@
android:translateY="5" >
<group android:name="v21_pivot" >
<group
- android:name="rectangle_path_1_position"
- android:alpha="0.1" >
+ android:name="rectangle_path_1_position">
<path
android:name="rectangle_path_1"
android:fillColor="?attr/colorControlActivated"
+ android:fillAlpha="0.1"
android:pathData="M -180.0 -1.0 l 360 0 l 0 2 l -360 0 Z" />
</group>
<group
diff --git a/core/res/res/layout/alert_dialog_material.xml b/core/res/res/layout/alert_dialog_material.xml
index 5f9066a..be89e41 100644
--- a/core/res/res/layout/alert_dialog_material.xml
+++ b/core/res/res/layout/alert_dialog_material.xml
@@ -33,8 +33,7 @@
android:gravity="center_vertical|start"
android:paddingStart="@dimen/alert_dialog_padding_material"
android:paddingEnd="@dimen/alert_dialog_padding_material"
- android:paddingTop="@dimen/alert_dialog_padding_material"
- android:paddingBottom="8dip">
+ android:paddingTop="@dimen/alert_dialog_padding_top_material">
<ImageView android:id="@+id/icon"
android:layout_width="32dip"
android:layout_height="32dip"
@@ -57,7 +56,8 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
- android:minHeight="64dp">
+ android:minHeight="64dp"
+ android:paddingTop="@dimen/alert_dialog_padding_top_material">
<ScrollView android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -67,9 +67,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="@dimen/alert_dialog_padding_material"
- android:paddingEnd="@dimen/alert_dialog_padding_material"
- android:paddingTop="@dimen/alert_dialog_padding_material"
- android:paddingBottom="@dimen/alert_dialog_padding_material" />
+ android:paddingEnd="@dimen/alert_dialog_padding_material" />
</ScrollView>
</LinearLayout>
@@ -89,15 +87,14 @@
android:layout_height="wrap_content"
android:layoutDirection="locale"
android:orientation="horizontal"
- android:paddingStart="6dp"
- android:paddingEnd="6dp"
- android:paddingBottom="6dp">
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp">
<Button android:id="@+id/button3"
style="?attr/buttonBarNeutralButtonStyle"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:maxLines="2"
- android:minHeight="@dimen/alert_dialog_button_bar_height" />
+ android:layout_height="wrap_content" />
<Space
android:layout_width="0dp"
android:layout_height="0dp"
@@ -106,14 +103,10 @@
<Button android:id="@+id/button2"
style="?attr/buttonBarNegativeButtonStyle"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:maxLines="2"
- android:minHeight="@dimen/alert_dialog_button_bar_height" />
+ android:layout_height="wrap_content" />
<Button android:id="@+id/button1"
style="?attr/buttonBarPositiveButtonStyle"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:maxLines="2"
- android:minHeight="@dimen/alert_dialog_button_bar_height" />
+ android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
diff --git a/core/res/res/layout/alert_dialog_progress_material.xml b/core/res/res/layout/alert_dialog_progress_material.xml
index b9d0814..d005a44 100644
--- a/core/res/res/layout/alert_dialog_progress_material.xml
+++ b/core/res/res/layout/alert_dialog_progress_material.xml
@@ -17,32 +17,27 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
- android:layout_height="match_parent">
- <ProgressBar android:id="@+id/progress"
- style="?android:attr/progressBarStyleHorizontal"
+ android:layout_height="match_parent"
+ android:paddingStart="@dimen/alert_dialog_padding_material"
+ android:paddingTop="@dimen/alert_dialog_padding_top_material"
+ android:paddingEnd="@dimen/alert_dialog_padding_material"
+ android:paddingBottom="@dimen/alert_dialog_padding_top_material">
+ <ProgressBar
+ android:id="@+id/progress"
+ style="?attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="16dip"
- android:layout_marginBottom="1dip"
- android:layout_marginStart="16dip"
- android:layout_marginEnd="16dip"
android:layout_centerHorizontal="true" />
<TextView
android:id="@+id/progress_percent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingBottom="16dip"
- android:layout_marginStart="16dip"
- android:layout_marginEnd="16dip"
android:layout_alignParentStart="true"
android:layout_below="@id/progress" />
<TextView
android:id="@+id/progress_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingBottom="16dip"
- android:layout_marginStart="16dip"
- android:layout_marginEnd="16dip"
android:layout_alignParentEnd="true"
android:layout_below="@id/progress" />
</RelativeLayout>
diff --git a/core/res/res/layout/dialog_custom_title_material.xml b/core/res/res/layout/dialog_custom_title_material.xml
index 550b72e..248a05e 100644
--- a/core/res/res/layout/dialog_custom_title_material.xml
+++ b/core/res/res/layout/dialog_custom_title_material.xml
@@ -23,17 +23,17 @@
android:fitsSystemWindows="true">
<FrameLayout android:id="@android:id/title_container"
android:layout_width="match_parent"
- android:layout_height="?android:attr/windowTitleSize"
+ android:layout_height="?attr/windowTitleSize"
android:layout_weight="0"
android:gravity="center_vertical|start"
- style="?android:attr/windowTitleBackgroundStyle" />
+ style="?attr/windowTitleBackgroundStyle" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
- android:foreground="?android:attr/windowContentOverlay">
- <FrameLayout android:id="@android:id/content"
+ android:foreground="?attr/windowContentOverlay">
+ <FrameLayout android:id="@id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
diff --git a/core/res/res/layout/dialog_title_icons_material.xml b/core/res/res/layout/dialog_title_icons_material.xml
index 28e20d9..21396da 100644
--- a/core/res/res/layout/dialog_title_icons_material.xml
+++ b/core/res/res/layout/dialog_title_icons_material.xml
@@ -28,16 +28,16 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
- android:paddingStart="16dip"
- android:paddingEnd="16dip"
- android:paddingTop="16dip">
+ android:paddingStart="@dimen/alert_dialog_padding_material"
+ android:paddingEnd="@dimen/alert_dialog_padding_material"
+ android:paddingTop="@dimen/alert_dialog_padding_material">
<ImageView android:id="@+id/left_icon"
android:layout_width="32dip"
android:layout_height="32dip"
android:scaleType="fitCenter"
android:layout_marginEnd="8dip" />
- <TextView android:id="@android:id/title"
- style="?android:attr/windowTitleStyle"
+ <TextView android:id="@id/title"
+ style="?attr/windowTitleStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0" />
@@ -52,8 +52,8 @@
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
- android:foreground="?android:attr/windowContentOverlay">
- <FrameLayout android:id="@android:id/content"
+ android:foreground="?attr/windowContentOverlay">
+ <FrameLayout android:id="@id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
diff --git a/core/res/res/layout/dialog_title_material.xml b/core/res/res/layout/dialog_title_material.xml
index 918c8f1..fcf6164 100644
--- a/core/res/res/layout/dialog_title_material.xml
+++ b/core/res/res/layout/dialog_title_material.xml
@@ -29,15 +29,15 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="viewStart"
- android:paddingStart="16dip"
- android:paddingEnd="16dip"
- android:paddingTop="16dip" />
+ android:paddingStart="@dimen/alert_dialog_padding_material"
+ android:paddingEnd="@dimen/alert_dialog_padding_material"
+ android:paddingTop="@dimen/alert_dialog_padding_top_material" />
<FrameLayout
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
- android:foreground="?android:attr/windowContentOverlay">
- <FrameLayout android:id="@android:id/content"
+ android:foreground="?attr/windowContentOverlay">
+ <FrameLayout android:id="@id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml
index 2382d18..8a66c3f 100644
--- a/core/res/res/layout/notification_template_material_inbox.xml
+++ b/core/res/res/layout/notification_template_material_inbox.xml
@@ -44,6 +44,7 @@
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp"
+ android:layout_marginEnd="8dp"
android:orientation="horizontal"
>
<TextView android:id="@+id/inbox_text0"
@@ -60,7 +61,6 @@
android:layout_height="@dimen/notification_badge_size"
android:layout_weight="0"
android:layout_marginStart="4dp"
- android:layout_marginEnd="8dp"
android:scaleType="fitCenter"
android:visibility="gone"
/>
diff --git a/core/res/res/layout/notification_template_part_line1.xml b/core/res/res/layout/notification_template_part_line1.xml
index 7de4089..78bc1ed 100644
--- a/core/res/res/layout/notification_template_part_line1.xml
+++ b/core/res/res/layout/notification_template_part_line1.xml
@@ -24,7 +24,7 @@
>
<TextView android:id="@+id/title"
android:textAppearance="@style/TextAppearance.Material.Notification.Title"
- android:layout_width="match_parent"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
diff --git a/core/res/res/layout/notification_template_part_line2.xml b/core/res/res/layout/notification_template_part_line2.xml
index 7e99c5e..aeef3ab 100644
--- a/core/res/res/layout/notification_template_part_line2.xml
+++ b/core/res/res/layout/notification_template_part_line2.xml
@@ -45,13 +45,13 @@
android:visibility="gone"
/>
</LinearLayout>
- <ProgressBar
+ <ViewStub
android:id="@android:id/progress"
+ android:layout="@layout/notification_template_progressbar"
android:layout_width="match_parent"
android:layout_height="15dp"
android:layout_marginEnd="8dp"
android:visibility="gone"
android:layout_weight="0"
- style="@style/Widget.Material.Light.ProgressBar.Horizontal"
/>
</merge>
diff --git a/core/res/res/layout/notification_template_progressbar.xml b/core/res/res/layout/notification_template_progressbar.xml
new file mode 100644
index 0000000..61480b8
--- /dev/null
+++ b/core/res/res/layout/notification_template_progressbar.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+
+<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/progress"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ style="@style/Widget.Material.Light.ProgressBar.Horizontal"
+ />
diff --git a/core/res/res/layout/preference_material.xml b/core/res/res/layout/preference_material.xml
index a137149..39c979c 100644
--- a/core/res/res/layout/preference_material.xml
+++ b/core/res/res/layout/preference_material.xml
@@ -42,6 +42,7 @@
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:adjustViewBounds="true"
android:maxWidth="48dp"
android:maxHeight="48dp" />
</LinearLayout>
diff --git a/core/res/res/layout/progress_dialog_material.xml b/core/res/res/layout/progress_dialog_material.xml
index 84d06b5..54af106 100644
--- a/core/res/res/layout/progress_dialog_material.xml
+++ b/core/res/res/layout/progress_dialog_material.xml
@@ -19,21 +19,27 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
- <LinearLayout android:id="@+id/body"
+ <LinearLayout
+ android:id="@+id/body"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
- android:padding="16dip">
+ android:paddingStart="@dimen/alert_dialog_padding_material"
+ android:paddingTop="@dimen/alert_dialog_padding_top_material"
+ android:paddingEnd="@dimen/alert_dialog_padding_material"
+ android:paddingBottom="@dimen/alert_dialog_padding_top_material">
- <ProgressBar android:id="@android:id/progress"
+ <ProgressBar
+ android:id="@id/progress"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:max="10000"
- android:layout_marginEnd="16dip" />
+ android:layout_marginEnd="@dimen/alert_dialog_padding_material" />
- <TextView android:id="@+id/message"
+ <TextView
+ android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical" />
diff --git a/core/res/res/layout/resolve_list_item.xml b/core/res/res/layout/resolve_list_item.xml
index 7aa9a72..37c4270 100644
--- a/core/res/res/layout/resolve_list_item.xml
+++ b/core/res/res/layout/resolve_list_item.xml
@@ -18,9 +18,10 @@
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
+ android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
+ android:minHeight="?attr/listPreferredItemHeightSmall"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:background="?attr/activatedBackgroundIndicator">
@@ -28,37 +29,40 @@
<!-- Activity icon when presenting dialog
Size will be filled in by ResolverActivity -->
<ImageView android:id="@+id/icon"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_gravity="center"
- android:layout_margin="4dp"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_gravity="start|center_vertical"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginTop="12dp"
+ android:layout_marginBottom="12dp"
android:scaleType="fitCenter" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:gravity="center"
+ android:gravity="start|center_vertical"
android:orientation="vertical"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:layout_gravity="center">
+ android:layout_gravity="start|center_vertical">
<!-- Activity name -->
<TextView android:id="@android:id/text1"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:fontFamily="sans-serif-condensed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="center"
- android:minLines="2"
- android:maxLines="2" />
+ android:textAppearance="?attr/textAppearanceMedium"
+ android:textColor="?attr/textColorPrimary"
+ android:minLines="1"
+ android:maxLines="1"
+ android:ellipsize="marquee" />
<!-- Extended activity info to distinguish between duplicate activity names -->
<TextView android:id="@android:id/text2"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:fontFamily="sans-serif-condensed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="center"
- android:minLines="2"
- android:maxLines="2"
- android:paddingTop="4dip" />
+ android:minLines="1"
+ android:maxLines="1"
+ android:ellipsize="marquee" />
</LinearLayout>
</LinearLayout>
diff --git a/core/res/res/layout/resolver_different_item_header.xml b/core/res/res/layout/resolver_different_item_header.xml
new file mode 100644
index 0000000..5889136
--- /dev/null
+++ b/core/res/res/layout/resolver_different_item_header.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 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.
+ */
+-->
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alwaysShow="true"
+ android:text="@string/use_a_different_app"
+ android:minHeight="56dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:gravity="start|center_vertical"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:background="@color/white"
+ android:elevation="8dp"
+ />
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index 8e57543..727f9c6 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -21,38 +21,36 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:maxWidth="@dimen/resolver_max_width"
- android:maxCollapsedHeight="260dp"
+ android:maxCollapsedHeight="192dp"
android:maxCollapsedHeightSmall="56dp"
android:id="@id/contentPanel"
>
<TextView android:id="@+id/title"
android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_height="wrap_content"
android:layout_alwaysShow="true"
+ android:minHeight="56dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="start|center_vertical"
- android:paddingLeft="32dp"
- android:paddingRight="32dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
android:background="@color/white"
android:elevation="8dp"
/>
- <GridView
+ <ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/resolver_list"
- android:numColumns="4"
- android:columnWidth="128dp"
android:clipToPadding="false"
android:scrollbarStyle="outsideOverlay"
- android:paddingLeft="32dp"
- android:paddingRight="32dp"
- android:paddingTop="16dp"
- android:paddingBottom="16dp"
android:background="@color/white"
android:elevation="8dp"
android:nestedScrollingEnabled="true"
+ android:divider="@null"
/>
<TextView android:id="@+id/empty"
@@ -72,14 +70,15 @@
android:layout_height="wrap_content"
android:layout_ignoreOffset="true"
android:layout_alwaysShow="true"
- android:gravity="end"
+ android:gravity="end|center_vertical"
android:orientation="horizontal"
android:layoutDirection="locale"
android:measureWithLargestChild="true"
android:background="@color/white"
- android:paddingBottom="16dp"
- android:paddingStart="32dp"
- android:paddingEnd="32dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp"
android:elevation="8dp">
<Button android:id="@+id/button_once"
android:layout_width="wrap_content"
diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml
index 0bd0e14..884f41e 100644
--- a/core/res/res/layout/resolver_list_with_default.xml
+++ b/core/res/res/layout/resolver_list_with_default.xml
@@ -21,7 +21,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:maxWidth="@dimen/resolver_max_width"
- android:maxCollapsedHeight="48dp"
+ android:maxCollapsedHeight="144dp"
android:id="@id/contentPanel"
>
@@ -35,26 +35,28 @@
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="80dp"
- android:paddingStart="32dp"
- android:paddingEnd="32dp"
+ android:layout_height="64dp"
android:orientation="horizontal"
>
+ <ImageView android:id="@+id/icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_gravity="start|top"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginTop="20dp"
+ android:scaleType="fitCenter"
+ />
<TextView android:id="@+id/title"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_marginStart="16dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="start|center_vertical"
android:paddingEnd="16dp"
/>
- <ImageView android:id="@+id/icon"
- android:layout_width="56dp"
- android:layout_height="56dp"
- android:layout_gravity="center_vertical"
- android:scaleType="fitCenter"
- />
</LinearLayout>
<LinearLayout
@@ -64,13 +66,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alwaysShow="true"
- android:gravity="end"
+ android:gravity="end|center_vertical"
android:orientation="horizontal"
android:layoutDirection="locale"
android:measureWithLargestChild="true"
- android:paddingBottom="16dp"
- android:paddingStart="32dp"
- android:paddingEnd="32dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp"
android:background="@color/white"
android:elevation="8dp">
<Button android:id="@+id/button_once"
@@ -99,21 +102,16 @@
android:background="?android:attr/dividerVertical" />
</LinearLayout>
- <GridView
+ <ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/resolver_list"
- android:numColumns="4"
- android:columnWidth="128dp"
android:clipToPadding="false"
android:scrollbarStyle="outsideOverlay"
- android:paddingLeft="32dp"
- android:paddingRight="32dp"
- android:paddingTop="16dp"
- android:paddingBottom="16dp"
android:background="@color/white"
android:elevation="8dp"
android:nestedScrollingEnabled="true"
+ android:divider="@null"
/>
</com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/layout/simple_spinner_dropdown_item.xml b/core/res/res/layout/simple_spinner_dropdown_item.xml
index e2bd474..f276cfa 100644
--- a/core/res/res/layout/simple_spinner_dropdown_item.xml
+++ b/core/res/res/layout/simple_spinner_dropdown_item.xml
@@ -4,24 +4,23 @@
**
** Copyright 2008, The Android Open Source Project
**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
+** 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
+** 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
+** 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.
*/
-->
-<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
+<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="?android:attr/spinnerDropDownItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="?android:attr/dropdownListPreferredItemHeight"
- android:ellipsize="marquee"
- android:textAlignment="inherit"/>
+ android:ellipsize="marquee"/>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 35ff766..3356081 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -183,9 +183,9 @@
<string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Tichý režim"</string>
<string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Zvuk je VYPNUTÝ."</string>
<string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Zvuk je zapnutý"</string>
- <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Režim V letadle"</string>
- <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Režim V letadle je ZAPNUTÝ"</string>
- <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Režim V letadle je VYPNUTÝ"</string>
+ <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Režim Letadlo"</string>
+ <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Režim Letadlo je ZAPNUTÝ"</string>
+ <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Režim Letadlo je VYPNUTÝ"</string>
<string name="global_action_settings" msgid="1756531602592545966">"Nastavení"</string>
<string name="global_action_lockdown" msgid="8751542514724332873">"Zamknout"</string>
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
@@ -280,10 +280,10 @@
<string name="permdesc_receiveSms" msgid="6424387754228766939">"Umožňuje aplikaci přijmout a zpracovat zprávy SMS. Znamená to, že aplikace může sledovat zprávy odeslané do vašeho zařízení nebo je smazat, aniž by se vám zobrazily."</string>
<string name="permlab_receiveMms" msgid="1821317344668257098">"příjem textových zpráv (MMS)"</string>
<string name="permdesc_receiveMms" msgid="533019437263212260">"Umožňuje aplikaci přijmout a zpracovat zprávy MMS. Znamená to, že aplikace může sledovat zprávy odeslané do vašeho zařízení nebo je smazat, aniž by se vám zobrazily."</string>
- <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"příjem nouzového vysílání"</string>
- <string name="permdesc_receiveEmergencyBroadcast" msgid="848524070262431974">"Umožňuje aplikaci přijmout a zpracovat zprávy tísňového vysílání. Toto oprávnění je dostupné pouze pro systémové aplikace."</string>
- <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"čtení zpráv informační služby"</string>
- <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Umožňuje aplikaci číst zprávy informační služby přijaté ve vašem zařízení. Upozornění informační služby jsou v některých oblastech odesílána za účelem varování před mimořádnými událostmi. Škodlivé aplikace mohou narušit výkon či provoz vašeho zařízení během přijímání zpráv informační služby."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"příjem výstražných zpráv o výjimečné situaci"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="848524070262431974">"Umožňuje aplikaci přijmout a zpracovat výstražné zprávy o výjimečných situacích. Toto oprávnění je dostupné pouze pro systémové aplikace."</string>
+ <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"čtení zpráv informačních služeb"</string>
+ <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Umožňuje aplikaci číst zprávy informačních služeb přijaté ve vašem zařízení. Výstražná upozornění informačních služeb jsou v některých oblastech odesílána za účelem varování před výjimečnými událostmi. Škodlivé aplikace mohou narušit výkon či provoz vašeho zařízení během přijímání zpráv informačních služeb."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"odesílaní zpráv SMS"</string>
<string name="permdesc_sendSms" msgid="7094729298204937667">"Umožňuje aplikaci odesílat zprávy SMS. Může to mít za následek účtování neočekávaných poplatků. Škodlivé aplikace vás mohou připravit o peníze odesíláním zpráv bez vašeho svolení."</string>
<string name="permlab_sendRespondViaMessageRequest" msgid="8713889105305943200">"odesílání událostí typu „odpovězte zprávou“"</string>
@@ -772,7 +772,7 @@
<item msgid="8901098336658710359">"Domů"</item>
<item msgid="869923650527136615">"Mobil"</item>
<item msgid="7897544654242874543">"Práce"</item>
- <item msgid="1103601433382158155">"Pracovní fax"</item>
+ <item msgid="1103601433382158155">"Fax práce"</item>
<item msgid="1735177144948329370">"Fax domů"</item>
<item msgid="603878674477207394">"Pager"</item>
<item msgid="1650824275177931637">"Ostatní"</item>
@@ -827,7 +827,7 @@
<string name="phoneTypeOtherFax" msgid="8587657145072446565">"Jiný fax"</string>
<string name="phoneTypeRadio" msgid="4093738079908667513">"Radiotelefon"</string>
<string name="phoneTypeTelex" msgid="3367879952476250512">"Telex"</string>
- <string name="phoneTypeTtyTdd" msgid="8606514378585000044">"Telefon pro sluchově postižené (TTY/TDD)"</string>
+ <string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY/TDD"</string>
<string name="phoneTypeWorkMobile" msgid="1311426989184065709">"Pracovní mobil"</string>
<string name="phoneTypeWorkPager" msgid="649938731231157056">"Pracovní pager"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"Asistent"</string>
@@ -1255,7 +1255,7 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Hlasitost médií"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Hlasitost oznámení"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Výchozí vyzváněcí tón"</string>
- <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Výchozí vyzváněcí tón (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+ <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Výchozí tón (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Žádné"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Vyzváněcí tóny"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Neznámý vyzváněcí tón"</string>
@@ -1639,7 +1639,7 @@
<string name="accessibility_enabled" msgid="1381972048564547685">"Usnadnění přístupu je aktivováno."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Usnadnění zrušeno."</string>
<string name="user_switched" msgid="3768006783166984410">"Aktuální uživatel je <xliff:g id="NAME">%1$s</xliff:g>."</string>
- <string name="user_switching_message" msgid="2871009331809089783">"Přepínání na uživatele <xliff:g id="NAME">%1$s</xliff:g>…"</string>
+ <string name="user_switching_message" msgid="2871009331809089783">"Přepínání na účet <xliff:g id="NAME">%1$s</xliff:g>…"</string>
<string name="owner_name" msgid="2716755460376028154">"Vlastník"</string>
<string name="error_message_title" msgid="4510373083082500195">"Chyba"</string>
<string name="error_message_change_not_allowed" msgid="1347282344200417578">"Administrátor tuto změnu zakázal"</string>
@@ -1774,6 +1774,6 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Před uvolněním požádat o kód PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Před uvolněním požádat o bezpečnostní gesto"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Před uvolněním požádat o heslo"</string>
- <string name="battery_saver_description" msgid="2510530476513605742">"Za účelem zvýšení životnosti baterie režim úspory baterie sníží výkon vašeho zařízení a omezí vibrace a většinu dat na pozadí. E-mail, zprávy a další aplikace, které používají synchronizaci, nemusejí být aktualizovány, dokud je nespustíte.\n\nPři nabíjení zařízení se režim úspory baterie automaticky vypne."</string>
+ <string name="battery_saver_description" msgid="2510530476513605742">"Za účelem zvýšení životnosti baterie spořič baterie sníží výkon vašeho zařízení a omezí vibrace a většinu dat na pozadí. E-mail, zprávy a další aplikace, které používají synchronizaci, nemusejí být aktualizovány, dokud je nespustíte.\n\nPři nabíjení zařízení se spořič baterie automaticky vypne."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Dokud v <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> neskončí pozastavení"</string>
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 95125eb..2fa54dc 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1241,7 +1241,7 @@
<string name="new_app_description" msgid="1932143598371537340">"Interrompi la vecchia applicazione senza salvare."</string>
<string name="sendText" msgid="5209874571959469142">"Scegli un\'azione per il testo"</string>
<string name="volume_ringtone" msgid="6885421406845734650">"Volume suoneria"</string>
- <string name="volume_music" msgid="5421651157138628171">"Volume app. multimediali"</string>
+ <string name="volume_music" msgid="5421651157138628171">"Volume contenuti multimediali"</string>
<string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Riproduzione tramite Bluetooth"</string>
<string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"Suoneria silenziosa impostata"</string>
<string name="volume_call" msgid="3941680041282788711">"Volume chiamate"</string>
@@ -1764,7 +1764,7 @@
<string name="lock_to_app_toast" msgid="1230563865743799321">"Per sbloccare questa schermata, tocca e tieni premuto contemporaneamente Indietro e Recenti."</string>
<string name="lock_to_app_toast_accessible" msgid="3340628918851844044">"Per sbloccare questa schermata, tocca e tieni premuto Recenti."</string>
<string name="lock_to_app_toast_locked" msgid="8739004135132606329">"La schermata è bloccata. La tua organizzazione non ne consente lo sblocco."</string>
- <string name="lock_to_app_title" msgid="1682643873107812874">"Utilizzare blocco schermata?"</string>
+ <string name="lock_to_app_title" msgid="1682643873107812874">"Utilizzare il blocco su schermo?"</string>
<string name="lock_to_app_description" msgid="9076084599283282800">"Il blocco schermata fissa la visualizzazione su una stessa immagine.\n\nPer uscire, tocca e tieni premuto contemporaneamente Indietro e Recenti."</string>
<string name="lock_to_app_description_accessible" msgid="2132076937479670601">"Il blocco schermata fissa la visualizzazione su una stessa immagine.\n\nPer uscire, tocca e tieni premuto Recenti."</string>
<string name="lock_to_app_negative" msgid="2259143719362732728">"NO, GRAZIE"</string>
diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
index 5259152..06b6efe 100644
--- a/core/res/res/values-mcc302-mnc220/config.xml
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -25,4 +25,6 @@
<item>302720</item>
<item>302780</item>
</string-array>
+
+ <integer name="config_mobile_mtu">1410</integer>
</resources>
diff --git a/core/res/res/values-mcc310-mnc004/config.xml b/core/res/res/values-mcc310-mnc004/config.xml
index 2778b6e..423e250 100644
--- a/core/res/res/values-mcc310-mnc004/config.xml
+++ b/core/res/res/values-mcc310-mnc004/config.xml
@@ -34,11 +34,4 @@
</string-array>
<bool name="config_auto_attach_data_on_creation">false</bool>
-
- <!-- Values for GPS configuration (Verizon) -->
- <string-array translatable="false" name="config_gpsParameters">
- <item>CAPABILITIES=0x31</item>
- <item>LPP_PROFILE=3</item>
- <item>GPS_LOCK=3</item>
- </string-array>
</resources>
diff --git a/core/res/res/values-mcc310-mnc120/config.xml b/core/res/res/values-mcc310-mnc120/config.xml
index 3b95db5..24e55b1 100644
--- a/core/res/res/values-mcc310-mnc120/config.xml
+++ b/core/res/res/values-mcc310-mnc120/config.xml
@@ -25,10 +25,6 @@
-->
<integer name="config_mobile_mtu">1422</integer>
- <!-- Values for GPS configuration (Sprint) -->
- <string-array translatable="false" name="config_gpsParameters">
- <item>CAPABILITIES=0x31</item>
- <item>GPS_LOCK=3</item>
- <item>LPP_PROFILE=2</item>
- </string-array>
+ <!-- Sprint need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">70</integer>
</resources>
diff --git a/core/res/res/values-mcc310-mnc150/config.xml b/core/res/res/values-mcc310-mnc150/config.xml
index 00d2db8..f1936f4 100644
--- a/core/res/res/values-mcc310-mnc150/config.xml
+++ b/core/res/res/values-mcc310-mnc150/config.xml
@@ -33,10 +33,4 @@
<item>315</item>
<item>316</item>
</string-array>
- <!-- Values for GPS configuration (AT&T) -->
- <string-array translatable="false" name="config_gpsParameters">
- <item>CAPABILITIES=0x33</item>
- <item>LPP_PROFILE=3</item>
- <item>GPS_LOCK=1</item>
- </string-array>
</resources>
diff --git a/core/res/res/values-mcc310-mnc260/config.xml b/core/res/res/values-mcc310-mnc260/config.xml
index f8fff3b..28cd695 100644
--- a/core/res/res/values-mcc310-mnc260/config.xml
+++ b/core/res/res/values-mcc310-mnc260/config.xml
@@ -29,11 +29,4 @@
carrier provisioning. If false: hard disabled. If true: then depends on carrier
provisioning, availability etc -->
<bool name="config_carrier_volte_vt_available">true</bool>
-
- <!-- Values for GPS configuration (T-Mobile) -->
- <string-array translatable="false" name="config_gpsParameters">
- <item>CAPABILITEIS=0x33</item>
- <item>GPS_LOCK=1</item>
- <item>LPP_PROFILE=2</item>
- </string-array>
</resources>
diff --git a/core/res/res/values-mcc310-mnc410/config.xml b/core/res/res/values-mcc310-mnc410/config.xml
index edf6d9f..b863aae 100644
--- a/core/res/res/values-mcc310-mnc410/config.xml
+++ b/core/res/res/values-mcc310-mnc410/config.xml
@@ -40,12 +40,6 @@
<item>315</item>
<item>316</item>
</string-array>
- <!-- Values for GPS configuration (AT&T) -->
- <string-array translatable="false" name="config_gpsParameters">
- <item>CAPABILITIES=0x33</item>
- <item>GPS_LOCK=1</item>
- <item>LPP_PROFILE=3</item>
- </string-array>
<!-- Do not translate. Defines the slots is Two Digit Number for dialing normally not USSD -->
<string-array name="config_twoDigitNumberPattern">
<item>"0"</item>
diff --git a/core/res/res/values-mcc311-mnc190/config.xml b/core/res/res/values-mcc311-mnc190/config.xml
index b4e436d..a6c4d1b 100644
--- a/core/res/res/values-mcc311-mnc190/config.xml
+++ b/core/res/res/values-mcc311-mnc190/config.xml
@@ -37,11 +37,4 @@
note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
<string translatable="false" name="config_tether_apndata">Tether,broadband.cellular1.net,,,,,,,,,311,190,,DUN</string>
- <!-- Values for GPS configuration (Sprint) -->
- <string-array translatable="false" name="config_gpsParameters">
- <item>CAPABILITIES=0x31</item>
- <item>GPS_LOCK=3</item>
- <item>LPP_PROFILE=2</item>
- </string-array>
-
</resources>
diff --git a/core/res/res/values-mcc311-mnc220/config.xml b/core/res/res/values-mcc311-mnc220/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc220/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc221/config.xml b/core/res/res/values-mcc311-mnc221/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc221/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc222/config.xml b/core/res/res/values-mcc311-mnc222/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc222/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc223/config.xml b/core/res/res/values-mcc311-mnc223/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc223/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc224/config.xml b/core/res/res/values-mcc311-mnc224/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc224/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc225/config.xml b/core/res/res/values-mcc311-mnc225/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc225/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc226/config.xml b/core/res/res/values-mcc311-mnc226/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc226/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc227/config.xml b/core/res/res/values-mcc311-mnc227/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc227/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc228/config.xml b/core/res/res/values-mcc311-mnc228/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc228/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc229/config.xml b/core/res/res/values-mcc311-mnc229/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc229/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index 57ecd31..cf19235 100644
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -44,11 +44,4 @@
<bool name="config_carrier_volte_vt_available">false</bool>
<bool name="config_auto_attach_data_on_creation">false</bool>
-
- <!-- Values for GPS configuration (Verizon) -->
- <string-array translatable="false" name="config_gpsParameters">
- <item>CAPABILITIES=0x31</item>
- <item>GPS_LOCK=3</item>
- <item>LPP_PROFILE=3</item>
- </string-array>
</resources>
diff --git a/core/res/res/values-mcc311-mnc490/config.xml b/core/res/res/values-mcc311-mnc490/config.xml
new file mode 100644
index 0000000..defe78d
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc490/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Sprint need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">70</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc580/config.xml b/core/res/res/values-mcc311-mnc580/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc580/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc581/config.xml b/core/res/res/values-mcc311-mnc581/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc581/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc582/config.xml b/core/res/res/values-mcc311-mnc582/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc582/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc583/config.xml b/core/res/res/values-mcc311-mnc583/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc583/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc584/config.xml b/core/res/res/values-mcc311-mnc584/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc584/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc585/config.xml b/core/res/res/values-mcc311-mnc585/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc585/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc586/config.xml b/core/res/res/values-mcc311-mnc586/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc586/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc587/config.xml b/core/res/res/values-mcc311-mnc587/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc587/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc588/config.xml b/core/res/res/values-mcc311-mnc588/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc588/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc589/config.xml b/core/res/res/values-mcc311-mnc589/config.xml
new file mode 100644
index 0000000..811e9c7
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc589/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- USC need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">300</integer>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc870/config.xml b/core/res/res/values-mcc311-mnc870/config.xml
new file mode 100644
index 0000000..24e55b1
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc870/config.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Configure mobile network MTU. Carrier specific value is set here.
+ -->
+ <integer name="config_mobile_mtu">1422</integer>
+
+ <!-- Sprint need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">70</integer>
+</resources>
diff --git a/core/res/res/values-mcc312-mnc530/config.xml b/core/res/res/values-mcc312-mnc530/config.xml
new file mode 100644
index 0000000..24e55b1
--- /dev/null
+++ b/core/res/res/values-mcc312-mnc530/config.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Configure mobile network MTU. Carrier specific value is set here.
+ -->
+ <integer name="config_mobile_mtu">1422</integer>
+
+ <!-- Sprint need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">70</integer>
+</resources>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 83e1baa..dc0b1ab 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -254,13 +254,13 @@
<string name="permgrouplab_storage" msgid="1971118770546336966">"သိုလှောင်မှုများ"</string>
<string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"USBအားချိတ်ဆက်ရန်"</string>
<string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"SDကတ်အားချိတ်ဆက်ရန်"</string>
- <string name="permgrouplab_accessibilityFeatures" msgid="7919025602283593907">"လွယ်ကူစွာ ရရှိနိုင်မှု ပေးသော စွမ်းရည်"</string>
+ <string name="permgrouplab_accessibilityFeatures" msgid="7919025602283593907">"အများသုံးစွဲနိုင်မှု စွမ်းရည်"</string>
<string name="permgroupdesc_accessibilityFeatures" msgid="4205196881678144335">"ကူညီပေးမှု နည်းပညာများမှ တောင်းဆိုနိုင်သော ထူးခြားချက်များ"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"ဝင်းဒိုးမှာပါရှိသည်များကို ထုတ်ယူခြင်း"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"သင် အပြန်အလှန်လုပ်နေသော ဝင်းဒိုးမှာပါရှိသည်များကို သေချာစွာ ကြည့်ရှုစစ်ဆေးပါ"</string>
<string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"ထိတို့ခြင်းဖြင့် ရှာဖွေပေးနိုင်တာကို ဖွင့်လိုက်ပါ"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="5800552516779249356">"ထိတွေ့လိုက်တဲ့ အရာများကို အသံနဲ့ ထုတ်ပြောမှာဖြစ်ပြီး ဖန်သားပြင်ပေါကနေ လက်နဲ့ ထပ်မံ ကြည့်ရှုနိုင်ပါတယ်"</string>
- <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"ဝက်ဘ် လွယ်ကူစွာ အသုံးပြုနိုင်မှု စွမ်းရည် မြှင့်တင်ခြင်းကို ဖွင့်ရန်"</string>
+ <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"ပိုမိုကောင်းမွန်သော ဝက်ဘ်အများသုံးစွဲနိုင်မှုကို ဖွင့်ရန်"</string>
<string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"အပလီကေးရှင်းကို ပိုမိုပြည့်စုံစေရန် စကရစ်များကို သွင်းနိုင်ပါတယ်"</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"ရိုက်သောစာများကို သေချာစွာ စစ်ဆေးပါ"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"အရေးကြီးသော ကိုယ်ရေးအချက်အလက်များဖြစ်တဲ့ ခရက်ဒစ်ကဒ်နံပါတ်များနှင့် စကားဝှက်များ ပါဝင်ပါတယ်."</string>
@@ -1188,7 +1188,7 @@
<string name="ok" msgid="5970060430562524910">"ကောင်းပြီ"</string>
<string name="cancel" msgid="6442560571259935130">"ပယ်ဖျက်ရန်"</string>
<string name="yes" msgid="5362982303337969312">"ကောင်းပြီ"</string>
- <string name="no" msgid="5141531044935541497">"ပယ်ဖျက်သည်"</string>
+ <string name="no" msgid="5141531044935541497">"နေတော့"</string>
<string name="dialog_alert_title" msgid="2049658708609043103">"သတိပြုရန်"</string>
<string name="loading" msgid="7933681260296021180">"တင်နေ…"</string>
<string name="capital_on" msgid="1544682755514494298">"ဖွင့်ရန်"</string>
@@ -1297,7 +1297,7 @@
<string name="sms_short_code_details" msgid="5873295990846059400"><b>"ဒါက သင့် မိုဘိုင်း အကောင့် အတွက် "</b>" ကုန်ကျမှု ရှိလာနိုင်သည်။"</string>
<string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"ဒါက သင့် မိုဘိုင်း အကောင့် အတွက် ကုန်ကျမှု ရှိလာနိုင်သည်။"</b></string>
<string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"ပို့ရန်"</string>
- <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"ပယ်ဖျက်သည်"</string>
+ <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"နေတော့"</string>
<string name="sms_short_code_remember_choice" msgid="5289538592272218136">"ကျွန်ပ်၏ရွေးချယ်မှုကို မှတ်ထားရန်"</string>
<string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"နောင်တွင် ဆက်တင် > အပလီကေးရှင်းများ မှပြောင်းနိုင်သည်"</string>
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"အမြဲခွင့်ပြုရန်"</string>
@@ -1410,7 +1410,7 @@
<string name="ime_action_go" msgid="8320845651737369027">"သွားပါ"</string>
<string name="ime_action_search" msgid="658110271822807811">"ရှာဖွေခြင်း"</string>
<string name="ime_action_send" msgid="2316166556349314424">"ပို့ခြင်း"</string>
- <string name="ime_action_next" msgid="3138843904009813834">"အရှေ့သို့"</string>
+ <string name="ime_action_next" msgid="3138843904009813834">"ရှေ့သို့"</string>
<string name="ime_action_done" msgid="8971516117910934605">"ပြီးပါပြီ"</string>
<string name="ime_action_previous" msgid="1443550039250105948">"အနောက်သို့"</string>
<string name="ime_action_default" msgid="2840921885558045721">"လုပ်ဆောင်ချက်"</string>
@@ -1525,7 +1525,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"ပိုမိုရွေးချယ်စရာများ"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s ၊ %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s ၊ %2$s ၊ %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"စက်အတွင်းသိမ်းဆည်းရန်နေရာ"</string>
+ <string name="storage_internal" msgid="4891916833657929263">"စက်တွင်း သိုလှောင်ထားမှု"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"SD ကဒ်"</string>
<string name="storage_usb" msgid="3017954059538517278">"USBဖြင့် သိမ်းဆည်း"</string>
<string name="extract_edit_menu_button" msgid="8940478730496610137">"ပြင်ဆင်ရန်"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d1cc1fd..13b1dd920 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4341,6 +4341,8 @@
<attr name="minDate" format="string" />
<!-- The maximal date shown by this calendar view in mm/dd/yyyy format. -->
<attr name="maxDate" format="string" />
+ <!-- The first day of week according to {@link java.util.Calendar}. -->
+ <attr name="firstDayOfWeek" />
<!-- @hide The layout of the date picker. -->
<attr name="internalLayout" format="reference" />
<!-- @hide The layout of the legacy DatePicker. -->
@@ -4481,12 +4483,12 @@
<!-- The row boundary delimiting the top of the group of cells
occupied by this view. -->
<attr name="layout_row" format="integer" />
- <!-- The row span: the difference between the bottom and top
+ <!-- The row span: the difference between the top and bottom
boundaries delimiting the group of cells occupied by this view.
The default is one.
See {@link android.widget.GridLayout.Spec}. -->
<attr name="layout_rowSpan" format="integer" min="1" />
- <!-- The relative proportion of horizontal space that should be allocated to this view
+ <!-- The relative proportion of vertical space that should be allocated to this view
during excess space distribution. -->
<attr name="layout_rowWeight" format="float" />
<!-- The column boundary delimiting the left of the group of cells
@@ -4497,7 +4499,7 @@
The default is one.
See {@link android.widget.GridLayout.Spec}. -->
<attr name="layout_columnSpan" format="integer" min="1" />
- <!-- The relative proportion of vertical space that should be allocated to this view
+ <!-- The relative proportion of horizontal space that should be allocated to this view
during excess space distribution. -->
<attr name="layout_columnWeight" format="float" />
<!-- Gravity specifies how a component should be placed in its group of cells.
@@ -5284,8 +5286,6 @@
<attr name="scaleX" />
<!-- The amount to scale the group on X coordinate -->
<attr name="scaleY" />
- <!-- The alpha of the group (0 is transparent and 1 is opaque) -->
- <attr name="alpha" />
</declare-styleable>
<!-- Defines the path used in VectorDrawables. -->
@@ -5296,8 +5296,14 @@
<attr name="strokeWidth" format="float" />
<!-- The color to stroke the path if not defined implies no stroke-->
<attr name="strokeColor" format="color" />
+ <!-- The opacity of a path stroke, as a value between 0 (completely transparent)
+ and 1 (completely opaque) -->
+ <attr name="strokeAlpha" format="float" />
<!-- The color to fill the path if not defined implies no fill-->
<attr name="fillColor" format="color" />
+ <!-- The alpha of the path fill, as a value between 0 (completely transparent)
+ and 1 (completely opaque)-->
+ <attr name="fillAlpha" format="float" />
<!-- The specification of the operations that define the path -->
<attr name="pathData" format="string" />
<!-- The fraction of the path to trim from the start from 0 to 1 -->
@@ -7432,12 +7438,6 @@
<attr name="settingsActivity" />
</declare-styleable>
- <!-- @removed -->
- <attr name="__removed1" format="reference" />
-
- <!-- TODO: Spacer to be removed from here and public.xml -->
- <attr name="__removed2" format="reference" />
-
<!-- Attributes that can be used with <code>rating-system-definition</code> tags inside of the
XML resource that describes TV content rating of a {@link android.media.tv.TvInputService},
which is referenced from its
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f3b3077..3907fc5 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -351,6 +351,18 @@
point on the move. A value of 0 means no periodic scans will be used in the framework. -->
<integer translatable="false" name="config_wifi_framework_scan_interval">300000</integer>
+ <!-- Integer indicating associated scan interval in milliseconds -->
+ <integer translatable="false" name="config_wifi_framework_associated_scan_interval">10000</integer>
+
+ <!-- Boolean indicating associated scan are allowed -->
+ <bool translatable="false" name="config_wifi_framework_enable_associated_autojoin_scan">true</bool>
+
+ <!-- Boolean indicating associated network selection is allowed -->
+ <bool translatable="false" name="config_wifi_framework_enable_associated_network_selection">true</bool>
+
+ <!-- Boolean indicating that wifi only link configuratios that have exact same credentials (i.e PSK) -->
+ <bool translatable="false" name="config_wifi_only_link_same_credential_configurations">true</bool>
+
<!-- Wifi driver stop delay, in milliseconds.
Default value is 2 minutes. -->
<integer translatable="false" name="config_wifi_driver_stop_delay">120000</integer>
@@ -1611,6 +1623,10 @@
<!-- default window ShowCircularMask property -->
<bool name="config_windowShowCircularMask">false</bool>
+ <!-- default value for whether circular emulators (ro.emulator.circular)
+ should show a display overlay on the screen -->
+ <bool name="config_windowEnableCircularEmulatorDisplayOverlay">false</bool>
+
<!-- Defines the default set of global actions. Actions may still be disabled or hidden based
on the current state of the device.
Each item must be one of the following strings:
@@ -1715,16 +1731,25 @@
<string-array translatable="false" name="config_gpsParameters">
<item>SUPL_HOST=supl.google.com</item>
<item>SUPL_PORT=7275</item>
- <item>XTRA_SERVER_1=http://xtrapath1.izatcloud.net/xtra2.bin</item>
- <item>XTRA_SERVER_2=http://xtrapath2.izatcloud.net/xtra2.bin</item>
- <item>XTRA_SERVER_3=http://xtrapath3.izatcloud.net/xtra2.bin</item>
<item>NTP_SERVER=north-america.pool.ntp.org</item>
<item>SUPL_VER=0x20000</item>
- <item>CAPABILITIES=0x33</item>
- <item>LPP_PROFILE=0</item>
- <item>NMEA_PROVIDER=0</item>
- <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
- <item>ERR_ESTIMATE=0</item>
- <item>INTERMEDIATE_POS=0</item>
</string-array>
+
+ <!-- If there is no preload VM number in the sim card, carriers such as
+ Verizon require to load a default vm number from the configurantion.
+ Define config_default_vm_number for this purpose. And there are two
+ optional formats for this configuration as below:
+ (1)<item>voicemail number</item>
+ (2)<item>voicemail number;gid</item>
+ The logic to pick up the correct voicemail number:
+ (1) If the config_default_vm_number array has no gid special item, the last one will be
+ picked
+ (2) If the config_default_vm_number array has gid special item and it matches the current
+ sim's gid, it will be picked.
+ (3) If the config_default_vm_number array has gid special item but it doesn't match the
+ current sim's gid, the last one without gid will be picked -->
+ <string-array translatable="false" name="config_default_vm_number" />
+
+ <!-- Sprint need a 70 ms delay for 3way call -->
+ <integer name="config_cdma_3waycall_flash_delay">0</integer>
</resources>
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index 5f7f0ed..275a5ec 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -77,5 +77,6 @@
<!-- Default rounded corner for controls -->
<dimen name="control_corner_material">2dp</dimen>
- <dimen name="alert_dialog_padding_material">18dp</dimen>
+ <dimen name="alert_dialog_padding_material">24dp</dimen>
+ <dimen name="alert_dialog_padding_top_material">18dp</dimen>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 5b047f7..38b1e13 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2291,6 +2291,8 @@
<public type="attr" name="fragmentAllowEnterTransitionOverlap" />
<public type="attr" name="fragmentAllowReturnTransitionOverlap" />
<public type="attr" name="patternPathData" />
+ <public type="attr" name="strokeAlpha" />
+ <public type="attr" name="fillAlpha" />
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
@@ -2307,16 +2309,14 @@
<public type="style" name="Widget.Toolbar" />
<public type="style" name="Widget.Toolbar.Button.Navigation" />
- <public type="style" name="Widget.Holo.FastScroll" />
- <public type="style" name="Widget.Holo.StackView" />
-
- <public type="style" name="Widget.Holo.Light.Button.Borderless" />
- <public type="style" name="Widget.Holo.Light.FastScroll" />
- <public type="style" name="Widget.Holo.Light.StackView" />
+ <public type="style" name="__removed3" />
+ <public type="style" name="__removed4" />
+ <public type="style" name="__removed5" />
+ <public type="style" name="__removed6" />
+ <public type="style" name="__removed7" />
<public type="style" name="Widget.DeviceDefault.FastScroll" />
<public type="style" name="Widget.DeviceDefault.StackView" />
-
<public type="style" name="Widget.DeviceDefault.Light.FastScroll" />
<public type="style" name="Widget.DeviceDefault.Light.StackView" />
@@ -2540,7 +2540,7 @@
<public type="style" name="Theme.Leanback.FormWizard"/>
- <public type="style" name="__removed" />
+ <public type="style" name="__removed1" />
<public type="style" name="TextAppearance.Material.Notification" />
<public type="style" name="TextAppearance.Material.Notification.Title" />
<public type="style" name="TextAppearance.Material.Notification.Line2" />
@@ -2559,6 +2559,9 @@
<public type="style" name="Theme.Material.Light.Dialog.Alert" />
<public type="style" name="Theme.Material.Light.Dialog.Presentation" />
+ <public type="style" name="Widget.Material.SearchView" />
+ <public type="style" name="Widget.Material.Light.SearchView" />
+
<public-padding type="string" name="l_resource_pad" end="0x01040030" />
<public type="string" name="config_webSettingsDefaultTextEncoding" />
diff --git a/core/res/res/values/removed.xml b/core/res/res/values/removed.xml
new file mode 100644
index 0000000..8eaca29
--- /dev/null
+++ b/core/res/res/values/removed.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Placeholder resources to be removed before release. -->
+<resources>
+ <style name="__removed1" />
+ <attr name="__removed2" />
+ <style name="__removed3" />
+ <style name="__removed4" />
+ <style name="__removed5" />
+ <style name="__removed6" />
+ <style name="__removed7" />
+</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f1ec5d2..50da1fa 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3443,6 +3443,9 @@
<string name="whichHomeApplication">Select a home app</string>
<!-- Option to always use the selected application resolution in the future. See the "Complete action using" dialog title-->
<string name="alwaysUse">Use by default for this action.</string>
+ <!-- Title of the list of alternate options to complete an action shown when the
+ last used option is being displayed separately. -->
+ <string name="use_a_different_app">Use a different app</string>
<!-- Text displayed when the user selects the check box for setting default application. See the "Use by default for this action" check box. -->
<string name="clearDefaultHintMsg">Clear default in System settings > Apps > Downloaded.</string>
<!-- Default title for the activity chooser, when one is not given. Android allows multiple activities to perform an action. for example, there may be many ringtone pickers installed. A dialog is shown to the user allowing him to pick which activity should be used. This is the title. -->
@@ -4874,4 +4877,19 @@
<!-- [CHAR_LIMIT=NONE] Zen mode: Condition summary for built-in downtime condition, if active -->
<string name="downtime_condition_summary">Until your downtime ends at <xliff:g id="formattedTime" example="10.00 PM">%1$s</xliff:g></string>
+
+ <!-- Zen mode condition: time duration in minutes. [CHAR LIMIT=NONE] -->
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one">For one minute</item>
+ <item quantity="other">For %d minutes</item>
+ </plurals>
+
+ <!-- Zen mode condition: time duration in hours. [CHAR LIMIT=NONE] -->
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one">For one hour</item>
+ <item quantity="other">For %d hours</item>
+ </plurals>
+
+ <!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_forever">Indefinitely</string>
</resources>
diff --git a/core/res/res/values/styles_leanback.xml b/core/res/res/values/styles_leanback.xml
index 7606c86..aaeaadd 100644
--- a/core/res/res/values/styles_leanback.xml
+++ b/core/res/res/values/styles_leanback.xml
@@ -36,24 +36,28 @@
<!-- Setup and form wizard themes -->
<style name="TextAppearance.Leanback.FormWizard" parent="@style/TextAppearance.Material">
<item name="textSize">18sp</item>
+ <item name="lineSpacingExtra">24sp</item>
<item name="fontFamily">sans-serif-light</item>
<item name="textColor">?attr/textColorPrimary</item>
</style>
<style name="TextAppearance.Leanback.FormWizard.Small" parent="@style/TextAppearance.Material.Small">
- <item name="textSize">18sp</item>
+ <item name="textSize">14sp</item>
+ <item name="lineSpacingExtra">24sp</item>
<item name="fontFamily">sans-serif-light</item>
<item name="textColor">?attr/textColorPrimary</item>
</style>
<style name="TextAppearance.Leanback.FormWizard.Medium" parent="@style/TextAppearance.Material.Medium">
<item name="textSize">36sp</item>
+ <item name="lineSpacingExtra">40sp</item>
<item name="fontFamily">sans-serif-thin</item>
<item name="textColor">?attr/textColorPrimary</item>
</style>
<style name="TextAppearance.Leanback.FormWizard.Large" parent="@style/TextAppearance.Material.Large">
- <item name="textSize">56sp</item>
+ <item name="textSize">42sp</item>
+ <item name="lineSpacingExtra">48sp</item>
<item name="fontFamily">sans-serif-thin</item>
<item name="textColor">?attr/textColorPrimary</item>
</style>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index a7335af..26c7d10 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -474,6 +474,13 @@
<item name="stateListAnimator">@anim/disabled_anim_material</item>
</style>
+ <!-- Alert dialog button bar button -->
+ <style name="Widget.Material.Button.ButtonBar.AlertDialog" parent="Widget.Material.Button.Borderless.Colored">
+ <item name="minWidth">64dp</item>
+ <item name="maxLines">2</item>
+ <item name="minHeight">@dimen/alert_dialog_button_bar_height</item>
+ </style>
+
<!-- Small borderless ink button -->
<style name="Widget.Material.Button.Borderless.Small">
<item name="minHeight">48dip</item>
@@ -496,7 +503,6 @@
<style name="Widget.Material.ButtonBar.AlertDialog">
<item name="background">@null</item>
- <item name="minHeight">@dimen/alert_dialog_button_bar_height</item>
</style>
<style name="Widget.Material.SearchView">
@@ -936,6 +942,7 @@
<style name="Widget.Material.Light.Button.Small" parent="Widget.Material.Button.Small"/>
<style name="Widget.Material.Light.Button.Borderless" parent="Widget.Material.Button.Borderless"/>
<style name="Widget.Material.Light.Button.Borderless.Colored" parent="Widget.Material.Button.Borderless.Colored"/>
+ <style name="Widget.Material.Light.Button.ButtonBar.AlertDialog" parent="Widget.Material.Button.ButtonBar.AlertDialog" />
<style name="Widget.Material.Light.Button.Borderless.Small" parent="Widget.Material.Button.Borderless.Small"/>
<style name="Widget.Material.Light.Button.Inset" parent="Widget.Material.Button.Inset"/>
<style name="Widget.Material.Light.Button.Toggle" parent="Widget.Material.Button.Toggle" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 01e6e76..7fc522f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -293,7 +293,10 @@
<java-symbol type="bool" name="config_windowIsRound" />
<java-symbol type="bool" name="config_hasRecents" />
<java-symbol type="bool" name="config_windowShowCircularMask" />
-
+ <java-symbol type="bool" name="config_windowEnableCircularEmulatorDisplayOverlay" />
+ <java-symbol type="bool" name="config_wifi_framework_enable_associated_autojoin_scan" />
+ <java-symbol type="bool" name="config_wifi_framework_enable_associated_network_selection" />
+ <java-symbol type="bool" name="config_wifi_only_link_same_credential_configurations" />
<java-symbol type="integer" name="config_bluetooth_max_advertisers" />
<java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
<java-symbol type="integer" name="config_cursorWindowSize" />
@@ -312,6 +315,7 @@
<java-symbol type="integer" name="config_shortPressOnPowerBehavior" />
<java-symbol type="integer" name="config_toastDefaultGravity" />
<java-symbol type="integer" name="config_wifi_framework_scan_interval" />
+ <java-symbol type="integer" name="config_wifi_framework_associated_scan_interval" />
<java-symbol type="integer" name="config_wifi_supplicant_scan_interval" />
<java-symbol type="integer" name="config_wifi_scan_interval_p2p_connected" />
<java-symbol type="integer" name="db_connection_pool_size" />
@@ -1155,6 +1159,7 @@
<java-symbol type="drawable" name="ic_corp_badge" />
<java-symbol type="drawable" name="ic_corp_icon_badge" />
<java-symbol type="drawable" name="ic_corp_icon" />
+ <java-symbol type="drawable" name="emulator_circular_window_overlay" />
<java-symbol type="drawable" name="sim_light_blue" />
<java-symbol type="drawable" name="sim_light_green" />
@@ -1915,6 +1920,9 @@
<java-symbol type="string" name="timepicker_transition_end_radius_multiplier" />
<java-symbol type="string" name="battery_saver_description" />
<java-symbol type="string" name="downtime_condition_summary" />
+ <java-symbol type="string" name="zen_mode_forever" />
+ <java-symbol type="plurals" name="zen_mode_duration_minutes" />
+ <java-symbol type="plurals" name="zen_mode_duration_hours" />
<java-symbol type="string" name="item_is_selected" />
<java-symbol type="string" name="day_of_week_label_typeface" />
@@ -2004,4 +2012,7 @@
<java-symbol type="bool" name="config_auto_attach_data_on_creation" />
<java-symbol type="id" name="date_picker_month_day_year_layout" />
<java-symbol type="attr" name="closeItemLayout" />
+ <java-symbol type="layout" name="resolver_different_item_header" />
+ <java-symbol type="array" name="config_default_vm_number" />
+ <java-symbol type="integer" name="config_cdma_3waycall_flash_delay"/>
</resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index ab5cd5a..485ea08 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -333,7 +333,7 @@
<item name="dividerVertical">?attr/listDivider</item>
<item name="dividerHorizontal">?attr/listDivider</item>
<item name="buttonBarStyle">@style/Widget.Material.ButtonBar</item>
- <item name="buttonBarButtonStyle">@style/Widget.Material.Button.Borderless.Colored</item>
+ <item name="buttonBarButtonStyle">@style/Widget.Material.Button.ButtonBar.AlertDialog</item>
<item name="segmentedButtonStyle">@style/Widget.Material.SegmentedButton</item>
<!-- SearchView attributes -->
@@ -679,7 +679,7 @@
<item name="dividerVertical">?attr/listDivider</item>
<item name="dividerHorizontal">?attr/listDivider</item>
<item name="buttonBarStyle">@style/Widget.Material.Light.ButtonBar</item>
- <item name="buttonBarButtonStyle">@style/Widget.Material.Light.Button.Borderless.Colored</item>
+ <item name="buttonBarButtonStyle">@style/Widget.Material.Light.Button.ButtonBar.AlertDialog</item>
<item name="segmentedButtonStyle">@style/Widget.Material.Light.SegmentedButton</item>
<!-- SearchView attributes -->
@@ -1256,7 +1256,4 @@
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
<item name="colorAccent">@color/material_deep_teal_500</item>
</style>
-
- <!-- TODO: Spacer to be removed from here and public.xml -->
- <style name="__removed" />
</resources>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
index 77e1c530..80d5668 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
@@ -322,8 +322,13 @@
* If the device is already associated with a WiFi, disconnect and forget it,
* We don't verify whether the connection is successful or not, leave this to the test
*/
- protected boolean connectToWifi(String knownSSID) {
- WifiConfiguration config = WifiConfigurationHelper.createOpenConfig(knownSSID);
+ protected boolean connectToWifi(String ssid, String password) {
+ WifiConfiguration config;
+ if (password == null) {
+ config = WifiConfigurationHelper.createOpenConfig(ssid);
+ } else {
+ config = WifiConfigurationHelper.createPskConfig(ssid, password);
+ }
return connectToWifiWithConfiguration(config);
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
index b94306a..b6eb674 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
@@ -35,8 +35,9 @@
*/
public class ConnectivityManagerTestRunner extends InstrumentationTestRunner {
- public boolean mWifiOnlyFlag = false;
- public String mTestSsid = null;
+ public boolean mWifiOnly = false;
+ public String mSsid = null;
+ public String mPassword = null;
@Override
public TestSuite getAllTests() {
@@ -54,13 +55,29 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- String testSSID = (String) icicle.get("ssid");
- if (testSSID != null) {
- mTestSsid = testSSID;
+ String ssid = icicle.getString("ssid");
+ if (ssid != null) {
+ mSsid = ssid;
+ }
+ String password = (String) icicle.get("password");
+ if (password != null) {
+ mPassword = password;
}
String wifiOnlyFlag = (String) icicle.get("wifi-only");
if (wifiOnlyFlag != null) {
- mWifiOnlyFlag = true;
+ mWifiOnly = true;
}
}
+
+ public String getWifiSsid() {
+ return mSsid;
+ }
+
+ public String getWifiPassword() {
+ return mPassword;
+ }
+
+ public boolean isWifiOnly() {
+ return mWifiOnly;
+ }
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiAssociationTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiAssociationTestRunner.java
index 2354484..f4ea6f2 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiAssociationTestRunner.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiAssociationTestRunner.java
@@ -16,17 +16,12 @@
package com.android.connectivitymanagertest;
-import android.content.Context;
-import android.net.wifi.WifiManager;
-import android.os.Bundle;
import android.test.InstrumentationTestRunner;
import android.test.InstrumentationTestSuite;
-import android.util.Log;
import com.android.connectivitymanagertest.functional.WifiAssociationTest;
import junit.framework.TestSuite;
-import junit.framework.Assert;
/**
* Instrumentation Test Runner for wifi association test.
@@ -39,8 +34,6 @@
* -w com.android.connectivitymanagertest/.WifiAssociationTestRunner"
*/
public class WifiAssociationTestRunner extends InstrumentationTestRunner {
- private static final String TAG = "WifiAssociationTestRunner";
- public int mBand;
@Override
public TestSuite getAllTests() {
@@ -53,35 +46,4 @@
public ClassLoader getLoader() {
return WifiAssociationTestRunner.class.getClassLoader();
}
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- String mFrequencyBand = icicle.getString("frequency-band");
- if (mFrequencyBand != null) {
- setFrequencyBand(mFrequencyBand);
- }
- }
-
- private void setFrequencyBand(String band) {
- WifiManager mWifiManager = (WifiManager)getContext().getSystemService(Context.WIFI_SERVICE);
- if (band.equals("2.4")) {
- Log.v(TAG, "set frequency band to 2.4");
- mBand = WifiManager.WIFI_FREQUENCY_BAND_2GHZ;
- } else if (band.equals("5.0")) {
- Log.v(TAG, "set frequency band to 5.0");
- mBand = WifiManager.WIFI_FREQUENCY_BAND_5GHZ;
- } else if (band.equals("auto")) {
- Log.v(TAG, "set frequency band to auto");
- mBand = WifiManager.WIFI_FREQUENCY_BAND_AUTO;
- } else {
- Assert.fail("invalid frequency band");
- }
- int currentFreq = mWifiManager.getFrequencyBand();
- if (mBand == currentFreq) {
- Log.v(TAG, "frequency band has been set");
- return;
- }
- mWifiManager.setFrequencyBand(mBand, true);
- }
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index b280106..d5051df 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -33,7 +33,8 @@
super(ConnectivityManagerMobileTest.class.getSimpleName());
}
- private String mTestAccessPoint;
+ private String mSsid;
+ private String mPassword;
private boolean mWifiOnlyFlag;
@Override
@@ -41,8 +42,9 @@
super.setUp();
ConnectivityManagerTestRunner mRunner =
(ConnectivityManagerTestRunner)getInstrumentation();
- mTestAccessPoint = mRunner.mTestSsid;
- mWifiOnlyFlag = mRunner.mWifiOnlyFlag;
+ mSsid = mRunner.getWifiSsid();
+ mPassword = mRunner.getWifiPassword();
+ mWifiOnlyFlag = mRunner.isWifiOnly();
// Each test case will start with cellular connection
if (Settings.Global.getInt(getInstrumentation().getContext().getContentResolver(),
@@ -120,11 +122,10 @@
// Test case 2: test connection to a given AP
@LargeTest
public void testConnectToWifi() {
- assertNotNull("SSID is null", mTestAccessPoint);
+ assertNotNull("SSID is null", mSsid);
// assert that we are able to connect to the ap
- assertTrue("failed to connect to " + mTestAccessPoint,
- connectToWifi(mTestAccessPoint));
+ assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
// assert that WifiManager reports correct state
assertTrue("wifi not enabled", waitForWifiState(
WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
@@ -144,14 +145,14 @@
// Test case 3: connect & reconnect to Wifi with known AP
@LargeTest
public void testConnectToWifWithKnownAP() {
- assertNotNull("SSID is null", mTestAccessPoint);
+ assertNotNull("SSID is null", mSsid);
// enable WiFi
assertTrue("failed to enable wifi", enableWifi());
// wait for wifi enable
assertTrue("wifi not enabled", waitForWifiState(
WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
// Connect to AP
- assertTrue("failed to connect to " + mTestAccessPoint, connectToWifi(mTestAccessPoint));
+ assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
// verify wifi connected as reported by ConnectivityManager
assertTrue("wifi not connected", waitForNetworkState(
ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
@@ -191,7 +192,7 @@
// Test case 4: test disconnect and clear wifi settings
@LargeTest
public void testDisconnectWifi() {
- assertNotNull("SSID is null", mTestAccessPoint);
+ assertNotNull("SSID is null", mSsid);
// enable WiFi
assertTrue("failed to enable wifi", enableWifi());
@@ -199,8 +200,7 @@
assertTrue("wifi not enabled", waitForWifiState(
WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
// connect to Wifi
- assertTrue("failed to connect to " + mTestAccessPoint,
- connectToWifi(mTestAccessPoint));
+ assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
assertTrue("wifi not connected", waitForNetworkState(
ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
@@ -257,7 +257,7 @@
// Test case 6: test connectivity with airplane mode on but wifi enabled
@LargeTest
public void testDataConnectionOverAMWithWifi() {
- assertNotNull("SSID is null", mTestAccessPoint);
+ assertNotNull("SSID is null", mSsid);
// enable airplane mode
mCm.setAirplaneMode(true);
// assert there is active network connection after airplane mode disabled
@@ -265,8 +265,7 @@
waitUntilNoActiveNetworkConnection(LONG_TIMEOUT));
// connect to Wifi
- assertTrue("failed to connect to " + mTestAccessPoint,
- connectToWifi(mTestAccessPoint));
+ assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
assertTrue("wifi not connected", waitForNetworkState(
ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
// verify that connection actually works
@@ -280,15 +279,14 @@
@LargeTest
public void testDataConnectionWithWifiToAMToWifi () {
// connect to mTestAccessPoint
- assertNotNull("SSID is null", mTestAccessPoint);
+ assertNotNull("SSID is null", mSsid);
// enable WiFi
assertTrue("failed to enable wifi", enableWifi());
// wait for wifi enable
assertTrue("wifi not enabled", waitForWifiState(
WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
// connect to Wifi
- assertTrue("failed to connect to " + mTestAccessPoint,
- connectToWifi(mTestAccessPoint));
+ assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
assertTrue("wifi not connected", waitForNetworkState(
ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
@@ -313,15 +311,14 @@
// Test case 8: test wifi state change while connecting/disconnecting to/from an AP
@LargeTest
public void testWifiStateChange () {
- assertNotNull("SSID is null", mTestAccessPoint);
+ assertNotNull("SSID is null", mSsid);
// enable WiFi
assertTrue("failed to enable wifi", enableWifi());
// wait for wifi enable
assertTrue("wifi not enabled", waitForWifiState(
WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
// connect to Wifi
- assertTrue("failed to connect to " + mTestAccessPoint,
- connectToWifi(mTestAccessPoint));
+ assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
assertTrue("wifi not connected", waitForNetworkState(
ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
assertNotNull("not associated with any AP", mWifiManager.getConnectionInfo().getBSSID());
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
index c2b80dc..68f3179 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
@@ -16,14 +16,13 @@
package com.android.connectivitymanagertest.functional;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo.State;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.GroupCipher;
import android.net.wifi.WifiConfiguration.PairwiseCipher;
import android.net.wifi.WifiConfiguration.Protocol;
import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.test.suitebuilder.annotation.LargeTest;
@@ -39,13 +38,7 @@
* -w com.android.connectivitymanagertest/.WifiAssociationTestRunner"
*/
public class WifiAssociationTest extends ConnectivityManagerTestBase {
- private String mSsid = null;
- private String mPassword = null;
- private String mSecurityType = null;
- private String mFrequencyBand = null;
- private int mBand;
-
- enum SECURITY_TYPE {
+ private enum SecurityType {
OPEN, WEP64, WEP128, WPA_TKIP, WPA2_AES
}
@@ -53,86 +46,106 @@
super(WifiAssociationTest.class.getSimpleName());
}
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- WifiAssociationTestRunner runner = (WifiAssociationTestRunner)getInstrumentation();
- Bundle arguments = runner.getArguments();
- mSecurityType = arguments.getString("security-type");
- mSsid = arguments.getString("ssid");
- mPassword = arguments.getString("password");
- mFrequencyBand = arguments.getString("frequency-band");
- mBand = runner.mBand;
- assertNotNull("security type is empty", mSecurityType);
- assertNotNull("ssid is empty", mSsid);
- validateFrequencyBand();
-
- // enable wifi and verify wpa_supplicant is started
- assertTrue("enable Wifi failed", enableWifi());
- assertTrue("wifi not connected", waitForNetworkState(
- ConnectivityManager.TYPE_WIFI, State.CONNECTED, LONG_TIMEOUT));
- WifiInfo wi = mWifiManager.getConnectionInfo();
- assertNotNull("no active wifi info", wi);
- assertTrue("failed to ping wpa_supplicant ", mWifiManager.pingSupplicant());
- }
-
- private void validateFrequencyBand() {
- if (mFrequencyBand != null) {
- int currentFreq = mWifiManager.getFrequencyBand();
- logv("read frequency band: " + currentFreq);
- assertEquals("specified frequency band does not match operational band of WifiManager",
- currentFreq, mBand);
- }
- }
-
+ /**
+ * Test that the wifi can associate with a given access point.
+ */
@LargeTest
public void testWifiAssociation() {
- assertNotNull("no test ssid", mSsid);
+ WifiAssociationTestRunner runner = (WifiAssociationTestRunner) getInstrumentation();
+ Bundle arguments = runner.getArguments();
+
+ String ssid = arguments.getString("ssid");
+ assertNotNull("ssid is empty", ssid);
+
+ String securityTypeStr = arguments.getString("security-type");
+ assertNotNull("security-type is empty", securityTypeStr);
+ SecurityType securityType = SecurityType.valueOf(securityTypeStr);
+
+ String password = arguments.getString("password");
+
+ String freqStr = arguments.getString("frequency-band");
+ if (freqStr != null) {
+ setFrequencyBand(freqStr);
+ }
+
+ assertTrue("enable Wifi failed", enableWifi());
+ WifiInfo wi = mWifiManager.getConnectionInfo();
+ logv("%s", wi);
+ assertNotNull("no active wifi info", wi);
+
+ WifiConfiguration config = getConfig(ssid, securityType, password);
+
+ logv("Network config: %s", config.toString());
+ connectToWifi(config);
+ }
+
+ /**
+ * Set the frequency band and verify that it has been set.
+ */
+ private void setFrequencyBand(String frequencyBandStr) {
+ int frequencyBand = -1;
+ if ("2.4".equals(frequencyBandStr)) {
+ frequencyBand = WifiManager.WIFI_FREQUENCY_BAND_2GHZ;
+ } else if ("5.0".equals(frequencyBandStr)) {
+ frequencyBand = WifiManager.WIFI_FREQUENCY_BAND_5GHZ;
+ } else if ("auto".equals(frequencyBandStr)) {
+ frequencyBand = WifiManager.WIFI_FREQUENCY_BAND_AUTO;
+ } else {
+ fail("Invalid frequency-band");
+ }
+ if (mWifiManager.getFrequencyBand() != frequencyBand) {
+ logv("Set frequency band to %s", frequencyBandStr);
+ mWifiManager.setFrequencyBand(frequencyBand, true);
+ }
+ assertEquals("Specified frequency band does not match operational band",
+ frequencyBand, mWifiManager.getFrequencyBand());
+ }
+
+ /**
+ * Get the {@link WifiConfiguration} based on ssid, security, and password.
+ */
+ private WifiConfiguration getConfig(String ssid, SecurityType securityType, String password) {
+ logv("Security type is %s", securityType.toString());
+
WifiConfiguration config = null;
- SECURITY_TYPE security = SECURITY_TYPE.valueOf(mSecurityType);
- logv("Security type is " + security.toString());
- switch (security) {
- // set network configurations
+ switch (securityType) {
case OPEN:
- config = WifiConfigurationHelper.createOpenConfig(mSsid);
+ config = WifiConfigurationHelper.createOpenConfig(ssid);
break;
case WEP64:
- assertNotNull("password is empty", mPassword);
+ assertNotNull("password is empty", password);
// always use hex pair for WEP-40
- assertTrue(WifiConfigurationHelper.isHex(mPassword, 10));
- config = WifiConfigurationHelper.createWepConfig(mSsid, mPassword);
+ assertTrue(WifiConfigurationHelper.isHex(password, 10));
+ config = WifiConfigurationHelper.createWepConfig(ssid, password);
config.allowedGroupCiphers.set(GroupCipher.WEP40);
break;
case WEP128:
- assertNotNull("password is empty", mPassword);
+ assertNotNull("password is empty", password);
// always use hex pair for WEP-104
- assertTrue(WifiConfigurationHelper.isHex(mPassword, 26));
- config = WifiConfigurationHelper.createWepConfig(mSsid, mPassword);
+ assertTrue(WifiConfigurationHelper.isHex(password, 26));
+ config = WifiConfigurationHelper.createWepConfig(ssid, password);
config.allowedGroupCiphers.set(GroupCipher.WEP104);
break;
case WPA_TKIP:
- assertNotNull("password is empty", mPassword);
- config = WifiConfigurationHelper.createPskConfig(mSsid, mPassword);
+ assertNotNull("password is empty", password);
+ config = WifiConfigurationHelper.createPskConfig(ssid, password);
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
config.allowedProtocols.set(Protocol.WPA);
config.allowedPairwiseCiphers.set(PairwiseCipher.TKIP);
config.allowedGroupCiphers.set(GroupCipher.TKIP);
break;
case WPA2_AES:
- assertNotNull("password is empty", mPassword);
- config = WifiConfigurationHelper.createPskConfig(mSsid, mPassword);
+ assertNotNull("password is empty", password);
+ config = WifiConfigurationHelper.createPskConfig(ssid, password);
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
config.allowedProtocols.set(Protocol.RSN);
config.allowedPairwiseCiphers.set(PairwiseCipher.CCMP);
config.allowedGroupCiphers.set(GroupCipher.CCMP);
break;
default:
- fail("Not a valid security type: " + mSecurityType);
+ fail("Not a valid security type: " + securityType);
break;
}
- logv("network config: %s", config.toString());
- connectToWifi(config);
- // verify that connection actually works
- assertTrue("no network connectivity at end of test", checkNetworkConnectivity());
+ return config;
}
}
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java
index bcf2e45..db547e2 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java
@@ -60,10 +60,10 @@
super.setUp();
DownloadManagerTestRunner mRunner = (DownloadManagerTestRunner)getInstrumentation();
externalDownloadUriValue = normalizeUri(mRunner.externalDownloadUriValue);
- assertNotNull(externalDownloadUriValue);
+ assertNotNull("download url is null", externalDownloadUriValue);
externalLargeDownloadUriValue = normalizeUri(mRunner.externalDownloadUriValue);
- assertNotNull(externalLargeDownloadUriValue);
+ assertNotNull("large download url is null", externalLargeDownloadUriValue);
}
/**
@@ -140,7 +140,7 @@
dlRequest = mDownloadManager.enqueue(request);
waitForDownloadToStart(dlRequest);
- assertTrue(dlRequest != -1);
+ assertTrue("request id is -1 from download manager", dlRequest != -1);
// Store ID of download for later retrieval
outputFile = new DataOutputStream(fileOutput);
@@ -183,7 +183,7 @@
mContext.deleteFile(DOWNLOAD_STARTED_FLAG);
}
- assertTrue(dlRequest != -1);
+ assertTrue("request id is -1 from download manager", dlRequest != -1);
Cursor cursor = getCursor(dlRequest);
ParcelFileDescriptor pfd = null;
try {
@@ -193,7 +193,7 @@
int status = cursor.getInt(columnIndex);
int currentWaitTime = 0;
- assertTrue(waitForDownload(dlRequest, 15 * 60 * 1000));
+ assertTrue("download not finished", waitForDownload(dlRequest, 15 * 60 * 1000));
Log.i(LOG_TAG, "Verifying download information...");
// Verify specific info about the file (size, name, etc)...
@@ -233,7 +233,7 @@
dlRequest = mDownloadManager.enqueue(request);
// Rather large file, so wait up to 15 mins...
- assertTrue(waitForDownload(dlRequest, 15 * 60 * 1000));
+ assertTrue("download not finished", waitForDownload(dlRequest, 15 * 60 * 1000));
Cursor cursor = getCursor(dlRequest);
ParcelFileDescriptor pfd = null;
@@ -317,7 +317,7 @@
Log.i(LOG_TAG, "Turning on WiFi...");
setWiFiStateOn(true);
Log.i(LOG_TAG, "Waiting up to 10 minutes for download to complete...");
- assertTrue(waitForDownload(dlRequest, 10 * 60 * 1000));
+ assertTrue("download not finished", waitForDownload(dlRequest, 10 * 60 * 1000));
ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
verifyFileSize(pfd, filesize);
} finally {
@@ -385,7 +385,7 @@
setWiFiStateOn(true);
Log.i(LOG_TAG, "Waiting up to 10 minutes for download to complete...");
- assertTrue(waitForDownload(dlRequest, 10 * 60 * 1000));
+ assertTrue("download not finished", waitForDownload(dlRequest, 10 * 60 * 1000));
ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
verifyFileSize(pfd, filesize);
} finally {
@@ -456,7 +456,7 @@
setAirplaneModeOn(false);
Log.i(LOG_TAG, "Waiting up to 10 minutes for donwload to complete...");
- assertTrue(waitForDownload(dlRequest, 10 * 60 * 1000)); // wait up to 10 mins
+ assertTrue("download not finished", waitForDownload(dlRequest, 10 * 60 * 1000)); // wait up to 10 mins
ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
verifyFileSize(pfd, filesize);
} finally {
@@ -489,11 +489,11 @@
Request request = new Request(remoteUri);
request.setTitle(filename);
dlRequest = mDownloadManager.enqueue(request);
- assertTrue(dlRequest != -1);
+ assertTrue("request id is -1 from download manager", dlRequest != -1);
downloadIds.add(dlRequest);
}
- assertTrue(waitForMultipleDownloads(downloadIds, 15 * 60 * 2000)); // wait 15 mins max
+ assertTrue("download not finished", waitForMultipleDownloads(downloadIds, 15 * 60 * 2000)); // wait 15 mins max
} finally {
removeAllCurrentDownloads();
}
diff --git a/core/tests/inputmethodtests/run_core_inputmethod_test.sh b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
index ed8b7f7..a11e49b 100755
--- a/core/tests/inputmethodtests/run_core_inputmethod_test.sh
+++ b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
@@ -15,7 +15,7 @@
if [[ $rebuild == true ]]; then
make -j4 FrameworksCoreInputMethodTests
- TESTAPP=${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreInputMethodTests.apk
+ TESTAPP=${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreInputMethodTests/FrameworksCoreInputMethodTests.apk
COMMAND="adb install -r $TESTAPP"
echo $COMMAND
$COMMAND
diff --git a/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java b/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java
index cc4a7c4..d4244ba 100644
--- a/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java
+++ b/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java
@@ -26,14 +26,12 @@
import java.util.Objects;
-import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_FULLY_VISIBLE;
-import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_INVISIBLE;
-import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_NOT_FEASIBLE;
-import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE;
-import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_UNSPECIFIED;
+import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
+import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
+import static android.view.inputmethod.CursorAnchorInfo.FLAG_IS_RTL;
public class CursorAnchorInfoTest extends InstrumentationTestCase {
- private static final RectF[] MANY_RECTS = new RectF[] {
+ private static final RectF[] MANY_BOUNDS = new RectF[] {
new RectF(101.0f, 201.0f, 301.0f, 401.0f),
new RectF(102.0f, 202.0f, 302.0f, 402.0f),
new RectF(103.0f, 203.0f, 303.0f, 403.0f),
@@ -55,25 +53,25 @@
new RectF(119.0f, 219.0f, 319.0f, 419.0f),
};
private static final int[] MANY_FLAGS_ARRAY = new int[] {
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_INVISIBLE,
- CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_NOT_FEASIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_NOT_FEASIBLE,
- CHARACTER_RECT_TYPE_NOT_FEASIBLE,
+ FLAG_HAS_INVISIBLE_REGION,
+ FLAG_HAS_INVISIBLE_REGION | FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+ FLAG_HAS_INVISIBLE_REGION | FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+ FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL,
+ FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_INVISIBLE_REGION,
+ FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL,
};
@SmallTest
@@ -82,11 +80,13 @@
final int SELECTION_END = 40;
final int COMPOSING_TEXT_START = 32;
final String COMPOSING_TEXT = "test";
- final boolean INSERTION_MARKER_CLIPPED = true;
+ final int INSERTION_MARKER_FLAGS =
+ FLAG_HAS_VISIBLE_REGION | FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL;
final float INSERTION_MARKER_HORIZONTAL = 10.5f;
final float INSERTION_MARKER_TOP = 100.1f;
final float INSERTION_MARKER_BASELINE = 110.4f;
final float INSERTION_MARKER_BOTOM = 111.0f;
+
Matrix TRANSFORM_MATRIX = new Matrix(Matrix.IDENTITY_MATRIX);
TRANSFORM_MATRIX.setScale(10.0f, 20.0f);
@@ -94,13 +94,13 @@
builder.setSelectionRange(SELECTION_START, SELECTION_END)
.setComposingText(COMPOSING_TEXT_START, COMPOSING_TEXT)
.setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP,
- INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM,
- INSERTION_MARKER_CLIPPED)
+ INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_FLAGS)
.setMatrix(TRANSFORM_MATRIX);
- for (int i = 0; i < MANY_RECTS.length; i++) {
- final RectF rect = MANY_RECTS[i];
+ for (int i = 0; i < MANY_BOUNDS.length; i++) {
+ final RectF bounds = MANY_BOUNDS[i];
final int flags = MANY_FLAGS_ARRAY[i];
- builder.addCharacterRect(i, rect.left, rect.top, rect.right, rect.bottom, flags);
+ builder.addCharacterBounds(i, bounds.left, bounds.top, bounds.right, bounds.bottom,
+ flags);
}
final CursorAnchorInfo info = builder.build();
@@ -108,26 +108,24 @@
assertEquals(SELECTION_END, info.getSelectionEnd());
assertEquals(COMPOSING_TEXT_START, info.getComposingTextStart());
assertTrue(TextUtils.equals(COMPOSING_TEXT, info.getComposingText()));
- assertTrue(info.isInsertionMarkerClipped());
+ assertEquals(INSERTION_MARKER_FLAGS, info.getInsertionMarkerFlags());
assertEquals(INSERTION_MARKER_HORIZONTAL, info.getInsertionMarkerHorizontal());
assertEquals(INSERTION_MARKER_TOP, info.getInsertionMarkerTop());
assertEquals(INSERTION_MARKER_BASELINE, info.getInsertionMarkerBaseline());
assertEquals(INSERTION_MARKER_BOTOM, info.getInsertionMarkerBottom());
assertEquals(TRANSFORM_MATRIX, info.getMatrix());
- for (int i = 0; i < MANY_RECTS.length; i++) {
- final RectF expectedRect = MANY_RECTS[i];
- assertEquals(expectedRect, info.getCharacterRect(i));
+ for (int i = 0; i < MANY_BOUNDS.length; i++) {
+ final RectF expectedBounds = MANY_BOUNDS[i];
+ assertEquals(expectedBounds, info.getCharacterBounds(i));
}
- assertNull(info.getCharacterRect(-1));
- assertNull(info.getCharacterRect(MANY_RECTS.length + 1));
+ assertNull(info.getCharacterBounds(-1));
+ assertNull(info.getCharacterBounds(MANY_BOUNDS.length + 1));
for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
final int expectedFlags = MANY_FLAGS_ARRAY[i];
- assertEquals(expectedFlags, info.getCharacterRectFlags(i));
+ assertEquals(expectedFlags, info.getCharacterBoundsFlags(i));
}
- assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
- info.getCharacterRectFlags(-1));
- assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
- info.getCharacterRectFlags(MANY_RECTS.length + 1));
+ assertEquals(0, info.getCharacterBoundsFlags(-1));
+ assertEquals(0, info.getCharacterBoundsFlags(MANY_BOUNDS.length + 1));
// Make sure that the builder can reproduce the same object.
final CursorAnchorInfo info2 = builder.build();
@@ -135,25 +133,24 @@
assertEquals(SELECTION_END, info2.getSelectionEnd());
assertEquals(COMPOSING_TEXT_START, info2.getComposingTextStart());
assertTrue(TextUtils.equals(COMPOSING_TEXT, info2.getComposingText()));
- assertTrue(info2.isInsertionMarkerClipped());
+ assertEquals(INSERTION_MARKER_FLAGS, info2.getInsertionMarkerFlags());
assertEquals(INSERTION_MARKER_HORIZONTAL, info2.getInsertionMarkerHorizontal());
assertEquals(INSERTION_MARKER_TOP, info2.getInsertionMarkerTop());
assertEquals(INSERTION_MARKER_BASELINE, info2.getInsertionMarkerBaseline());
assertEquals(INSERTION_MARKER_BOTOM, info2.getInsertionMarkerBottom());
assertEquals(TRANSFORM_MATRIX, info2.getMatrix());
- for (int i = 0; i < MANY_RECTS.length; i++) {
- final RectF expectedRect = MANY_RECTS[i];
- assertEquals(expectedRect, info2.getCharacterRect(i));
+ for (int i = 0; i < MANY_BOUNDS.length; i++) {
+ final RectF expectedBounds = MANY_BOUNDS[i];
+ assertEquals(expectedBounds, info2.getCharacterBounds(i));
}
- assertNull(info2.getCharacterRect(-1));
- assertNull(info2.getCharacterRect(MANY_RECTS.length + 1));
+ assertNull(info2.getCharacterBounds(-1));
+ assertNull(info2.getCharacterBounds(MANY_BOUNDS.length + 1));
for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
final int expectedFlags = MANY_FLAGS_ARRAY[i];
- assertEquals(expectedFlags, info2.getCharacterRectFlags(i));
+ assertEquals(expectedFlags, info2.getCharacterBoundsFlags(i));
}
- assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, info2.getCharacterRectFlags(-1));
- assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
- info2.getCharacterRectFlags(MANY_RECTS.length + 1));
+ assertEquals(0, info2.getCharacterBoundsFlags(-1));
+ assertEquals(0, info2.getCharacterBoundsFlags(MANY_BOUNDS.length + 1));
assertEquals(info, info2);
assertEquals(info.hashCode(), info2.hashCode());
@@ -163,25 +160,24 @@
assertEquals(SELECTION_END, info3.getSelectionEnd());
assertEquals(COMPOSING_TEXT_START, info3.getComposingTextStart());
assertTrue(TextUtils.equals(COMPOSING_TEXT, info3.getComposingText()));
- assertTrue(info3.isInsertionMarkerClipped());
+ assertEquals(INSERTION_MARKER_FLAGS, info3.getInsertionMarkerFlags());
assertEquals(INSERTION_MARKER_HORIZONTAL, info3.getInsertionMarkerHorizontal());
assertEquals(INSERTION_MARKER_TOP, info3.getInsertionMarkerTop());
assertEquals(INSERTION_MARKER_BASELINE, info3.getInsertionMarkerBaseline());
assertEquals(INSERTION_MARKER_BOTOM, info3.getInsertionMarkerBottom());
assertEquals(TRANSFORM_MATRIX, info3.getMatrix());
- for (int i = 0; i < MANY_RECTS.length; i++) {
- final RectF expectedRect = MANY_RECTS[i];
- assertEquals(expectedRect, info3.getCharacterRect(i));
+ for (int i = 0; i < MANY_BOUNDS.length; i++) {
+ final RectF expectedBounds = MANY_BOUNDS[i];
+ assertEquals(expectedBounds, info3.getCharacterBounds(i));
}
- assertNull(info3.getCharacterRect(-1));
- assertNull(info3.getCharacterRect(MANY_RECTS.length + 1));
+ assertNull(info3.getCharacterBounds(-1));
+ assertNull(info3.getCharacterBounds(MANY_BOUNDS.length + 1));
for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
final int expectedFlags = MANY_FLAGS_ARRAY[i];
- assertEquals(expectedFlags, info3.getCharacterRectFlags(i));
+ assertEquals(expectedFlags, info3.getCharacterBoundsFlags(i));
}
- assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, info3.getCharacterRectFlags(-1));
- assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
- info3.getCharacterRectFlags(MANY_RECTS.length + 1));
+ assertEquals(0, info3.getCharacterBoundsFlags(-1));
+ assertEquals(0, info3.getCharacterBoundsFlags(MANY_BOUNDS.length + 1));
assertEquals(info.hashCode(), info3.hashCode());
builder.reset();
@@ -190,7 +186,7 @@
assertEquals(-1, uninitializedInfo.getSelectionEnd());
assertEquals(-1, uninitializedInfo.getComposingTextStart());
assertNull(uninitializedInfo.getComposingText());
- assertFalse(uninitializedInfo.isInsertionMarkerClipped());
+ assertEquals(0, uninitializedInfo.getInsertionMarkerFlags());
assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerHorizontal());
assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerTop());
assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBaseline());
@@ -218,7 +214,7 @@
final int SELECTION_END1 = 7;
final String COMPOSING_TEXT1 = "0123456789";
final int COMPOSING_TEXT_START1 = 0;
- final boolean INSERTION_MARKER_CLIPPED1 = true;
+ final int INSERTION_MARKER_FLAGS1 = FLAG_HAS_VISIBLE_REGION;
final float INSERTION_MARKER_HORIZONTAL1 = 10.5f;
final float INSERTION_MARKER_TOP1 = 100.1f;
final float INSERTION_MARKER_BASELINE1 = 110.4f;
@@ -227,7 +223,8 @@
final int SELECTION_END2 = 8;
final String COMPOSING_TEXT2 = "9876543210";
final int COMPOSING_TEXT_START2 = 3;
- final boolean INSERTION_MARKER_CLIPPED2 = false;
+ final int INSERTION_MARKER_FLAGS2 =
+ FLAG_HAS_VISIBLE_REGION | FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL;
final float INSERTION_MARKER_HORIZONTAL2 = 14.5f;
final float INSERTION_MARKER_TOP2 = 200.1f;
final float INSERTION_MARKER_BASELINE2 = 210.4f;
@@ -265,10 +262,10 @@
assertEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
Float.NaN, Float.NaN, Float.NaN, Float.NaN,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
Float.NaN, Float.NaN, Float.NaN, Float.NaN,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
// Check Matrix.
assertEquals(
@@ -290,74 +287,74 @@
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
assertNotEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
Float.NaN, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
assertNotEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
assertNotEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP2,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
assertNotEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE2, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
assertNotEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
assertNotEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM2,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
assertNotEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED2).build());
+ INSERTION_MARKER_FLAGS2).build());
}
@SmallTest
@@ -394,7 +391,7 @@
final int SELECTION_END = 40;
final int COMPOSING_TEXT_START = 32;
final String COMPOSING_TEXT = "test";
- final boolean INSERTION_MARKER_CLIPPED = true;
+ final int INSERTION_MARKER_FLAGS = FLAG_HAS_VISIBLE_REGION;
final float INSERTION_MARKER_HORIZONTAL = 10.5f;
final float INSERTION_MARKER_TOP = 100.1f;
final float INSERTION_MARKER_BASELINE = 110.4f;
@@ -416,7 +413,7 @@
}
builder.setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP,
- INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_CLIPPED);
+ INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_FLAGS);
try {
// Coordinate transformation matrix is required if no positional information is
// specified.
@@ -438,19 +435,10 @@
}
@SmallTest
- public void testBuilderAddCharacterRect() throws Exception {
+ public void testBuilderAddCharacterBounds() throws Exception {
// A negative index should be rejected.
try {
- new Builder().addCharacterRect(-1, 0.0f, 0.0f, 0.0f, 0.0f,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE);
- assertTrue(false);
- } catch (IllegalArgumentException ex) {
- }
-
- // CHARACTER_RECT_TYPE_UNSPECIFIED is not allowed.
- try {
- new Builder().addCharacterRect(0, 0.0f, 0.0f, 0.0f, 0.0f,
- CHARACTER_RECT_TYPE_UNSPECIFIED);
+ new Builder().addCharacterBounds(-1, 0.0f, 0.0f, 0.0f, 0.0f, FLAG_HAS_VISIBLE_REGION);
assertTrue(false);
} catch (IllegalArgumentException ex) {
}
diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
index fa1bd8f..30eb939 100644
--- a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
@@ -16,8 +16,6 @@
package android.os;
-import com.android.internal.inputmethod.InputMethodUtils;
-
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
@@ -26,15 +24,27 @@
import android.test.suitebuilder.annotation.SmallTest;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
+import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
+
+import com.android.internal.inputmethod.InputMethodUtils;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
public class InputMethodTest extends InstrumentationTestCase {
private static final boolean IS_AUX = true;
private static final boolean IS_DEFAULT = true;
private static final boolean IS_AUTO = true;
+ private static final boolean IS_ASCII_CAPABLE = true;
+ private static final boolean IS_SYSTEM_READY = true;
private static final ArrayList<InputMethodSubtype> NO_SUBTYPE = null;
+ private static final Locale LOCALE_EN_US = new Locale("en", "US");
+ private static final Locale LOCALE_EN_GB = new Locale("en", "GB");
+ private static final Locale LOCALE_EN_IN = new Locale("en", "IN");
+ private static final Locale LOCALE_HI = new Locale("hi");
@SmallTest
public void testDefaultEnabledImesWithDefaultVoiceIme() throws Exception {
@@ -44,22 +54,79 @@
imis.add(createNonDefaultAutoDummyVoiceIme0());
imis.add(createNonDefaultAutoDummyVoiceIme1());
imis.add(createNonDefaultDummyVoiceIme2());
- imis.add(createDefaultDummyEnUSKeyboardIme());
+ imis.add(createDefaultDummyLatinKeyboardIme());
imis.add(createNonDefaultDummyJaJPKeyboardIme());
imis.add(createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes());
- final ArrayList<InputMethodInfo> enabledImis = InputMethodUtils.getDefaultEnabledImes(
- context, true, imis);
- assertEquals(2, enabledImis.size());
- for (int i = 0; i < enabledImis.size(); ++i) {
- final InputMethodInfo imi = enabledImis.get(0);
- // "DummyDefaultAutoVoiceIme" and "DummyDefaultEnKeyboardIme"
- if (imi.getPackageName().equals("DummyDefaultAutoVoiceIme")
- || imi.getPackageName().equals("DummyDefaultEnKeyboardIme")) {
- continue;
- } else {
- fail("Invalid enabled subtype.");
- }
- }
+ imis.add(createDefaultDummyHinglishKeyboardIme());
+
+ // locale: en_US, system: not ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemNotReadyLocaleEnUs =
+ callGetDefaultEnabledImesUnderWithLocale(context, !IS_SYSTEM_READY, imis,
+ LOCALE_EN_US);
+ assertEquals(toSet("DummyDefaultAutoVoiceIme", "DummyDefaultEnKeyboardIme",
+ "DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1",
+ "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemNotReadyLocaleEnUs));
+
+ // locale: en_US, system: ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemReadyLocaleEnUs =
+ callGetDefaultEnabledImesUnderWithLocale(context, IS_SYSTEM_READY, imis,
+ LOCALE_EN_US);
+ assertEquals(toSet("DummyDefaultAutoVoiceIme", "DummyDefaultEnKeyboardIme",
+ "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemReadyLocaleEnUs));
+
+ // locale: en_GB, system: not ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemNotReadyLocaleEnGB =
+ callGetDefaultEnabledImesUnderWithLocale(context, !IS_SYSTEM_READY, imis,
+ LOCALE_EN_GB);
+ assertEquals(toSet("DummyDefaultAutoVoiceIme", "DummyDefaultEnKeyboardIme",
+ "DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1",
+ "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemNotReadyLocaleEnGB));
+
+ // locale: en_GB, system: ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemReadyLocaleEnGB =
+ callGetDefaultEnabledImesUnderWithLocale(context, IS_SYSTEM_READY, imis,
+ LOCALE_EN_GB);
+ assertEquals(toSet("DummyDefaultAutoVoiceIme", "DummyDefaultEnKeyboardIme",
+ "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemReadyLocaleEnGB));
+
+ // locale: en_IN, system: not ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemNotReadyLocaleEnIN =
+ callGetDefaultEnabledImesUnderWithLocale(context, !IS_SYSTEM_READY, imis,
+ LOCALE_EN_IN);
+ assertEquals(toSet("DummyDefaultAutoVoiceIme", "DummyDefaultEnKeyboardIme",
+ "DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1",
+ "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemNotReadyLocaleEnIN));
+
+ // locale: en_IN, system: ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemReadyLocaleEnIN =
+ callGetDefaultEnabledImesUnderWithLocale(context, IS_SYSTEM_READY, imis,
+ LOCALE_EN_IN);
+ assertEquals(toSet("DummyDefaultAutoVoiceIme", "DummyDefaultEnKeyboardIme",
+ "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemReadyLocaleEnIN));
+
+ // locale: hi, system: not ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemNotReadyLocaleHi =
+ callGetDefaultEnabledImesUnderWithLocale(context, !IS_SYSTEM_READY, imis,
+ LOCALE_HI);
+ assertEquals(toSet("DummyDefaultAutoVoiceIme", "DummyDefaultEnKeyboardIme",
+ "DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1",
+ "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemNotReadyLocaleHi));
+
+ // locale: hi, system: ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemReadyLocaleHi =
+ callGetDefaultEnabledImesUnderWithLocale(context, IS_SYSTEM_READY, imis,
+ LOCALE_HI);
+ assertEquals(toSet("DummyDefaultAutoVoiceIme", "DummyDefaultEnKeyboardIme",
+ "DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1",
+ "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemReadyLocaleHi));
}
@SmallTest
@@ -69,24 +136,74 @@
imis.add(createNonDefaultAutoDummyVoiceIme0());
imis.add(createNonDefaultAutoDummyVoiceIme1());
imis.add(createNonDefaultDummyVoiceIme2());
- imis.add(createDefaultDummyEnUSKeyboardIme());
+ imis.add(createDefaultDummyLatinKeyboardIme());
imis.add(createNonDefaultDummyJaJPKeyboardIme());
imis.add(createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes());
- final ArrayList<InputMethodInfo> enabledImis = InputMethodUtils.getDefaultEnabledImes(
- context, true, imis);
- assertEquals(3, enabledImis.size());
- for (int i = 0; i < enabledImis.size(); ++i) {
- final InputMethodInfo imi = enabledImis.get(0);
- // "DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1" and
- // "DummyDefaultEnKeyboardIme"
- if (imi.getPackageName().equals("DummyNonDefaultAutoVoiceIme0")
- || imi.getPackageName().equals("DummyNonDefaultAutoVoiceIme1")
- || imi.getPackageName().equals("DummyDefaultEnKeyboardIme")) {
- continue;
- } else {
- fail("Invalid enabled subtype.");
- }
- }
+ imis.add(createDefaultDummyHinglishKeyboardIme());
+
+ // locale: en_US, system: not ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemNotReadyLocaleEnUs =
+ callGetDefaultEnabledImesUnderWithLocale(context, !IS_SYSTEM_READY, imis,
+ LOCALE_EN_US);
+ assertEquals(toSet("DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1",
+ "DummyDefaultEnKeyboardIme", "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemNotReadyLocaleEnUs));
+
+ // locale: en_US, system: ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemReadyLocaleEnUs =
+ callGetDefaultEnabledImesUnderWithLocale(context, IS_SYSTEM_READY, imis,
+ LOCALE_EN_US);
+ assertEquals(toSet("DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1",
+ "DummyDefaultEnKeyboardIme", "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemReadyLocaleEnUs));
+
+ // locale: en_GB, system: not ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemNotReadyLocaleEnGB =
+ callGetDefaultEnabledImesUnderWithLocale(context, !IS_SYSTEM_READY, imis,
+ LOCALE_EN_GB);
+ assertEquals(toSet("DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1",
+ "DummyDefaultEnKeyboardIme", "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemNotReadyLocaleEnGB));
+
+ // locale: en_GB, system: ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemReadyLocaleEnGB =
+ callGetDefaultEnabledImesUnderWithLocale(context, IS_SYSTEM_READY, imis,
+ LOCALE_EN_GB);
+ assertEquals(toSet("DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1",
+ "DummyDefaultEnKeyboardIme", "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemReadyLocaleEnGB));
+
+ // locale: en_IN, system: not ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemNotReadyLocaleEnIN =
+ callGetDefaultEnabledImesUnderWithLocale(context, !IS_SYSTEM_READY, imis,
+ LOCALE_EN_IN);
+ assertEquals(toSet("DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1",
+ "DummyDefaultEnKeyboardIme", "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemNotReadyLocaleEnIN));
+
+ // locale: en_IN, system: ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemReadyLocaleEnIN =
+ callGetDefaultEnabledImesUnderWithLocale(context, IS_SYSTEM_READY, imis,
+ LOCALE_EN_IN);
+ assertEquals(toSet("DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1",
+ "DummyDefaultEnKeyboardIme", "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemReadyLocaleEnIN));
+
+ // locale: hi, system: not ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemNotReadyLocaleHi =
+ callGetDefaultEnabledImesUnderWithLocale(context, !IS_SYSTEM_READY, imis,
+ LOCALE_HI);
+ assertEquals(toSet("DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1",
+ "DummyDefaultEnKeyboardIme", "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemNotReadyLocaleHi));
+
+ // locale: hi, system: ready
+ final ArrayList<InputMethodInfo> enabledImisForSystemReadyLocaleHi =
+ callGetDefaultEnabledImesUnderWithLocale(context, IS_SYSTEM_READY, imis,
+ LOCALE_HI);
+ assertEquals(toSet("DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1",
+ "DummyDefaultEnKeyboardIme", "DummyDefaultHinglishKeyboardIme"),
+ getPackageNames(enabledImisForSystemReadyLocaleHi));
}
@SmallTest
@@ -95,7 +212,7 @@
originalList.add(createNonDefaultAutoDummyVoiceIme0());
originalList.add(createNonDefaultAutoDummyVoiceIme1());
originalList.add(createNonDefaultDummyVoiceIme2());
- originalList.add(createDefaultDummyEnUSKeyboardIme());
+ originalList.add(createDefaultDummyLatinKeyboardIme());
originalList.add(createNonDefaultDummyJaJPKeyboardIme());
originalList.add(createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes());
@@ -127,6 +244,32 @@
}
}
+ private static ArrayList<InputMethodInfo> callGetDefaultEnabledImesUnderWithLocale(
+ final Context context, final boolean isSystemReady,
+ final ArrayList<InputMethodInfo> imis, final Locale locale) {
+ final Locale initialLocale = context.getResources().getConfiguration().locale;
+ try {
+ context.getResources().getConfiguration().setLocale(locale);
+ return InputMethodUtils.getDefaultEnabledImes(context, isSystemReady, imis);
+ } finally {
+ context.getResources().getConfiguration().setLocale(initialLocale);
+ }
+ }
+
+ @SafeVarargs
+ private static <T> HashSet<T> toSet(final T... xs) {
+ return new HashSet<T>(Arrays.asList(xs));
+ }
+
+ private HashSet<String> getPackageNames(final ArrayList<InputMethodInfo> imis) {
+ final HashSet<String> packageNames = new HashSet<>();
+ for (final InputMethodInfo imi : imis) {
+ final String actualPackageName = imi.getPackageName();
+ packageNames.add(actualPackageName);
+ }
+ return packageNames;
+ }
+
private static void verifyEquality(InputMethodInfo expected, InputMethodInfo actual) {
assertEquals(expected, actual);
assertEquals(expected.getSubtypeCount(), actual.getSubtypeCount());
@@ -158,52 +301,78 @@
}
private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode,
- boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) {
- return new InputMethodSubtype(0, 0, locale, mode, "", isAuxiliary,
- overridesImplicitlyEnabledSubtype);
+ boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype,
+ boolean isAsciiCapable) {
+ return new InputMethodSubtypeBuilder()
+ .setSubtypeNameResId(0)
+ .setSubtypeIconResId(0)
+ .setSubtypeLocale(locale)
+ .setSubtypeMode(mode)
+ .setSubtypeExtraValue("")
+ .setIsAuxiliary(isAuxiliary)
+ .setOverridesImplicitlyEnabledSubtype(overridesImplicitlyEnabledSubtype)
+ .setIsAsciiCapable(isAsciiCapable)
+ .build();
}
private static InputMethodInfo createDefaultAutoDummyVoiceIme() {
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
- subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO));
- subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO));
+ subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO,
+ !IS_ASCII_CAPABLE));
+ subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO,
+ !IS_ASCII_CAPABLE));
return createDummyInputMethodInfo("DummyDefaultAutoVoiceIme", "dummy.voice0",
"DummyVoice0", IS_AUX, IS_DEFAULT, subtypes);
}
private static InputMethodInfo createNonDefaultAutoDummyVoiceIme0() {
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
- subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO));
- subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO));
+ subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO,
+ !IS_ASCII_CAPABLE));
+ subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO,
+ !IS_ASCII_CAPABLE));
return createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme0", "dummy.voice1",
"DummyVoice1", IS_AUX, !IS_DEFAULT, subtypes);
}
private static InputMethodInfo createNonDefaultAutoDummyVoiceIme1() {
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
- subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO));
- subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO));
+ subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO,
+ !IS_ASCII_CAPABLE));
+ subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO,
+ !IS_ASCII_CAPABLE));
return createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme1", "dummy.voice2",
"DummyVoice2", IS_AUX, !IS_DEFAULT, subtypes);
}
private static InputMethodInfo createNonDefaultDummyVoiceIme2() {
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
- subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO));
+ subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO,
+ !IS_ASCII_CAPABLE));
return createDummyInputMethodInfo("DummyNonDefaultVoiceIme2", "dummy.voice3",
"DummyVoice3", IS_AUX, !IS_DEFAULT, subtypes);
}
- private static InputMethodInfo createDefaultDummyEnUSKeyboardIme() {
+ private static InputMethodInfo createDefaultDummyLatinKeyboardIme() {
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
- subtypes.add(createDummyInputMethodSubtype("en_US", "keyboard", !IS_AUX, !IS_AUTO));
+ subtypes.add(createDummyInputMethodSubtype("en_US", "keyboard", !IS_AUX, !IS_AUTO,
+ IS_ASCII_CAPABLE));
+ subtypes.add(createDummyInputMethodSubtype("en_GB", "keyboard", !IS_AUX, !IS_AUTO,
+ IS_ASCII_CAPABLE));
+ subtypes.add(createDummyInputMethodSubtype("en_IN", "keyboard", !IS_AUX, !IS_AUTO,
+ IS_ASCII_CAPABLE));
+ subtypes.add(createDummyInputMethodSubtype("hi", "keyboard", !IS_AUX, !IS_AUTO,
+ !IS_ASCII_CAPABLE)); // not AsciiCapable!
+ subtypes.add(createDummyInputMethodSubtype("hi_ZZ", "keyboard", !IS_AUX, !IS_AUTO,
+ IS_ASCII_CAPABLE));
return createDummyInputMethodInfo("DummyDefaultEnKeyboardIme", "dummy.keyboard0",
"DummyKeyboard0", !IS_AUX, IS_DEFAULT, subtypes);
}
private static InputMethodInfo createNonDefaultDummyJaJPKeyboardIme() {
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
- subtypes.add(createDummyInputMethodSubtype("ja_JP", "keyboard", !IS_AUX, !IS_AUTO));
+ subtypes.add(createDummyInputMethodSubtype("ja_JP", "keyboard", !IS_AUX, !IS_AUTO,
+ IS_ASCII_CAPABLE));
return createDummyInputMethodInfo("DummyNonDefaultJaJPKeyboardIme", "dummy.keyboard1",
"DummyKeyboard1", !IS_AUX, !IS_DEFAULT, subtypes);
}
@@ -215,4 +384,14 @@
return createDummyInputMethodInfo("DummyNonDefaultJaJPKeyboardImeWithoutSubtypes",
"dummy.keyboard2", "DummyKeyboard2", !IS_AUX, !IS_DEFAULT, NO_SUBTYPE);
}
+
+ private static InputMethodInfo createDefaultDummyHinglishKeyboardIme() {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(createDummyInputMethodSubtype("en_IN", "keyboard", !IS_AUX, !IS_AUTO,
+ IS_ASCII_CAPABLE));
+ subtypes.add(createDummyInputMethodSubtype("hi", "keyboard", !IS_AUX, !IS_AUTO,
+ !IS_ASCII_CAPABLE)); // not AsciiCapable!
+ return createDummyInputMethodInfo("DummyDefaultHinglishKeyboardIme", "dummy.keyboard2",
+ "DummyKeyboard2", !IS_AUX, IS_DEFAULT, subtypes);
+ }
}
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index cfc1484..f10ba96 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -405,6 +405,7 @@
# key 504 KEY_BRL_DOT8
key 580 APP_SWITCH
+key 582 VOICE_ASSIST
# Keys defined by HID usages
key usage 0x0c006F BRIGHTNESS_UP
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 1e5fc4d..808f04a 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -64,7 +64,7 @@
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on August 12, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on September 9, 2014.
<br/>Any versions with less than 0.1% distribution are not shown.</em>
</p>
@@ -95,7 +95,8 @@
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on August 12, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on September 9, 2014.
+
<br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
@@ -114,7 +115,7 @@
<img alt="" style="float:right"
-src="//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A0.1%2C80.2%2C19.7&chf=bg%2Cs%2C00000000&chl=GL%201.1%20only%7CGL%202.0%7CGL%203.0&chco=c4df9b%2C6fad0c" />
+src="//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A77.5%2C22.5&chf=bg%2Cs%2C00000000&chl=GL%202.0%7CGL%203.0&chco=c4df9b%2C6fad0c" />
<p>To declare which version of OpenGL ES your application requires, you should use the {@code
android:glEsVersion} attribute of the <a
@@ -131,22 +132,18 @@
<th scope="col">Distribution</th>
</tr>
<tr>
-<td>1.1 only</th>
-<td>0.1%</td>
+<td>2.0</td>
+<td>77.5%</td>
</tr>
<tr>
-<td>2.0</th>
-<td>80.2%</td>
-</tr>
-<tr>
-<td>3.0</th>
-<td>19.7%</td>
+<td>3.0</td>
+<td>22.5%</td>
</tr>
</table>
-<p style="clear:both"><em>Data collected during a 7-day period ending on August 12, 2014</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on September 9, 2014</em></p>
@@ -164,7 +161,7 @@
var VERSION_DATA =
[
{
- "chart": "//chart.googleapis.com/chart?cht=p&chs=500x250&chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chd=t%3A0.7%2C13.6%2C10.6%2C54.2%2C20.9&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c",
+ "chart": "//chart.googleapis.com/chart?chco=c4df9b%2C6fad0c&cht=p&chs=500x250&chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chd=t%3A0.7%2C11.4%2C9.6%2C53.8%2C24.5&chf=bg%2Cs%2C00000000",
"data": [
{
"api": 8,
@@ -174,41 +171,38 @@
{
"api": 10,
"name": "Gingerbread",
- "perc": "13.6"
+ "perc": "11.4"
},
{
"api": 15,
"name": "Ice Cream Sandwich",
- "perc": "10.6"
+ "perc": "9.6"
},
{
"api": 16,
"name": "Jelly Bean",
- "perc": "26.5"
+ "perc": "25.1"
},
{
"api": 17,
"name": "Jelly Bean",
- "perc": "19.8"
+ "perc": "20.7"
},
{
"api": 18,
"name": "Jelly Bean",
- "perc": "7.9"
+ "perc": "8.0"
},
{
"api": 19,
"name": "KitKat",
- "perc": "20.9"
+ "perc": "24.5"
}
]
}
];
-
-
-
var SCREEN_DATA =
[
{
@@ -216,27 +210,27 @@
"Large": {
"hdpi": "0.6",
"ldpi": "0.5",
- "mdpi": "4.2",
- "tvdpi": "1.6",
- "xhdpi": "0.5"
+ "mdpi": "4.3",
+ "tvdpi": "1.7",
+ "xhdpi": "0.6"
},
"Normal": {
- "hdpi": "35.5",
- "mdpi": "11.8",
- "xhdpi": "18.4",
- "xxhdpi": "15.2"
+ "hdpi": "35.7",
+ "mdpi": "10.6",
+ "xhdpi": "19.2",
+ "xxhdpi": "16.2"
},
"Small": {
- "ldpi": "7.4"
+ "ldpi": "6.2"
},
"Xlarge": {
"hdpi": "0.3",
- "mdpi": "3.6",
+ "mdpi": "3.7",
"xhdpi": "0.4"
}
},
- "densitychart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A7.9%2C19.6%2C1.6%2C36.4%2C19.3%2C15.2&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c",
- "layoutchart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.3%2C7.4%2C80.9%2C7.4&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c"
+ "densitychart": "//chart.googleapis.com/chart?chco=c4df9b%2C6fad0c&cht=p&chs=400x250&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A6.7%2C18.6%2C1.7%2C36.6%2C20.2%2C16.2&chf=bg%2Cs%2C00000000",
+ "layoutchart": "//chart.googleapis.com/chart?chco=c4df9b%2C6fad0c&cht=p&chs=400x250&chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.4%2C7.7%2C81.7%2C6.2&chf=bg%2Cs%2C00000000"
}
];
diff --git a/docs/html/google/play/billing/api.jd b/docs/html/google/play/billing/api.jd
index 3d46715..bc710f9 100644
--- a/docs/html/google/play/billing/api.jd
+++ b/docs/html/google/play/billing/api.jd
@@ -1,6 +1,7 @@
-page.title=In-app Billing Version 3
+page.title=In-app Billing API
parent.title=In-app Billing
parent.link=index.html
+page.tags="billing, inapp, iap"
@jd:body
<div id="qv-wrapper">
diff --git a/docs/html/google/play/billing/billing_integrate.jd b/docs/html/google/play/billing/billing_integrate.jd
index dba43cd..052cf75 100644
--- a/docs/html/google/play/billing/billing_integrate.jd
+++ b/docs/html/google/play/billing/billing_integrate.jd
@@ -1,6 +1,7 @@
-page.title=Implementing In-app Billing <span style="font-size:16px;">(IAB Version 3)</span>
+page.title=Implementing In-app Billing
parent.title=In-app Billing
parent.link=index.html
+page.tags="inapp, billing, iap"
@jd:body
<div id="qv-wrapper">
@@ -141,15 +142,17 @@
};
</pre>
-<p>In your activity’s {@link android.app.Activity#onCreate onCreate} method, perform the binding by calling the {@link android.content.Context#bindService bindService} method. Pass the method an {@link android.content.Intent} that references the In-app Billing service and an instance of the {@link android.content.ServiceConnection} that you created.</p>
-<pre>
-@Override
-public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- bindService(new
- Intent("com.android.vending.billing.InAppBillingService.BIND"),
- mServiceConn, Context.BIND_AUTO_CREATE);
+<p>In your activity’s {@link android.app.Activity#onCreate onCreate} method, perform the binding by calling the {@link android.content.Context#bindService bindService} method. Pass the method an {@link android.content.Intent} that references the In-app Billing service and an instance of the {@link android.content.ServiceConnection} that you created, and explicitly set the Intent's target package name to <code>com.android.vending</code> — the package name of Google Play app.</p>
+
+<p class="caution"><strong>Caution:</strong> To protect the security of billing transactions, always make sure to explicitly set the intent's target package name to <code>com.android.vending</code>, using {@link android.content.Intent#setPackage(java.lang.String) setPackage()} as shown in the example below. Setting the package name explicitly ensures that <em>only</em> the Google Play app can handle billing requests from your app, preventing other apps from intercepting those requests.</p>
+
+<pre>@Override
+public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
+ serviceIntent.setPackage("com.android.vending");
+ bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
</pre>
<p>You can now use the mService reference to communicate with the Google Play service.</p>
<p class="note"><strong>Important:</strong> Remember to unbind from the In-app Billing service when you are done with your {@link android.app.Activity}. If you don’t unbind, the open service connection could cause your device’s performance to degrade. This example shows how to perform the unbind operation on a service connection to In-app Billing called {@code mServiceConn} by overriding the activity’s {@link android.app.Activity#onDestroy onDestroy} method.</p>
@@ -269,7 +272,7 @@
}
}
</pre>
-<p class="note"><strong>Security Recommendation:</strong> When you send a purchase request, create a String token that uniquely identifies this purchase request and include this token in the {@code developerPayload}.You can use a randomly generated string as the token. When you receive the purchase response from Google Play, make sure to check the returned data signature, the {@code orderId}, and the {@code developerPayload} String. For added security, you should perform the checking on your own secure server. Make sure to verify that the {@code orderId} is a unique value that you have not previously processed, and the {@code developerPayload} String matches the token that you sent previously with the purchase request.</p>
+<p class="note"><strong>Security Recommendation:</strong> When you send a purchase request, create a String token that uniquely identifies this purchase request and include this token in the {@code developerPayload}.You can use a randomly generated string as the token. When you receive the purchase response from Google Play, make sure to check the returned data signature, the {@code orderId}, and the {@code developerPayload} String. For added security, you should perform the checking on your own secure server. Make sure to verify that the {@code orderId} is a unique value that you have not previously processed, and the {@code developerPayload} String matches the token that you sent previously with the purchase request.</p>
<h3 id="QueryPurchases">Querying for Purchased Items</h3>
<p>To retrieve information about purchases made by a user from your app, call the {@code getPurchases} method on the In-app Billing Version 3 service. Pass in to the method the In-app Billing API version (“3”), the package name of your calling app, and the purchase type (“inapp” or "subs").</p>
diff --git a/docs/html/google/play/billing/billing_reference.jd b/docs/html/google/play/billing/billing_reference.jd
index 4f5e65c..4d80964 100644
--- a/docs/html/google/play/billing/billing_reference.jd
+++ b/docs/html/google/play/billing/billing_reference.jd
@@ -1,4 +1,4 @@
-page.title=In-app Billing Reference <span style="font-size:16px;">(IAB Version 3)</span>
+page.title=In-app Billing Reference
parent.title=In-app Billing
parent.link=index.html
@jd:body
diff --git a/docs/html/google/play/billing/billing_subscriptions.jd b/docs/html/google/play/billing/billing_subscriptions.jd
index 3c72da1..2b78ab3 100644
--- a/docs/html/google/play/billing/billing_subscriptions.jd
+++ b/docs/html/google/play/billing/billing_subscriptions.jd
@@ -1,9 +1,9 @@
-page.title=Google Play In-App Subscriptions
+page.title=In-App Subscriptions
parent.title=In-app Billing
parent.link=index.html
page.metaDescription=Subscriptions let you sell content or features in your app with automated, recurring billing.
page.image=/images/play_dev.jpg
-page.tags="inapp, iap, billing"
+page.tags="subscriptions, billing, inapp, iap"
meta.tags="monetization, inappbilling, subscriptions"
@jd:body
diff --git a/docs/html/google/play/billing/billing_testing.jd b/docs/html/google/play/billing/billing_testing.jd
index 8a49433..10f5326 100644
--- a/docs/html/google/play/billing/billing_testing.jd
+++ b/docs/html/google/play/billing/billing_testing.jd
@@ -1,6 +1,7 @@
page.title=Testing In-app Billing
parent.title=In-app Billing
parent.link=index.html
+page.tags="inapp, billing, iap"
@jd:body
<div id="qv-wrapper">
diff --git a/docs/html/google/play/billing/index.jd b/docs/html/google/play/billing/index.jd
index 18b1523..875271fe 100644
--- a/docs/html/google/play/billing/index.jd
+++ b/docs/html/google/play/billing/index.jd
@@ -2,7 +2,7 @@
page.metaDescription=In-app Billing lets you sell digital content as one-time purchases or subscriptions.
page.image=/images/play_dev.jpg
meta.tags="monetizing, inappbilling, subscriptions"
-page.tags="inapp, iap, subscriptions"
+page.tags="billing, inapp, iap"
@jd:body
<p>In-app Billing is a Google Play service that lets you sell digital content from inside
diff --git a/docs/html/google/play/billing/versions.jd b/docs/html/google/play/billing/versions.jd
index 1271a15..dbe3ea3 100644
--- a/docs/html/google/play/billing/versions.jd
+++ b/docs/html/google/play/billing/versions.jd
@@ -1,3 +1,4 @@
+excludeFromSuggestions=true
page.title=In-app Billing Version Notes
@jd:body
diff --git a/docs/html/reference/renderscript/rs__matrix_8rsh.html b/docs/html/reference/renderscript/rs__matrix_8rsh.html
index 69cc373..3b8e047 100644
--- a/docs/html/reference/renderscript/rs__matrix_8rsh.html
+++ b/docs/html/reference/renderscript/rs__matrix_8rsh.html
@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
-<title>/usr/local/google/home/srhines/android_trees/jb-mr2-dev/frameworks/rs/scriptc/rs_matrix.rsh File Reference</title>
+<title>frameworks/rs/scriptc/rs_matrix.rsh File Reference</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
@@ -27,18 +27,18 @@
<div class="summary">
<a href="#func-members">Functions</a> </div>
<div class="headertitle">
-<div class="title">/usr/local/google/home/srhines/android_trees/jb-mr2-dev/frameworks/rs/scriptc/rs_matrix.rsh File Reference</div> </div>
+<div class="title">frameworks/rs/scriptc/rs_matrix.rsh File Reference</div> </div>
</div>
<div class="contents">
<table class="memberdecls">
<tr><td colspan="2"><h2><a name="func-members"></a>
Functions</h2></td></tr>
-<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#ad6ea242218e0f1a031f754df0317e6e7">rsMatrixSet</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, float v)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#ab69543f85a673f23fbb5f893e5824395">rsMatrixSet</a> (<a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, float v)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a0a85c8d3607f1b75019f6991c5b19fca">rsMatrixSet</a> (<a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, float v)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top">float </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a22e983b67d3089c5cb97032e249ca335">rsMatrixGet</a> (const <a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top">float </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#ad485084684991796cffdd8a008557569">rsMatrixGet</a> (const <a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top">float </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#aaa86b029d5c5c15fead5338bba02e4c3">rsMatrixGet</a> (const <a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#aca88832ed720e301780152c60884393e">rsMatrixSet</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, float v)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a08a247cdf2e70e78310bf04f9ecd5144">rsMatrixSet</a> (<a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, float v)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#af9707d7be5945bf55ed53683624176ff">rsMatrixSet</a> (<a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, float v)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME float </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#af26fdbf8b8f0ed5d1b53f62b2aef5110">rsMatrixGet</a> (const <a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME float </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#acfebfc7b97e7282b78cd9c65b791932a">rsMatrixGet</a> (const <a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME float </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a683b4537b98103c50cc66780dfe8cd69">rsMatrixGet</a> (const <a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a0ffd9de971cf10d0a663ff565be8d3cc">rsMatrixLoadIdentity</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a5b31e83553efa947db2198674d5db043">rsMatrixLoadIdentity</a> (<a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> *m)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#ad2954a5ac11d2370227296be89e92471">rsMatrixLoadIdentity</a> (<a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m)</td></tr>
@@ -65,9 +65,9 @@
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a4c59884a0e534dbbcdc5655842732d43">rsMatrixLoadOrtho</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, float left, float right, float bottom, float top, float near, float far)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#ad25760aaf01e95d0055237afab41bbb3">rsMatrixLoadFrustum</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, float left, float right, float bottom, float top, float near, float far)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#aa404c34d7478f2921f7415d2da95d02b">rsMatrixLoadPerspective</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, float fovy, float aspect, float near, float far)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top"><a class="el" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a2f11c3d7cc34ddce90ba785b93af8da2">rsMatrixMultiply</a> (const <a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, <a class="el" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> in)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top"><a class="el" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a88ae2ed203769cb4a7917f84f6c1a2e2">rsMatrixMultiply</a> (const <a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> *m, <a class="el" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top"><a class="el" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a8d81a7143d5d45f60f7e91f955579bab">rsMatrixMultiply</a> (const <a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m, <a class="el" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME <a class="el" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a47b6abbf32ffaf77bb13d96c3f05779f">rsMatrixMultiply</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, <a class="el" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> in)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME <a class="el" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a716bc2d29b80eb25388aba3ba8845aef">rsMatrixMultiply</a> (<a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> *m, <a class="el" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME <a class="el" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a> (<a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m, <a class="el" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">bool </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a00b6a334ba5ac94d84850f22ec9f4de5">rsMatrixInverse</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">bool </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#ac05080d52da2d99a759ef34fa0655e82">rsMatrixInverseTranspose</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a88095c70f1550c760844b3e32e41a31a">rsMatrixTranspose</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m)</td></tr>
@@ -75,16 +75,30 @@
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a49164dd4d4e85b212196028b1fd89dc1">rsMatrixTranspose</a> (<a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m)</td></tr>
</table>
<hr/><a name="details" id="details"></a><h2>Detailed Description</h2>
-<div class="textblock"><p>Matrix routines. </p>
+<div class="textblock"><p>Matrix functions. </p>
+<p>These functions let you manipulate square matrices of rank 2x2, 3x3, and 4x4. They are particularly useful for graphical transformations and are compatible with OpenGL.</p>
+<p>A few general notes:</p>
+<ul>
+<li>We use a zero-based index for rows and columns. E.g. the last element of a <a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> is found at (3, 3).</li>
+</ul>
+<ul>
+<li>RenderScript uses column-based vectors. Transforming a vector is done by postmultiplying the vector, e.g. <em>(matrix * vector)</em>, as provided by <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</li>
+</ul>
+<ul>
+<li>To create a transformation matrix that performs two transformations at once, multiply the two source matrices, with the first transformation as the right argument. E.g. to create a transformation matrix that applies the transformation <em>s1</em> followed by <em>s2</em>, call rsMatrixLoadMultiply(&combined, &s2, &s1). This derives from <em>s2 * (s1 * v)</em>, which is <em>(s2 * s1) * v</em>.</li>
+</ul>
+<ul>
+<li>We have two style of functions to create transformation matrices: rsMatrixLoad<em>Transformation</em> and rsMatrix<em>Transformation</em>. The former style simply stores the transformation matrix in the first argument. The latter modifies a pre-existing transformation matrix so that the new transformation happens first. E.g. if you call <a class="el" href="rs__matrix_8rsh.html#a4df5f9b5bb6044f3c3426f2f58b94405">rsMatrixTranslate</a> on a matrix that already does a scaling, the resulting matrix when applied to a vector will first do the translation then the scaling. </li>
+</ul>
<p>Definition in file <a class="el" href="rs__matrix_8rsh_source.html">rs_matrix.rsh</a>.</p>
</div><hr/><h2>Function Documentation</h2>
-<a class="anchor" id="a22e983b67d3089c5cb97032e249ca335"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixGet" ref="a22e983b67d3089c5cb97032e249ca335" args="(const rs_matrix4x4 *m, uint32_t row, uint32_t col)" -->
+<a class="anchor" id="af26fdbf8b8f0ed5d1b53f62b2aef5110"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixGet" ref="af26fdbf8b8f0ed5d1b53f62b2aef5110" args="(const rs_matrix4x4 *m, uint32_t col, uint32_t row)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname">float rsMatrixGet </td>
+ <td class="memname">_RS_RUNTIME float rsMatrixGet </td>
<td>(</td>
<td class="paramtype">const <a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> * </td>
<td class="paramname"><em>m</em>, </td>
@@ -93,13 +107,13 @@
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>row</em>, </td>
+ <td class="paramname"><em>col</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>col</em> </td>
+ <td class="paramname"><em>row</em> </td>
</tr>
<tr>
<td></td>
@@ -109,25 +123,26 @@
</table>
</div>
<div class="memdoc">
-<p>Get one element of a matrix.</p>
+<p>Returns one element of a matrix.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td>The matrix to read from </td></tr>
- <tr><td class="paramname">row</td><td></td></tr>
- <tr><td class="paramname">col</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to extract the element from. </td></tr>
+ <tr><td class="paramname">col</td><td>The zero-based column of the element to be extracted. </td></tr>
+ <tr><td class="paramname">row</td><td>The zero-based row of the element to extracted.</td></tr>
</table>
</dd>
</dl>
+<dl class="warning"><dt><b>Warning:</b></dt><dd>The order of the column and row parameters may be unexpected.</dd></dl>
<dl class="return"><dt><b>Returns:</b></dt><dd>float </dd></dl>
</div>
</div>
-<a class="anchor" id="ad485084684991796cffdd8a008557569"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixGet" ref="ad485084684991796cffdd8a008557569" args="(const rs_matrix3x3 *m, uint32_t row, uint32_t col)" -->
+<a class="anchor" id="acfebfc7b97e7282b78cd9c65b791932a"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixGet" ref="acfebfc7b97e7282b78cd9c65b791932a" args="(const rs_matrix3x3 *m, uint32_t col, uint32_t row)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname">float rsMatrixGet </td>
+ <td class="memname">_RS_RUNTIME float rsMatrixGet </td>
<td>(</td>
<td class="paramtype">const <a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> * </td>
<td class="paramname"><em>m</em>, </td>
@@ -136,13 +151,13 @@
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>row</em>, </td>
+ <td class="paramname"><em>col</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>col</em> </td>
+ <td class="paramname"><em>row</em> </td>
</tr>
<tr>
<td></td>
@@ -156,12 +171,12 @@
</div>
</div>
-<a class="anchor" id="aaa86b029d5c5c15fead5338bba02e4c3"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixGet" ref="aaa86b029d5c5c15fead5338bba02e4c3" args="(const rs_matrix2x2 *m, uint32_t row, uint32_t col)" -->
+<a class="anchor" id="a683b4537b98103c50cc66780dfe8cd69"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixGet" ref="a683b4537b98103c50cc66780dfe8cd69" args="(const rs_matrix2x2 *m, uint32_t col, uint32_t row)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname">float rsMatrixGet </td>
+ <td class="memname">_RS_RUNTIME float rsMatrixGet </td>
<td>(</td>
<td class="paramtype">const <a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> * </td>
<td class="paramname"><em>m</em>, </td>
@@ -170,13 +185,13 @@
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>row</em>, </td>
+ <td class="paramname"><em>col</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>col</em> </td>
+ <td class="paramname"><em>row</em> </td>
</tr>
<tr>
<td></td>
@@ -204,10 +219,11 @@
</table>
</div>
<div class="memdoc">
-<p>Returns true if the matrix was successfully inversed</p>
+<p>Inverts a matrix in place.</p>
+<p>Returns true if the matrix was successfully inversed.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to invert. </td></tr>
</table>
</dd>
</dl>
@@ -228,10 +244,11 @@
</table>
</div>
<div class="memdoc">
-<p>Returns true if the matrix was successfully inversed and transposed.</p>
+<p>Inverts and transpose a matrix in place.</p>
+<p>The matrix is first inverted then transposed. Returns true if the matrix was successfully inverted.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to modify. </td></tr>
</table>
</dd>
</dl>
@@ -263,9 +280,11 @@
</div>
<div class="memdoc">
<p>Set the elements of a matrix from an array of floats.</p>
+<p>The array of floats should be in row-major order, i.e. the element a <em>row 0, column 0</em> should be first, followed by the element at <em>row 0, column 1</em>, etc.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
+ <tr><td class="paramname">v</td><td>The array of values to set the matrix to. These arrays should be 4, 9, or 16 floats long, depending on the matrix size. </td></tr>
</table>
</dd>
</dl>
@@ -352,7 +371,20 @@
</table>
</div>
<div class="memdoc">
-<p>This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. </p>
+<p>Set the elements of a matrix from another matrix.</p>
+<p>If the source matrix is smaller than the destination, the rest of the destination is filled with elements of the identity matrix. E.g. loading a <a class="el" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> into a <a class="el" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> will give:</p>
+ <table>
+ <tr><td>m00</td><td>m01</td><td>0.0</td><td>0.0</td></tr>
+ <tr><td>m10</td><td>m11</td><td>0.0</td><td>0.0</td></tr>
+ <tr><td>0.0</td><td>0.0</td><td>1.0</td><td>0.0</td></tr>
+ <tr><td>0.0</td><td>0.0</td><td>0.0</td><td>1.0</td></tr>
+ </table><dl><dt><b>Parameters:</b></dt><dd>
+ <table class="params">
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
+ <tr><td class="paramname">v</td><td>The source matrix. </td></tr>
+ </table>
+ </dd>
+</dl>
</div>
</div>
@@ -408,13 +440,7 @@
</table>
</div>
<div class="memdoc">
-<p>Set the elements of a matrix from another matrix.</p>
-<dl><dt><b>Parameters:</b></dt><dd>
- <table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- </table>
- </dd>
-</dl>
+<p>This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. </p>
</div>
</div>
@@ -528,10 +554,13 @@
</table>
</div>
<div class="memdoc">
-<p>Load an Frustum projection matrix constructed from the 6 planes</p>
+<p>Load a frustum projection matrix.</p>
+<p>Constructs a frustum projection matrix, transforming the box identified by the six clipping planes <em>left, right, bottom, top, near, far</em>.</p>
+<p>To apply this projection to a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
+<p>See <a href="https://www.opengl.org/documentation/specs/version2.0/glspec20.pdf">https://www.opengl.org/documentation/specs/version2.0/glspec20.pdf</a></p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
<tr><td class="paramname">left</td><td></td></tr>
<tr><td class="paramname">right</td><td></td></tr>
<tr><td class="paramname">bottom</td><td></td></tr>
@@ -561,7 +590,7 @@
<p>Set the elements of a matrix to the identity matrix.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
</table>
</dd>
</dl>
@@ -634,12 +663,15 @@
</table>
</div>
<div class="memdoc">
-<p>Multiply two matrix (lhs, rhs) and place the result in m.</p>
+<p>Multiply two matrices.</p>
+<p>Sets <em>m</em> to the matrix product of <em>lhs * rhs</em>.</p>
+<p>To combine two 4x4 transformaton matrices, multiply the second transformation matrix by the first transformation matrix. E.g. to create a transformation matrix that applies the transformation <em>s1</em> followed by <em>s2</em>, call rsMatrixLoadMultiply(&combined, &s2, &s1).</p>
+<dl class="warning"><dt><b>Warning:</b></dt><dd>As of version 21, storing the result back into right matrix is not supported and will result in undefined behavior. Use rsMatrixMulitply instead. E.g. instead of doing rsMatrixLoadMultiply (&m2r, &m2r, &m2l), use rsMatrixMultiply (&m2r, &m2l). rsMatrixLoadMultiply (&m2l, &m2r, &m2l) works as expected.</dd></dl>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- <tr><td class="paramname">lhs</td><td></td></tr>
- <tr><td class="paramname">rhs</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
+ <tr><td class="paramname">lhs</td><td>The left matrix of the product. </td></tr>
+ <tr><td class="paramname">rhs</td><td>The right matrix of the product. </td></tr>
</table>
</dd>
</dl>
@@ -768,10 +800,13 @@
</table>
</div>
<div class="memdoc">
-<p>Load an Ortho projection matrix constructed from the 6 planes</p>
+<p>Load an orthographic projection matrix.</p>
+<p>Constructs an orthographic projection matrix, transforming the box identified by the six clipping planes <em>left, right, bottom, top, near, far</em> into a unit cube with a corner at <em>(-1, -1, -1)</em> and the opposite at <em>(1, 1, 1)</em>.</p>
+<p>To apply this projection to a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
+<p>See <a href="https://en.wikipedia.org/wiki/Orthographic_projection">https://en.wikipedia.org/wiki/Orthographic_projection</a> and <a href="https://www.opengl.org/documentation/specs/version2.0/glspec20.pdf">https://www.opengl.org/documentation/specs/version2.0/glspec20.pdf</a></p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
<tr><td class="paramname">left</td><td></td></tr>
<tr><td class="paramname">right</td><td></td></tr>
<tr><td class="paramname">bottom</td><td></td></tr>
@@ -826,14 +861,17 @@
</table>
</div>
<div class="memdoc">
-<p>Load an perspective projection matrix constructed from the 6 planes</p>
+<p>Load a perspective projection matrix.</p>
+<p>Constructs a perspective projection matrix, assuming a symmetrical field of view.</p>
+<p>To apply this projection to a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
+<p>See <a href="https://www.opengl.org/documentation/specs/version2.0/glspec20.pdf">https://www.opengl.org/documentation/specs/version2.0/glspec20.pdf</a></p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
<tr><td class="paramname">fovy</td><td>Field of view, in degrees along the Y axis. </td></tr>
<tr><td class="paramname">aspect</td><td>Ratio of x / y. </td></tr>
- <tr><td class="paramname">near</td><td></td></tr>
- <tr><td class="paramname">far</td><td></td></tr>
+ <tr><td class="paramname">near</td><td>The near clipping plane. </td></tr>
+ <tr><td class="paramname">far</td><td>The far clipping plane. </td></tr>
</table>
</dd>
</dl>
@@ -883,13 +921,16 @@
</div>
<div class="memdoc">
<p>Load a rotation matrix.</p>
+<p>This function creates a rotation matrix. The axis of rotation is the <em>(x, y, z)</em> vector.</p>
+<p>To rotate a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
+<p>See <a href="http://en.wikipedia.org/wiki/Rotation_matrix">http://en.wikipedia.org/wiki/Rotation_matrix</a> .</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- <tr><td class="paramname">rot</td><td></td></tr>
- <tr><td class="paramname">x</td><td></td></tr>
- <tr><td class="paramname">y</td><td></td></tr>
- <tr><td class="paramname">z</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
+ <tr><td class="paramname">rot</td><td>How much rotation to do, in degrees. </td></tr>
+ <tr><td class="paramname">x</td><td>The x component of the vector that is the axis of rotation. </td></tr>
+ <tr><td class="paramname">y</td><td>The y component of the vector that is the axis of rotation. </td></tr>
+ <tr><td class="paramname">z</td><td>The z component of the vector that is the axis of rotation. </td></tr>
</table>
</dd>
</dl>
@@ -933,12 +974,14 @@
</div>
<div class="memdoc">
<p>Load a scale matrix.</p>
+<p>This function creates a scaling matrix, where each component of a vector is multiplied by a number. This number can be negative.</p>
+<p>To scale a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- <tr><td class="paramname">x</td><td></td></tr>
- <tr><td class="paramname">y</td><td></td></tr>
- <tr><td class="paramname">z</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
+ <tr><td class="paramname">x</td><td>The multiple to scale the x components by. </td></tr>
+ <tr><td class="paramname">y</td><td>The multiple to scale the y components by. </td></tr>
+ <tr><td class="paramname">z</td><td>The multiple to scale the z components by. </td></tr>
</table>
</dd>
</dl>
@@ -982,12 +1025,14 @@
</div>
<div class="memdoc">
<p>Load a translation matrix.</p>
+<p>This function creates a translation matrix, where a number is added to each element of a vector.</p>
+<p>To translate a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- <tr><td class="paramname">x</td><td></td></tr>
- <tr><td class="paramname">y</td><td></td></tr>
- <tr><td class="paramname">z</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
+ <tr><td class="paramname">x</td><td>The number to add to each x component. </td></tr>
+ <tr><td class="paramname">y</td><td>The number to add to each y component. </td></tr>
+ <tr><td class="paramname">z</td><td>The number to add to each z component. </td></tr>
</table>
</dd>
</dl>
@@ -1018,11 +1063,13 @@
</table>
</div>
<div class="memdoc">
-<p>Multiply the matrix m by rhs and place the result back into m.</p>
+<p>Multiply a matrix into another one.</p>
+<p>Sets <em>m</em> to the matrix product <em>m * rhs</em>.</p>
+<p>When combining two 4x4 transformation matrices using this function, the resulting matrix will correspond to performing the <em>rhs</em> transformation first followed by the original <em>m</em> transformation.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td>(lhs) </td></tr>
- <tr><td class="paramname">rhs</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The left matrix of the product and the matrix to be set. </td></tr>
+ <tr><td class="paramname">rhs</td><td>The right matrix of the product. </td></tr>
</table>
</dd>
</dl>
@@ -1085,14 +1132,14 @@
</div>
</div>
-<a class="anchor" id="a2f11c3d7cc34ddce90ba785b93af8da2"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixMultiply" ref="a2f11c3d7cc34ddce90ba785b93af8da2" args="(const rs_matrix4x4 *m, float4 in)" -->
+<a class="anchor" id="a47b6abbf32ffaf77bb13d96c3f05779f"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixMultiply" ref="a47b6abbf32ffaf77bb13d96c3f05779f" args="(rs_matrix4x4 *m, float4 in)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname"><a class="el" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> rsMatrixMultiply </td>
+ <td class="memname">_RS_RUNTIME <a class="el" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> rsMatrixMultiply </td>
<td>(</td>
- <td class="paramtype">const <a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> * </td>
+ <td class="paramtype"><a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> * </td>
<td class="paramname"><em>m</em>, </td>
</tr>
<tr>
@@ -1109,19 +1156,24 @@
</table>
</div>
<div class="memdoc">
-<p>Multiply a vector by a matrix and return the result vector. API version 14+</p>
+<p>Multiply a vector by a matrix.</p>
+<p>Returns the post-multiplication of the vector by the matrix, ie. <em>m * in</em>.</p>
+<p>When multiplying a <em>float3</em> to a <em><a class="el" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a></em>, the vector is expanded with (1).</p>
+<p>When multiplying a <em>float2</em> to a <em><a class="el" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a></em>, the vector is expanded with (0, 1).</p>
+<p>When multiplying a <em>float2</em> to a <em><a class="el" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a></em>, the vector is expanded with (0).</p>
+<p>This function is available in API version 10-13. Starting with API 14, the function takes a const matrix as the first argument.</p>
<p>This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. </p>
</div>
</div>
-<a class="anchor" id="a88ae2ed203769cb4a7917f84f6c1a2e2"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixMultiply" ref="a88ae2ed203769cb4a7917f84f6c1a2e2" args="(const rs_matrix3x3 *m, float3 in)" -->
+<a class="anchor" id="a716bc2d29b80eb25388aba3ba8845aef"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixMultiply" ref="a716bc2d29b80eb25388aba3ba8845aef" args="(rs_matrix3x3 *m, float3 in)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname"><a class="el" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> rsMatrixMultiply </td>
+ <td class="memname">_RS_RUNTIME <a class="el" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> rsMatrixMultiply </td>
<td>(</td>
- <td class="paramtype">const <a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> * </td>
+ <td class="paramtype"><a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> * </td>
<td class="paramname"><em>m</em>, </td>
</tr>
<tr>
@@ -1142,14 +1194,14 @@
</div>
</div>
-<a class="anchor" id="a8d81a7143d5d45f60f7e91f955579bab"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixMultiply" ref="a8d81a7143d5d45f60f7e91f955579bab" args="(const rs_matrix2x2 *m, float2 in)" -->
+<a class="anchor" id="a4d9a8bb7c3f5d67b14fa349bdd531d13"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixMultiply" ref="a4d9a8bb7c3f5d67b14fa349bdd531d13" args="(rs_matrix2x2 *m, float2 in)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname"><a class="el" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> rsMatrixMultiply </td>
+ <td class="memname">_RS_RUNTIME <a class="el" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> rsMatrixMultiply </td>
<td>(</td>
- <td class="paramtype">const <a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> * </td>
+ <td class="paramtype"><a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> * </td>
<td class="paramname"><em>m</em>, </td>
</tr>
<tr>
@@ -1212,14 +1264,16 @@
</table>
</div>
<div class="memdoc">
-<p>Multiple matrix m with a rotation matrix</p>
+<p>Multiply the matrix <em>m</em> with a rotation matrix.</p>
+<p>This function modifies a transformation matrix to first do a rotation. The axis of rotation is the <em>(x, y, z)</em> vector.</p>
+<p>To apply this combined transformation to a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- <tr><td class="paramname">rot</td><td></td></tr>
- <tr><td class="paramname">x</td><td></td></tr>
- <tr><td class="paramname">y</td><td></td></tr>
- <tr><td class="paramname">z</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to modify. </td></tr>
+ <tr><td class="paramname">rot</td><td>How much rotation to do, in degrees. </td></tr>
+ <tr><td class="paramname">x</td><td>The x component of the vector that is the axis of rotation. </td></tr>
+ <tr><td class="paramname">y</td><td>The y component of the vector that is the axis of rotation. </td></tr>
+ <tr><td class="paramname">z</td><td>The z component of the vector that is the axis of rotation. </td></tr>
</table>
</dd>
</dl>
@@ -1262,25 +1316,27 @@
</table>
</div>
<div class="memdoc">
-<p>Multiple matrix m with a scale matrix</p>
+<p>Multiply the matrix <em>m</em> with a scaling matrix.</p>
+<p>This function modifies a transformation matrix to first do a scaling. When scaling, each component of a vector is multiplied by a number. This number can be negative.</p>
+<p>To apply this combined transformation to a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- <tr><td class="paramname">x</td><td></td></tr>
- <tr><td class="paramname">y</td><td></td></tr>
- <tr><td class="paramname">z</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to modify. </td></tr>
+ <tr><td class="paramname">x</td><td>The multiple to scale the x components by. </td></tr>
+ <tr><td class="paramname">y</td><td>The multiple to scale the y components by. </td></tr>
+ <tr><td class="paramname">z</td><td>The multiple to scale the z components by. </td></tr>
</table>
</dd>
</dl>
</div>
</div>
-<a class="anchor" id="ad6ea242218e0f1a031f754df0317e6e7"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixSet" ref="ad6ea242218e0f1a031f754df0317e6e7" args="(rs_matrix4x4 *m, uint32_t row, uint32_t col, float v)" -->
+<a class="anchor" id="aca88832ed720e301780152c60884393e"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixSet" ref="aca88832ed720e301780152c60884393e" args="(rs_matrix4x4 *m, uint32_t col, uint32_t row, float v)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname">void rsMatrixSet </td>
+ <td class="memname">_RS_RUNTIME void rsMatrixSet </td>
<td>(</td>
<td class="paramtype"><a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> * </td>
<td class="paramname"><em>m</em>, </td>
@@ -1289,13 +1345,13 @@
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>row</em>, </td>
+ <td class="paramname"><em>col</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>col</em>, </td>
+ <td class="paramname"><em>row</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
@@ -1311,26 +1367,27 @@
</table>
</div>
<div class="memdoc">
-<p>Set one element of a matrix.</p>
+<p>Set an element of a matrix.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td>The matrix to be set </td></tr>
- <tr><td class="paramname">row</td><td></td></tr>
- <tr><td class="paramname">col</td><td></td></tr>
- <tr><td class="paramname">v</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix that will be modified. </td></tr>
+ <tr><td class="paramname">col</td><td>The zero-based column of the element to be set. </td></tr>
+ <tr><td class="paramname">row</td><td>The zero-based row of the element to be set. </td></tr>
+ <tr><td class="paramname">v</td><td>The value to set.</td></tr>
</table>
</dd>
</dl>
+<dl class="warning"><dt><b>Warning:</b></dt><dd>The order of the column and row parameters may be unexpected.</dd></dl>
<dl class="return"><dt><b>Returns:</b></dt><dd>void </dd></dl>
</div>
</div>
-<a class="anchor" id="ab69543f85a673f23fbb5f893e5824395"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixSet" ref="ab69543f85a673f23fbb5f893e5824395" args="(rs_matrix3x3 *m, uint32_t row, uint32_t col, float v)" -->
+<a class="anchor" id="a08a247cdf2e70e78310bf04f9ecd5144"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixSet" ref="a08a247cdf2e70e78310bf04f9ecd5144" args="(rs_matrix3x3 *m, uint32_t col, uint32_t row, float v)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname">void rsMatrixSet </td>
+ <td class="memname">_RS_RUNTIME void rsMatrixSet </td>
<td>(</td>
<td class="paramtype"><a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> * </td>
<td class="paramname"><em>m</em>, </td>
@@ -1339,13 +1396,13 @@
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>row</em>, </td>
+ <td class="paramname"><em>col</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>col</em>, </td>
+ <td class="paramname"><em>row</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
@@ -1365,12 +1422,12 @@
</div>
</div>
-<a class="anchor" id="a0a85c8d3607f1b75019f6991c5b19fca"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixSet" ref="a0a85c8d3607f1b75019f6991c5b19fca" args="(rs_matrix2x2 *m, uint32_t row, uint32_t col, float v)" -->
+<a class="anchor" id="af9707d7be5945bf55ed53683624176ff"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixSet" ref="af9707d7be5945bf55ed53683624176ff" args="(rs_matrix2x2 *m, uint32_t col, uint32_t row, float v)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname">void rsMatrixSet </td>
+ <td class="memname">_RS_RUNTIME void rsMatrixSet </td>
<td>(</td>
<td class="paramtype"><a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> * </td>
<td class="paramname"><em>m</em>, </td>
@@ -1379,13 +1436,13 @@
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>row</em>, </td>
+ <td class="paramname"><em>col</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>col</em>, </td>
+ <td class="paramname"><em>row</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
@@ -1441,13 +1498,15 @@
</table>
</div>
<div class="memdoc">
-<p>Multiple matrix m with a translation matrix</p>
+<p>Multiply the matrix <em>m</em> with a translation matrix.</p>
+<p>This function modifies a transformation matrix to first do a translation. When translating, a number is added to each component of a vector.</p>
+<p>To apply this combined transformation to a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- <tr><td class="paramname">x</td><td></td></tr>
- <tr><td class="paramname">y</td><td></td></tr>
- <tr><td class="paramname">z</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to modify. </td></tr>
+ <tr><td class="paramname">x</td><td>The number to add to each x component. </td></tr>
+ <tr><td class="paramname">y</td><td>The number to add to each y component. </td></tr>
+ <tr><td class="paramname">z</td><td>The number to add to each z component. </td></tr>
</table>
</dd>
</dl>
@@ -1468,10 +1527,10 @@
</table>
</div>
<div class="memdoc">
-<p>Transpose the matrix m.</p>
+<p>Transpose the matrix m in place.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to transpose. </td></tr>
</table>
</dd>
</dl>
diff --git a/docs/html/reference/renderscript/rs__matrix_8rsh_source.html b/docs/html/reference/renderscript/rs__matrix_8rsh_source.html
index c1aaeb2..77144bd 100644
--- a/docs/html/reference/renderscript/rs__matrix_8rsh_source.html
+++ b/docs/html/reference/renderscript/rs__matrix_8rsh_source.html
@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
-<title>/usr/local/google/home/srhines/android_trees/jb-mr2-dev/frameworks/rs/scriptc/rs_matrix.rsh Source File</title>
+<title>frameworks/rs/scriptc/rs_matrix.rsh Source File</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
@@ -24,7 +24,7 @@
</div>
<div class="header">
<div class="headertitle">
-<div class="title">/usr/local/google/home/srhines/android_trees/jb-mr2-dev/frameworks/rs/scriptc/rs_matrix.rsh</div> </div>
+<div class="title">frameworks/rs/scriptc/rs_matrix.rsh</div> </div>
</div>
<div class="contents">
<a href="rs__matrix_8rsh.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
@@ -43,129 +43,128 @@
<a name="l00014"></a>00014 <span class="comment"> * limitations under the License.</span>
<a name="l00015"></a>00015 <span class="comment"> */</span>
<a name="l00016"></a>00016
-<a name="l00023"></a>00023 <span class="preprocessor">#ifndef __RS_MATRIX_RSH__</span>
-<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#define __RS_MATRIX_RSH__</span>
-<a name="l00025"></a>00025 <span class="preprocessor"></span>
-<a name="l00036"></a>00036 _RS_RUNTIME <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00037"></a>00037 <a class="code" href="rs__matrix_8rsh.html#ad6ea242218e0f1a031f754df0317e6e7">rsMatrixSet</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <span class="keywordtype">float</span> v);
-<a name="l00041"></a>00041 _RS_RUNTIME <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00042"></a>00042 <a class="code" href="rs__matrix_8rsh.html#ad6ea242218e0f1a031f754df0317e6e7">rsMatrixSet</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <span class="keywordtype">float</span> v);
-<a name="l00046"></a>00046 _RS_RUNTIME <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00047"></a>00047 <a class="code" href="rs__matrix_8rsh.html#ad6ea242218e0f1a031f754df0317e6e7">rsMatrixSet</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <span class="keywordtype">float</span> v);
-<a name="l00048"></a>00048
-<a name="l00058"></a>00058 _RS_RUNTIME <span class="keywordtype">float</span> __attribute__((overloadable))
-<a name="l00059"></a>00059 <a class="code" href="rs__matrix_8rsh.html#a22e983b67d3089c5cb97032e249ca335">rsMatrixGet</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col);
-<a name="l00063"></a>00063 _RS_RUNTIME <span class="keywordtype">float</span> __attribute__((overloadable))
-<a name="l00064"></a>00064 <a class="code" href="rs__matrix_8rsh.html#a22e983b67d3089c5cb97032e249ca335">rsMatrixGet</a>(const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col);
-<a name="l00068"></a>00068 _RS_RUNTIME <span class="keywordtype">float</span> __attribute__((overloadable))
-<a name="l00069"></a>00069 <a class="code" href="rs__matrix_8rsh.html#a22e983b67d3089c5cb97032e249ca335">rsMatrixGet</a>(const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col);
-<a name="l00070"></a>00070
-<a name="l00076"></a>00076 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a0ffd9de971cf10d0a663ff565be8d3cc">rsMatrixLoadIdentity</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
-<a name="l00080"></a>00080 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a0ffd9de971cf10d0a663ff565be8d3cc">rsMatrixLoadIdentity</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m);
-<a name="l00084"></a>00084 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a0ffd9de971cf10d0a663ff565be8d3cc">rsMatrixLoadIdentity</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m);
-<a name="l00085"></a>00085
-<a name="l00091"></a>00091 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <span class="keywordtype">float</span> *v);
-<a name="l00095"></a>00095 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <span class="keywordtype">float</span> *v);
-<a name="l00099"></a>00099 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <span class="keywordtype">float</span> *v);
-<a name="l00103"></a>00103 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *v);
-<a name="l00107"></a>00107 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *v);
-<a name="l00108"></a>00108
-<a name="l00114"></a>00114 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *v);
-<a name="l00118"></a>00118 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *v);
-<a name="l00122"></a>00122 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *v);
-<a name="l00123"></a>00123
-<a name="l00133"></a>00133 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00134"></a>00134 <a class="code" href="rs__matrix_8rsh.html#a268032f3ac6d766b1d7fe72a6cb50464">rsMatrixLoadRotate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> rot, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
-<a name="l00135"></a>00135
-<a name="l00144"></a>00144 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00145"></a>00145 <a class="code" href="rs__matrix_8rsh.html#acaf51d1f9ad5041ce01fbf8b7c5923fd">rsMatrixLoadScale</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
-<a name="l00146"></a>00146
-<a name="l00155"></a>00155 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00156"></a>00156 <a class="code" href="rs__matrix_8rsh.html#a1b521c8a3d1260fa732cbf0a71af0e74">rsMatrixLoadTranslate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
-<a name="l00157"></a>00157
-<a name="l00165"></a>00165 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00166"></a>00166 <a class="code" href="rs__matrix_8rsh.html#a79f14c4c0f5ecc1bbd0bf54da8b653ef">rsMatrixLoadMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *lhs, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *rhs);
-<a name="l00170"></a>00170 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00171"></a>00171 <a class="code" href="rs__matrix_8rsh.html#a79f14c4c0f5ecc1bbd0bf54da8b653ef">rsMatrixLoadMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *lhs, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *rhs);
-<a name="l00175"></a>00175 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00176"></a>00176 <a class="code" href="rs__matrix_8rsh.html#a79f14c4c0f5ecc1bbd0bf54da8b653ef">rsMatrixLoadMultiply</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *lhs, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *rhs);
-<a name="l00177"></a>00177
-<a name="l00184"></a>00184 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00185"></a>00185 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *rhs);
-<a name="l00189"></a>00189 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00190"></a>00190 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *rhs);
-<a name="l00194"></a>00194 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00195"></a>00195 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *rhs);
-<a name="l00196"></a>00196
-<a name="l00206"></a>00206 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00207"></a>00207 <a class="code" href="rs__matrix_8rsh.html#ad5ed05ca4880397fb29615e3c6798de1">rsMatrixRotate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> rot, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
-<a name="l00208"></a>00208
-<a name="l00217"></a>00217 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00218"></a>00218 <a class="code" href="rs__matrix_8rsh.html#a94cc6b22bd1a6c07a9a1c1d21afb392c">rsMatrixScale</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
-<a name="l00219"></a>00219
-<a name="l00228"></a>00228 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00229"></a>00229 <a class="code" href="rs__matrix_8rsh.html#a4df5f9b5bb6044f3c3426f2f58b94405">rsMatrixTranslate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
-<a name="l00230"></a>00230
-<a name="l00242"></a>00242 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00243"></a>00243 <a class="code" href="rs__matrix_8rsh.html#a4c59884a0e534dbbcdc5655842732d43">rsMatrixLoadOrtho</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> left, <span class="keywordtype">float</span> right, <span class="keywordtype">float</span> bottom, <span class="keywordtype">float</span> top, <span class="keywordtype">float</span> near, <span class="keywordtype">float</span> far);
-<a name="l00244"></a>00244
-<a name="l00256"></a>00256 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00257"></a>00257 <a class="code" href="rs__matrix_8rsh.html#ad25760aaf01e95d0055237afab41bbb3">rsMatrixLoadFrustum</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> left, <span class="keywordtype">float</span> right, <span class="keywordtype">float</span> bottom, <span class="keywordtype">float</span> top, <span class="keywordtype">float</span> near, <span class="keywordtype">float</span> far);
-<a name="l00258"></a>00258
-<a name="l00268"></a>00268 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00269"></a>00269 <a class="code" href="rs__matrix_8rsh.html#aa404c34d7478f2921f7415d2da95d02b">rsMatrixLoadPerspective</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a>* m, <span class="keywordtype">float</span> fovy, <span class="keywordtype">float</span> aspect, <span class="keywordtype">float</span> near, <span class="keywordtype">float</span> far);
-<a name="l00270"></a>00270
-<a name="l00271"></a>00271 <span class="preprocessor">#if !defined(RS_VERSION) || (RS_VERSION < 14)</span>
-<a name="l00272"></a>00272 <span class="preprocessor"></span>
-<a name="l00276"></a>00276 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
-<a name="l00277"></a>00277 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> in);
-<a name="l00278"></a>00278
-<a name="l00282"></a>00282 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
-<a name="l00283"></a>00283 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
+<a name="l00050"></a>00050 <span class="preprocessor">#ifndef __RS_MATRIX_RSH__</span>
+<a name="l00051"></a>00051 <span class="preprocessor"></span><span class="preprocessor">#define __RS_MATRIX_RSH__</span>
+<a name="l00052"></a>00052 <span class="preprocessor"></span>
+<a name="l00066"></a>00066 _RS_RUNTIME <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00067"></a>00067 <a class="code" href="rs__matrix_8rsh.html#aca88832ed720e301780152c60884393e">rsMatrixSet</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <span class="keywordtype">float</span> v);
+<a name="l00071"></a>00071 _RS_RUNTIME <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00072"></a>00072 <a class="code" href="rs__matrix_8rsh.html#aca88832ed720e301780152c60884393e">rsMatrixSet</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <span class="keywordtype">float</span> v);
+<a name="l00076"></a>00076 _RS_RUNTIME <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00077"></a>00077 <a class="code" href="rs__matrix_8rsh.html#aca88832ed720e301780152c60884393e">rsMatrixSet</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <span class="keywordtype">float</span> v);
+<a name="l00078"></a>00078
+<a name="l00091"></a>00091 _RS_RUNTIME <span class="keywordtype">float</span> __attribute__((overloadable))
+<a name="l00092"></a>00092 <a class="code" href="rs__matrix_8rsh.html#af26fdbf8b8f0ed5d1b53f62b2aef5110">rsMatrixGet</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row);
+<a name="l00096"></a>00096 _RS_RUNTIME <span class="keywordtype">float</span> __attribute__((overloadable))
+<a name="l00097"></a>00097 <a class="code" href="rs__matrix_8rsh.html#af26fdbf8b8f0ed5d1b53f62b2aef5110">rsMatrixGet</a>(const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row);
+<a name="l00101"></a>00101 _RS_RUNTIME <span class="keywordtype">float</span> __attribute__((overloadable))
+<a name="l00102"></a>00102 <a class="code" href="rs__matrix_8rsh.html#af26fdbf8b8f0ed5d1b53f62b2aef5110">rsMatrixGet</a>(const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row);
+<a name="l00103"></a>00103
+<a name="l00109"></a>00109 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a0ffd9de971cf10d0a663ff565be8d3cc">rsMatrixLoadIdentity</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
+<a name="l00113"></a>00113 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a0ffd9de971cf10d0a663ff565be8d3cc">rsMatrixLoadIdentity</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m);
+<a name="l00117"></a>00117 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a0ffd9de971cf10d0a663ff565be8d3cc">rsMatrixLoadIdentity</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m);
+<a name="l00118"></a>00118
+<a name="l00130"></a>00130 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <span class="keywordtype">float</span> *v);
+<a name="l00134"></a>00134 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <span class="keywordtype">float</span> *v);
+<a name="l00138"></a>00138 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <span class="keywordtype">float</span> *v);
+<a name="l00156"></a>00156 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *v);
+<a name="l00160"></a>00160 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *v);
+<a name="l00164"></a>00164 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *v);
+<a name="l00168"></a>00168 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *v);
+<a name="l00172"></a>00172 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *v);
+<a name="l00173"></a>00173
+<a name="l00191"></a>00191 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00192"></a>00192 <a class="code" href="rs__matrix_8rsh.html#a268032f3ac6d766b1d7fe72a6cb50464">rsMatrixLoadRotate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> rot, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
+<a name="l00193"></a>00193
+<a name="l00208"></a>00208 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00209"></a>00209 <a class="code" href="rs__matrix_8rsh.html#acaf51d1f9ad5041ce01fbf8b7c5923fd">rsMatrixLoadScale</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
+<a name="l00210"></a>00210
+<a name="l00225"></a>00225 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00226"></a>00226 <a class="code" href="rs__matrix_8rsh.html#a1b521c8a3d1260fa732cbf0a71af0e74">rsMatrixLoadTranslate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
+<a name="l00227"></a>00227
+<a name="l00247"></a>00247 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00248"></a>00248 <a class="code" href="rs__matrix_8rsh.html#a79f14c4c0f5ecc1bbd0bf54da8b653ef">rsMatrixLoadMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *lhs, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *rhs);
+<a name="l00252"></a>00252 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00253"></a>00253 <a class="code" href="rs__matrix_8rsh.html#a79f14c4c0f5ecc1bbd0bf54da8b653ef">rsMatrixLoadMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *lhs, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *rhs);
+<a name="l00257"></a>00257 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00258"></a>00258 <a class="code" href="rs__matrix_8rsh.html#a79f14c4c0f5ecc1bbd0bf54da8b653ef">rsMatrixLoadMultiply</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *lhs, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *rhs);
+<a name="l00259"></a>00259
+<a name="l00272"></a>00272 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00273"></a>00273 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *rhs);
+<a name="l00277"></a>00277 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00278"></a>00278 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *rhs);
+<a name="l00282"></a>00282 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00283"></a>00283 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *rhs);
<a name="l00284"></a>00284
-<a name="l00288"></a>00288 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
-<a name="l00289"></a>00289 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
-<a name="l00290"></a>00290
-<a name="l00294"></a>00294 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
-<a name="l00295"></a>00295 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
-<a name="l00296"></a>00296
-<a name="l00300"></a>00300 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
-<a name="l00301"></a>00301 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
+<a name="l00300"></a>00300 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00301"></a>00301 <a class="code" href="rs__matrix_8rsh.html#ad5ed05ca4880397fb29615e3c6798de1">rsMatrixRotate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> rot, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
<a name="l00302"></a>00302
-<a name="l00306"></a>00306 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> __attribute__((overloadable))
-<a name="l00307"></a>00307 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
-<a name="l00308"></a>00308 <span class="preprocessor">#else</span>
-<a name="l00309"></a>00309 <span class="preprocessor"></span>
-<a name="l00313"></a>00313 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
-<a name="l00314"></a>00314 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> in);
-<a name="l00315"></a>00315
-<a name="l00319"></a>00319 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
-<a name="l00320"></a>00320 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
-<a name="l00321"></a>00321
-<a name="l00325"></a>00325 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
-<a name="l00326"></a>00326 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
-<a name="l00327"></a>00327
-<a name="l00331"></a>00331 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
-<a name="l00332"></a>00332 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
-<a name="l00333"></a>00333
-<a name="l00337"></a>00337 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
-<a name="l00338"></a>00338 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
-<a name="l00339"></a>00339
-<a name="l00343"></a>00343 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> __attribute__((overloadable))
-<a name="l00344"></a>00344 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
-<a name="l00345"></a>00345 <span class="preprocessor">#endif</span>
-<a name="l00346"></a>00346 <span class="preprocessor"></span>
-<a name="l00347"></a>00347
-<a name="l00353"></a>00353 <span class="keyword">extern</span> <span class="keywordtype">bool</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a00b6a334ba5ac94d84850f22ec9f4de5">rsMatrixInverse</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
-<a name="l00354"></a>00354
-<a name="l00360"></a>00360 extern <span class="keywordtype">bool</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac05080d52da2d99a759ef34fa0655e82">rsMatrixInverseTranspose</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
-<a name="l00361"></a>00361
-<a name="l00367"></a>00367 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a88095c70f1550c760844b3e32e41a31a">rsMatrixTranspose</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
-<a name="l00371"></a>00371 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a88095c70f1550c760844b3e32e41a31a">rsMatrixTranspose</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m);
-<a name="l00375"></a>00375 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a88095c70f1550c760844b3e32e41a31a">rsMatrixTranspose</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m);
-<a name="l00376"></a>00376
-<a name="l00377"></a>00377
-<a name="l00378"></a>00378 <span class="preprocessor">#endif</span>
+<a name="l00318"></a>00318 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00319"></a>00319 <a class="code" href="rs__matrix_8rsh.html#a94cc6b22bd1a6c07a9a1c1d21afb392c">rsMatrixScale</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
+<a name="l00320"></a>00320
+<a name="l00336"></a>00336 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00337"></a>00337 <a class="code" href="rs__matrix_8rsh.html#a4df5f9b5bb6044f3c3426f2f58b94405">rsMatrixTranslate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
+<a name="l00338"></a>00338
+<a name="l00361"></a>00361 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00362"></a>00362 <a class="code" href="rs__matrix_8rsh.html#a4c59884a0e534dbbcdc5655842732d43">rsMatrixLoadOrtho</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> left, <span class="keywordtype">float</span> right, <span class="keywordtype">float</span> bottom, <span class="keywordtype">float</span> top, <span class="keywordtype">float</span> near, <span class="keywordtype">float</span> far);
+<a name="l00363"></a>00363
+<a name="l00384"></a>00384 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00385"></a>00385 <a class="code" href="rs__matrix_8rsh.html#ad25760aaf01e95d0055237afab41bbb3">rsMatrixLoadFrustum</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> left, <span class="keywordtype">float</span> right, <span class="keywordtype">float</span> bottom, <span class="keywordtype">float</span> top, <span class="keywordtype">float</span> near, <span class="keywordtype">float</span> far);
+<a name="l00386"></a>00386
+<a name="l00403"></a>00403 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00404"></a>00404 <a class="code" href="rs__matrix_8rsh.html#aa404c34d7478f2921f7415d2da95d02b">rsMatrixLoadPerspective</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a>* m, <span class="keywordtype">float</span> fovy, <span class="keywordtype">float</span> aspect, <span class="keywordtype">float</span> near, <span class="keywordtype">float</span> far);
+<a name="l00405"></a>00405
+<a name="l00406"></a>00406 <span class="preprocessor">#if !defined(RS_VERSION) || (RS_VERSION < 14)</span>
+<a name="l00407"></a>00407 <span class="preprocessor"></span>
+<a name="l00421"></a>00421 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
+<a name="l00422"></a>00422 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> in);
+<a name="l00423"></a>00423
+<a name="l00427"></a>00427 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
+<a name="l00428"></a>00428 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
+<a name="l00429"></a>00429
+<a name="l00433"></a>00433 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
+<a name="l00434"></a>00434 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
+<a name="l00435"></a>00435
+<a name="l00439"></a>00439 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
+<a name="l00440"></a>00440 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
+<a name="l00441"></a>00441
+<a name="l00445"></a>00445 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
+<a name="l00446"></a>00446 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
+<a name="l00447"></a>00447
+<a name="l00451"></a>00451 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> __attribute__((overloadable))
+<a name="l00452"></a>00452 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
+<a name="l00453"></a>00453 <span class="preprocessor">#else</span>
+<a name="l00454"></a>00454 <span class="preprocessor"></span>
+<a name="l00467"></a>00467 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
+<a name="l00468"></a>00468 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> in);
+<a name="l00469"></a>00469
+<a name="l00473"></a>00473 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
+<a name="l00474"></a>00474 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
+<a name="l00475"></a>00475
+<a name="l00479"></a>00479 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
+<a name="l00480"></a>00480 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
+<a name="l00481"></a>00481
+<a name="l00485"></a>00485 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
+<a name="l00486"></a>00486 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
+<a name="l00487"></a>00487
+<a name="l00491"></a>00491 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
+<a name="l00492"></a>00492 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
+<a name="l00493"></a>00493
+<a name="l00497"></a>00497 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> __attribute__((overloadable))
+<a name="l00498"></a>00498 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
+<a name="l00499"></a>00499 <span class="preprocessor">#endif</span>
+<a name="l00500"></a>00500 <span class="preprocessor"></span>
+<a name="l00501"></a>00501
+<a name="l00509"></a>00509 <span class="keyword">extern</span> <span class="keywordtype">bool</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a00b6a334ba5ac94d84850f22ec9f4de5">rsMatrixInverse</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
+<a name="l00510"></a>00510
+<a name="l00519"></a>00519 extern <span class="keywordtype">bool</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac05080d52da2d99a759ef34fa0655e82">rsMatrixInverseTranspose</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
+<a name="l00520"></a>00520
+<a name="l00526"></a>00526 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a88095c70f1550c760844b3e32e41a31a">rsMatrixTranspose</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
+<a name="l00530"></a>00530 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a88095c70f1550c760844b3e32e41a31a">rsMatrixTranspose</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m);
+<a name="l00534"></a>00534 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a88095c70f1550c760844b3e32e41a31a">rsMatrixTranspose</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m);
+<a name="l00535"></a>00535
+<a name="l00536"></a>00536
+<a name="l00537"></a>00537 <span class="preprocessor">#endif</span>
</pre></div></div>
</div>
diff --git a/docs/html/tools/building/index.jd b/docs/html/tools/building/index.jd
index c64942f..c1f3019 100644
--- a/docs/html/tools/building/index.jd
+++ b/docs/html/tools/building/index.jd
@@ -79,3 +79,14 @@
running on a device.</li>
</ul>
+<p class="note"><b>Note:</b> Apps are limited to a 64K method reference limit. If your app reaches
+this limit, the build process outputs the following error message:
+
+<pre>Unable to execute dex: method ID not in [0, 0xffff]: 65536.</pre>
+
+To avoid this, you can
+<a href="http://android-developers.blogspot.com.es/2011/07/custom-class-loading-in-dalvik.html">load
+secondary dex files at runtime</a> and use
+<a href="http://developer.android.com/tools/help/proguard.html">ProGuard</a> to strip out unnecessary
+class references (Proguard only works when building in release mode).
+</p>
\ No newline at end of file
diff --git a/docs/html/tools/sdk/ndk/index.jd b/docs/html/tools/sdk/ndk/index.jd
index 71b15d5..e75f451 100644
--- a/docs/html/tools/sdk/ndk/index.jd
+++ b/docs/html/tools/sdk/ndk/index.jd
@@ -2,59 +2,59 @@
page.template=sdk
-ndk.mac64_download=android-ndk32-r10-darwin-x86_64.tar.bz2
-ndk.mac64_bytes=411610468
-ndk.mac64_checksum=3ce1fa3dbe7a188f5d2640fd2f7ca944
+ndk.mac64_download=android-ndk32-r10b-darwin-x86_64.tar.bz2
+ndk.mac64_bytes=413652124
+ndk.mac64_checksum=7ca4a84e9c56c38acdafb007e7cd33c5
-ndk.mac32_download=android-ndk32-r10-darwin-x86.tar.bz2
-ndk.mac32_bytes=404768263
-ndk.mac32_checksum=1824eec1f6749b6cb7bb306a3b924c33
+ndk.mac32_download=android-ndk32-r10b-darwin-x86.tar.bz2
+ndk.mac32_bytes=406998070
+ndk.mac32_checksum=db3626b2c5f3245d90e2724f7bcf4c3e
-ndk.linux64_download=android-ndk32-r10-linux-x86_64.tar.bz2
-ndk.linux64_bytes=420671390
-ndk.linux64_checksum=e3ff629d212a8106a43415862fa39baf
+ndk.linux64_download=android-ndk32-r10b-linux-x86_64.tar.bz2
+ndk.linux64_bytes=422237011
+ndk.linux64_checksum=5c0f301aa789a1a747d5d2aeb8c69ef3
-ndk.linux32_download=android-ndk32-r10-linux-x86.tar.bz2
-ndk.linux32_bytes=420078216
-ndk.linux32_checksum=8d9a5faa6e77b43bfae0f169079b21c4
+ndk.linux32_download=android-ndk32-r10b-linux-x86.tar.bz2
+ndk.linux32_bytes=421052081
+ndk.linux32_checksum=e8f55daa5c9de7ab79aaaf5d7d751b69
-ndk.win64_download=android-ndk32-r10-windows-x86_64.zip
-ndk.win64_bytes=529850429
-ndk.win64_checksum=b11f9239344f7c377ed5b627f0fb236e
+ndk.win64_download=android-ndk32-r10b-windows-x86_64.zip
+ndk.win64_bytes=531912027
+ndk.win64_checksum=e4dd2e0c6f38e3ad936c366bdf6b1d4e
-ndk.win32_download=android-ndk32-r10-windows-x86.zip
-ndk.win32_bytes=500135685
-ndk.win32_checksum=0a3c01147abba945cc4ef5837519ec97
+ndk.win32_download=android-ndk32-r10b-windows-x86.zip
+ndk.win32_bytes=502720425
+ndk.win32_checksum=9fa4f19bca7edd6eefa63fe788737987
-ndk.mac64_64_download=android-ndk64-r10-darwin-x86_64.tar.bz2
-ndk.mac64_64_bytes=327740247
-ndk.mac64_64_checksum=72561b27acc6192a2e81b345ea128a20
+ndk.mac64_64_download=android-ndk64-r10b-darwin-x86_64.tar.bz2
+ndk.mac64_64_bytes=346423776
+ndk.mac64_64_checksum=5bae7feed20ebf0762c0baefe6b84b6d
-ndk.mac32_64_download=android-ndk64-r10-darwin-x86.tar.bz2
-ndk.mac32_64_bytes=323736411
-ndk.mac32_64_checksum=5bbaf9d8051ba5d2c0fff74cfd87c374
+ndk.mac32_64_download=android-ndk64-r10b-darwin-x86.tar.bz2
+ndk.mac32_64_bytes=344052876
+ndk.mac32_64_checksum=4447049ac2b5877176b9b6b1cf3bcdb2
-ndk.linux64_64_download=android-ndk64-r10-linux-x86_64.tar.bz2
-ndk.linux64_64_bytes=339708042
-ndk.linux64_64_checksum=737290195583268b7fbff4aa56465ab6
+ndk.linux64_64_download=android-ndk64-r10b-linux-x86_64.tar.bz2
+ndk.linux64_64_bytes=358835298
+ndk.linux64_64_checksum=2aa12a0d9a70bcab83e42d010a685136
-ndk.linux32_64_download=android-ndk64-r10-linux-x86.tar.bz2
-ndk.linux32_64_bytes=338544906
-ndk.linux32_64_checksum=bea5d027baeb948cbff6af840d26b80d
+ndk.linux32_64_download=android-ndk64-r10b-linux-x86.tar.bz2
+ndk.linux32_64_bytes=358060577
+ndk.linux32_64_checksum=b77eb583626d8c7f5c11e49181fd5eac
-ndk.win64_64_download=android-ndk64-r10-windows-x86_64.zip
-ndk.win64_64_bytes=417411195
-ndk.win64_64_checksum=91879ec85539b45313a21b9526b911a8
+ndk.win64_64_download=android-ndk64-r10b-windows-x86_64.zip
+ndk.win64_64_bytes=437152652
+ndk.win64_64_checksum=df39185e6c5a4d72eb9fca3f9aaabc46
-ndk.win32_64_download=android-ndk64-r10-windows-x86.zip
-ndk.win32_64_bytes=396751892
-ndk.win32_64_checksum=f79070ace2cde9ebf6a2e2be4a61ac7a
+ndk.win32_64_download=android-ndk64-r10b-windows-x86.zip
+ndk.win32_64_bytes=417290468
+ndk.win32_64_checksum=0f0324cb11f04e8b2641e5422ee39c81
-ndk.debug_info_download=android-ndk-r10-cxx-stl-libs-with-debug-info.zip
-ndk.debug_info_bytes=253198908
-ndk.debug_info_checksum=c2a90c43d17dbb5f0609cc8237491788
+ndk.debug_info_download=android-ndk-r10b-cxx-stl-libs-with-debug-info.zip
+ndk.debug_info_bytes=227302317
+ndk.debug_info_checksum=bed1bb855a41bdb572a804dbf6d45aa6
page.title=Android NDK
@@ -357,15 +357,6 @@
</div>
</div>
-
-
-
-
-
-
-
-
-
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
@@ -418,7 +409,7 @@
<p>With NDK revision 9 and higher, the release packages have been split to reduce download size.
- The first download for each platform contains the default NDK toolchain. The second download
+ The first download for each platform contains the default NDK toolchain. The additional download
contains legacy NDK toolchains for that platform, which is only required if you are not using
the current, recommended toolchain for your NDK builds.</p>
@@ -426,10 +417,91 @@
<p>The following sections provide information about releases of the NDK.</p>
+
<div class="toggle-content opened">
<p>
<a href="#" onclick="return toggleContent(this)"> <img
src="/assets/images/triangle-opened.png" class="toggle-content-img" alt=""
+ >Android NDK, Revision 10b</a> <em>(September 2014)</em>
+ </p>
+ <div class="toggle-content-toggleme">
+ <dl>
+
+ <dt>Important notes:</dt>
+ <dd>
+ <ul>
+ <li>Because of the 512MB size restriction on downloadable packages, the following 32-bit items are not in the 32-bit NDK download packages. Instead, they reside in the 64-bit ones:</li>
+ <ul>
+ <li>Android-L headers</li>
+ <li>GCC 4.9</li>
+ </ul>
+ <li>Currently, the only Renderscript support provided by the NDK is for 32-bit Renderscript with Android 4.4 (API level 19). You cannot build HelloComputeNDK (the only Renderscript sample) with any other combination of Renderscript (32- or 64-bit) and Android version.</li>
+ <li>To compile native-codec, you must use a 64-bit NDK package, which is where all the Android-L headers are located. </li>
+ </ul>
+ </dd>
+
+
+ <dt>Important bug fixes:</dt>
+ <dd>
+ <ul>
+ <li>Fixed gdb 7.6 in GCC 4.8/4.9. (Issues <a href="http://b.android.com/74112">74112</a> and <a href="http://b.android.com/74371">74371</a>.)</li>
+ <li>Fixed GCC 4.8/4.9 for x86, so that they no longer enable <code>-msse4.2</code> and <code>-mpopcnt</code> by default. (Issue <a href="http://b.android.com/73843">73843</a>.)</li>
+ </ul>
+ </dd>
+
+ <dt>Other bug fixes:</dt>
+ <dd>
+ <ul>
+ <li>Removed <code>stdio.h</code> from the <code>include-fixed/</code> directories of all versions of GCC. (Issue <a href="http://b.android.com/73728">73728</a>.)</li>
+ <li>Removed duplicate header files from the Windows packages in the <code>platforms/android-L/arch-*/usr/include/linux/netfilter*/</code> directories. (Issue <a href="https://code.google.com/p/android/issues/detail?id=73704">73704</a>.)</li>
+ <li>Fixed a problem that prevented Clang from building HelloComputeNDK.</li>
+ <li>Fixed atexit. (Issue <a href="http://b.android.com/66595">66595</a>.)</li>
+ <li>Made various fixes to the docs in <code>docs/</code> and <code>sources/third_party/googletest/README.NDK</code>. (Issue <a href="http://b.android.com/74069">74069</a>.)</li>
+ <li>Made the following fixes to the Android-L headers:</li>
+ <ol>
+ <li>Added the following functions to <code>ctype.h</code> and <code>wchar.h</code>: <code>dn_expand()</code>, <code>grantpt()</code>, <code> inet_nsap_addr()</code>, <code>inet_nsap_ntoa()</code>, <code>insque()</code>, <code>nsdispatch()</code>, <code>posix_openpt()</code>, <code>__pthread_cleanup_pop()</code>, <code>__pthread_cleanup_push()</code>, <code>remque()</code>, <code>setfsgid()</code>, <code>setfsuid()</code>, <code>splice()</code>, <code>tee()</code>, <code>twalk()</code> (Issue <a href = "http://b.android.com/73719">73719</a>), and 42 <code>*_l()</code> functions.</li>
+
+ <li>Renamed <code>cmsg_nxthdr</code> to <code>__cmsg_nxthdr</code>.</li>
+
+ <li>Removed <code>__libc_malloc_dispatch</code>.</li>
+
+ <li>Changed the <code>ptrace()</code> prototype to <code>long ptrace(int, ...);</code>.</li>
+
+ <li>Removed <code>sha1.h</code>.</li>
+
+ <li>Extended <code>android_dlextinfo</code> in <code>android/dlext.h</code>.</li>
+
+ <li>Annotated <code>__NDK_FPABI__</code> for functions receiving or returning float- or double-type values in <code>stdlib.h</code>, <code>time.h</code>, <code>wchar.h</code>, and <code>complex.h</code>.</li>
+ </ol>
+ </ul>
+ </dd>
+
+ <dt>Other changes:</dt>
+ <dd>
+ <ul>
+ <li>Updated <code>mipsel-linux-android-4.9</code> and <code>mips64el-linux-android-4.9</code>, implementing a new multilib directory layout, and providing support for gdb-7.7</li>
+ <li>Enhanced <code>cpu-features</code> to detect more arm64 features. (Change list <a href="https://android-review.googlesource.com/#/c/100339">100339</a>.)</li>
+ </dd>
+ </ul>
+
+
+
+ </dl>
+ </div>
+</div>
+
+
+
+
+
+
+
+
+
+<div class="toggle-content closed">
+ <p>
+ <a href="#" onclick="return toggleContent(this)"> <img
+ src="/assets/images/triangle-closed.png" class="toggle-content-img" alt=""
>Android NDK, Revision 10</a> <em>(July 2014)</em>
</p>
<div class="toggle-content-toggleme">
@@ -442,7 +514,7 @@
<li>GCC 4.9 is the default compiler for 64-bit ABIs. Clang is currently version 3.4.
<code>NDK_TOOLCHAIN_VERSION=clang</code>
may not work for arm64-v8a and mips64.</li>
- <li>Android API level L is the first level with 64-bit support. Note that this API
+ <li>Android-L is the first level with 64-bit support. Note that this API
level is a temporary one, and only for L-preview. An actual API level number will replace it at
L-release.</li>
<li>This release includes now includes <code>all32</code> and <code>all64</code>
@@ -479,7 +551,7 @@
<li>For ndk-build, enable 32-bit, GCC 4.9 building either by adding
<code>NDK_TOOLCHAIN_VERSION=4.9</code> to <code>Application.mk</code>, or exporting it as an
environment variable from the command line.</li>
- <li>For a standalone toolchain, use the <code> --toolchain=</code> option in the
+ <li>For a standalone toolchain, use the <code>--toolchain=</code> option in the
<code>make-standalone-toolchain.sh</code> script. For example: <code>--toolchain=arm-linux-androideabi-4.9.</code></li>
</ul>
<li>Upgraded GDB to version 7.6 in GCC 4.8/4.9 and x86*. Since GDB is still at version GDB-7.3.x in
diff --git a/docs/html/training/efficient-downloads/redundant_redundant.jd b/docs/html/training/efficient-downloads/redundant_redundant.jd
index 4bf9af9..674298a 100644
--- a/docs/html/training/efficient-downloads/redundant_redundant.jd
+++ b/docs/html/training/efficient-downloads/redundant_redundant.jd
@@ -30,8 +30,8 @@
<p>The most fundamental way to reduce your downloads is to download only what you need. In terms of data, that means implementing REST APIs that allow you to specify query criteria that limit the returned data by using parameters such as the time of your last update.</p>
<p>Similarly, when downloading images, it's good practice to reduce the size of the images server-side, rather than downloading full-sized images that are reduced on the client.</p>
-
-<h2 id="LocalCache">Cache Files Locally</h2>
+
+<h2 id="LocalCache">Cache Files Locally</h2>
<p>Another important technique is to avoid downloading duplicate data. You can do this by aggressive caching. Always cache static resources, including on-demand downloads such as full size images, for as long as reasonably possible. On-demand resources should be stored separately to enable you to regularly flush your on-demand cache to manage its size.</p>
@@ -60,11 +60,11 @@
<p>Alternatively, you can use the managed / secure application cache. Note that this internal cache may be flushed when the system is running low on available storage.</p>
-<pre>Context.getCache();</pre>
+<pre>Context.getCacheDir();</pre>
<p>Files stored in either cache location will be erased when the application is uninstalled.</p>
-<h2 id="ResponseCache">Use the HttpURLConnection Response Cache</h2>
+<h2 id="ResponseCache">Use the HttpURLConnection Response Cache</h2>
<p>Android 4.0 added a response cache to {@code HttpURLConnection}. You can enable HTTP response caching on supported devices using reflection as follows:</p>
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index ba22550..49e8b9d 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -27,6 +27,7 @@
import android.graphics.Outline;
import android.graphics.PorterDuff;
import android.graphics.Rect;
+import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.Log;
@@ -131,7 +132,9 @@
private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;
- private final AnimatedVectorDrawableState mAnimatedVectorState;
+ private AnimatedVectorDrawableState mAnimatedVectorState;
+
+ private boolean mMutated;
public AnimatedVectorDrawable() {
mAnimatedVectorState = new AnimatedVectorDrawableState(
@@ -140,7 +143,6 @@
private AnimatedVectorDrawable(AnimatedVectorDrawableState state, Resources res,
Theme theme) {
- // TODO: Correctly handle the constant state for AVD.
mAnimatedVectorState = new AnimatedVectorDrawableState(state);
if (theme != null && canApplyTheme()) {
applyTheme(theme);
@@ -148,8 +150,17 @@
}
@Override
+ public Drawable mutate() {
+ if (!mMutated && super.mutate() == this) {
+ mAnimatedVectorState = new AnimatedVectorDrawableState(mAnimatedVectorState);
+ mMutated = true;
+ }
+ return this;
+ }
+
+ @Override
public ConstantState getConstantState() {
- return null;
+ return mAnimatedVectorState;
}
@Override
@@ -252,6 +263,7 @@
throws XmlPullParserException, IOException {
int eventType = parser.getEventType();
+ float pathErrorScale = 1;
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
final String tagName = parser.getName();
@@ -261,9 +273,11 @@
int drawableRes = a.getResourceId(
R.styleable.AnimatedVectorDrawable_drawable, 0);
if (drawableRes != 0) {
- mAnimatedVectorState.mVectorDrawable = (VectorDrawable) res.getDrawable(
+ VectorDrawable vectorDrawable = (VectorDrawable) res.getDrawable(
drawableRes, theme).mutate();
- mAnimatedVectorState.mVectorDrawable.setAllowCaching(false);
+ vectorDrawable.setAllowCaching(false);
+ pathErrorScale = vectorDrawable.getPixelSize();
+ mAnimatedVectorState.mVectorDrawable = vectorDrawable;
}
a.recycle();
} else if (TARGET.equals(tagName)) {
@@ -275,7 +289,8 @@
int id = a.getResourceId(
R.styleable.AnimatedVectorDrawableTarget_animation, 0);
if (id != 0) {
- Animator objectAnimator = AnimatorInflater.loadAnimator(res, theme, id);
+ Animator objectAnimator = AnimatorInflater.loadAnimator(res, theme, id,
+ pathErrorScale);
setupAnimatorsForTarget(target, objectAnimator);
}
a.recycle();
@@ -307,14 +322,31 @@
int mChangingConfigurations;
VectorDrawable mVectorDrawable;
ArrayList<Animator> mAnimators;
+ ArrayMap<Animator, String> mTargetNameMap;
public AnimatedVectorDrawableState(AnimatedVectorDrawableState copy) {
if (copy != null) {
mChangingConfigurations = copy.mChangingConfigurations;
- // TODO: Make sure the constant state are handled correctly.
- mVectorDrawable = new VectorDrawable();
- mVectorDrawable.setAllowCaching(false);
- mAnimators = new ArrayList<Animator>();
+ if (copy.mVectorDrawable != null) {
+ mVectorDrawable = (VectorDrawable) copy.mVectorDrawable.getConstantState().newDrawable();
+ mVectorDrawable.mutate();
+ mVectorDrawable.setAllowCaching(false);
+ mVectorDrawable.setBounds(copy.mVectorDrawable.getBounds());
+ }
+ if (copy.mAnimators != null) {
+ final int numAnimators = copy.mAnimators.size();
+ mAnimators = new ArrayList<Animator>(numAnimators);
+ mTargetNameMap = new ArrayMap<Animator, String>(numAnimators);
+ for (int i = 0; i < numAnimators; ++i) {
+ Animator anim = copy.mAnimators.get(i);
+ Animator animClone = anim.clone();
+ String targetName = copy.mTargetNameMap.get(anim);
+ Object targetObject = mVectorDrawable.getTargetByName(targetName);
+ animClone.setTarget(targetObject);
+ mAnimators.add(animClone);
+ mTargetNameMap.put(animClone, targetName);
+ }
+ }
}
}
@@ -342,7 +374,12 @@
private void setupAnimatorsForTarget(String name, Animator animator) {
Object target = mAnimatedVectorState.mVectorDrawable.getTargetByName(name);
animator.setTarget(target);
+ if (mAnimatedVectorState.mAnimators == null) {
+ mAnimatedVectorState.mAnimators = new ArrayList<Animator>();
+ mAnimatedVectorState.mTargetNameMap = new ArrayMap<Animator, String>();
+ }
mAnimatedVectorState.mAnimators.add(animator);
+ mAnimatedVectorState.mTargetNameMap.put(animator, name);
if (DBG_ANIMATION_VECTOR_DRAWABLE) {
Log.v(LOGTAG, "add animator for target " + name + " " + animator);
}
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 2c8611e..e1c88cb 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -1552,6 +1552,7 @@
mUseLevel = state.mUseLevel;
mUseLevelForShape = state.mUseLevelForShape;
mOpaqueOverBounds = state.mOpaqueOverBounds;
+ mOpaqueOverShape = state.mOpaqueOverShape;
mThemeAttrs = state.mThemeAttrs;
mAttrSize = state.mAttrSize;
mAttrGradient = state.mAttrGradient;
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index b05fb61..b13669b 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -156,6 +156,13 @@
private boolean mOverrideBounds;
/**
+ * Whether the next draw MUST draw something to canvas. Used to work around
+ * a bug in hardware invalidation following a render thread-accelerated
+ * animation.
+ */
+ private boolean mNeedsDraw;
+
+ /**
* Constructor used for drawable inflation.
*/
RippleDrawable() {
@@ -204,6 +211,8 @@
}
cancelExitingRipples();
+
+ mNeedsDraw = true;
invalidateSelf();
}
@@ -548,6 +557,8 @@
}
cancelExitingRipples();
+
+ mNeedsDraw = true;
invalidateSelf();
}
@@ -642,11 +653,12 @@
canvas.restoreToCount(rippleLayer);
}
- // If we failed to draw anything, at least draw a color so that
- // invalidation works correctly.
- if (contentLayer < 0 && backgroundLayer < 0 && rippleLayer < 0) {
+ // If we failed to draw anything and we just canceled animations, at
+ // least draw a color so that hardware invalidation works correctly.
+ if (contentLayer < 0 && backgroundLayer < 0 && rippleLayer < 0 && mNeedsDraw) {
canvas.drawColor(Color.TRANSPARENT);
}
+ mNeedsDraw = false;
canvas.restoreToCount(saveCount);
}
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 042da5b..4407a3c 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -104,8 +104,6 @@
* <dt><code>android:translateY</code></dt>
* <dd>The amount of translation on the Y coordinate.
* This is defined in the viewport space.</dd>
- * <dt><code>android:alpha</code></dt>
- * <dd>The amount of transparency.</dd>
* </dl></dd>
* </dl>
*
@@ -124,6 +122,10 @@
* <dd>Defines the color to draw the path outline (none if not present).</dd>
* <dt><code>android:strokeWidth</code></dt>
* <dd>The width a path stroke.</dd>
+ * <dt><code>android:strokeAlpha</code></dt>
+ * <dd>The opacity of a path stroke.</dd>
+ * <dt><code>android:fillAlpha</code></dt>
+ * <dd>The opacity to fill the path with.</dd>
* <dt><code>android:trimPathStart</code></dt>
* <dd>The fraction of the path to trim from the start, in the range from 0 to 1.</dd>
* <dt><code>android:trimPathEnd</code></dt>
@@ -368,6 +370,29 @@
}
}
+ /**
+ * The size of a pixel when scaled from the intrinsic dimension to the viewport dimension.
+ * This is used to calculate the path animation accuracy.
+ *
+ * @hide
+ */
+ public float getPixelSize() {
+ if (mVectorState == null && mVectorState.mVPathRenderer == null ||
+ mVectorState.mVPathRenderer.mBaseWidth == 0 ||
+ mVectorState.mVPathRenderer.mBaseHeight == 0 ||
+ mVectorState.mVPathRenderer.mViewportHeight == 0 ||
+ mVectorState.mVPathRenderer.mViewportWidth == 0) {
+ return 1; // fall back to 1:1 pixel mapping.
+ }
+ float intrinsicWidth = mVectorState.mVPathRenderer.mBaseWidth;
+ float intrinsicHeight = mVectorState.mVPathRenderer.mBaseHeight;
+ float viewportWidth = mVectorState.mVPathRenderer.mViewportWidth;
+ float viewportHeight = mVectorState.mVPathRenderer.mViewportHeight;
+ float scaleX = viewportWidth / intrinsicWidth;
+ float scaleY = viewportHeight / intrinsicHeight;
+ return Math.min(scaleX, scaleY);
+ }
+
/** @hide */
public static VectorDrawable create(Resources resources, int rid) {
try {
@@ -606,6 +631,15 @@
mThemeAttrs = copy.mThemeAttrs;
mChangingConfigurations = copy.mChangingConfigurations;
mVPathRenderer = new VPathRenderer(copy.mVPathRenderer);
+ if (copy.mVPathRenderer.mFillPaint != null) {
+ mVPathRenderer.mFillPaint = new Paint(copy.mVPathRenderer.mFillPaint);
+ }
+ if (copy.mVPathRenderer.mStrokePaint != null) {
+ mVPathRenderer.mStrokePaint = new Paint(copy.mVPathRenderer.mStrokePaint);
+ }
+ if (copy.mVPathRenderer.mColorFilter != null) {
+ mVPathRenderer.mColorFilter = copy.mVPathRenderer.mColorFilter;
+ }
mTint = copy.mTint;
mTintMode = copy.mTintMode;
mAutoMirrored = copy.mAutoMirrored;
@@ -677,8 +711,8 @@
*/
// Variables that only used temporarily inside the draw() call, so there
// is no need for deep copying.
- private final Path mPath = new Path();
- private final Path mRenderPath = new Path();
+ private final Path mPath;
+ private final Path mRenderPath;
private static final Matrix IDENTITY_MATRIX = new Matrix();
private final Matrix mFinalPathMatrix = new Matrix();
@@ -701,6 +735,8 @@
public VPathRenderer() {
mRootGroup = new VGroup();
+ mPath = new Path();
+ mRenderPath = new Path();
}
public void setRootAlpha(int alpha) {
@@ -713,6 +749,8 @@
public VPathRenderer(VPathRenderer copy) {
mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
+ mPath = new Path(copy.mPath);
+ mRenderPath = new Path(copy.mRenderPath);
mBaseWidth = copy.mBaseWidth;
mBaseHeight = copy.mBaseHeight;
mViewportWidth = copy.mViewportWidth;
@@ -789,7 +827,7 @@
}
private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix,
- float currentAlpha, Canvas canvas, int w, int h) {
+ Canvas canvas, int w, int h) {
// Calculate current group's matrix by preConcat the parent's and
// and the current one on the top of the stack.
// Basically the Mfinal = Mviewport * M0 * M1 * M2;
@@ -798,30 +836,26 @@
currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
- float stackedAlpha = currentAlpha * currentGroup.mGroupAlpha;
-
// Draw the group tree in the same order as the XML file.
for (int i = 0; i < currentGroup.mChildren.size(); i++) {
Object child = currentGroup.mChildren.get(i);
if (child instanceof VGroup) {
VGroup childGroup = (VGroup) child;
drawGroupTree(childGroup, currentGroup.mStackedMatrix,
- stackedAlpha, canvas, w, h);
+ canvas, w, h);
} else if (child instanceof VPath) {
VPath childPath = (VPath) child;
- drawPath(currentGroup, childPath, stackedAlpha, canvas, w, h);
+ drawPath(currentGroup, childPath, canvas, w, h);
}
}
}
public void draw(Canvas canvas, int w, int h) {
// Travese the tree in pre-order to draw.
- drawGroupTree(mRootGroup, IDENTITY_MATRIX, ((float) mRootAlpha) / 0xFF,
- canvas, w, h);
+ drawGroupTree(mRootGroup, IDENTITY_MATRIX, canvas, w, h);
}
- private void drawPath(VGroup vGroup, VPath vPath, float stackedAlpha,
- Canvas canvas, int w, int h) {
+ private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h) {
final float scaleX = w / mViewportWidth;
final float scaleY = h / mViewportHeight;
final float minScale = Math.min(scaleX, scaleY);
@@ -869,7 +903,8 @@
mFillPaint.setStyle(Paint.Style.FILL);
mFillPaint.setAntiAlias(true);
}
- mFillPaint.setColor(applyAlpha(fullPath.mFillColor, stackedAlpha));
+ mFillPaint.setColor(applyAlpha(fullPath.mFillColor,
+ fullPath.mFillAlpha));
canvas.drawPath(mRenderPath, mFillPaint);
}
@@ -892,7 +927,8 @@
strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
- strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, stackedAlpha));
+ strokePaint.setColor(applyAlpha(fullPath.mStrokeColor,
+ fullPath.mStrokeAlpha));
strokePaint.setStrokeWidth(fullPath.mStrokeWidth * minScale);
canvas.drawPath(mRenderPath, strokePaint);
}
@@ -916,7 +952,6 @@
private float mScaleY = 1;
private float mTranslateX = 0;
private float mTranslateY = 0;
- private float mGroupAlpha = 1;
// mLocalMatrix is updated based on the update of transformation information,
// either parsed from the XML or by animation.
@@ -933,7 +968,6 @@
mScaleY = copy.mScaleY;
mTranslateX = copy.mTranslateX;
mTranslateY = copy.mTranslateY;
- mGroupAlpha = copy.mGroupAlpha;
mThemeAttrs = copy.mThemeAttrs;
mGroupName = copy.mGroupName;
mChangingConfigurations = copy.mChangingConfigurations;
@@ -1002,7 +1036,6 @@
mScaleY = a.getFloat(R.styleable.VectorDrawableGroup_scaleY, mScaleY);
mTranslateX = a.getFloat(R.styleable.VectorDrawableGroup_translateX, mTranslateX);
mTranslateY = a.getFloat(R.styleable.VectorDrawableGroup_translateY, mTranslateY);
- mGroupAlpha = a.getFloat(R.styleable.VectorDrawableGroup_alpha, mGroupAlpha);
final String groupName = a.getString(R.styleable.VectorDrawableGroup_name);
if (groupName != null) {
@@ -1124,18 +1157,6 @@
updateLocalMatrix();
}
}
-
- @SuppressWarnings("unused")
- public float getAlpha() {
- return mGroupAlpha;
- }
-
- @SuppressWarnings("unused")
- public void setAlpha(float groupAlpha) {
- if (groupAlpha != mGroupAlpha) {
- mGroupAlpha = groupAlpha;
- }
- }
}
/**
@@ -1239,8 +1260,11 @@
int mStrokeColor = Color.TRANSPARENT;
float mStrokeWidth = 0;
+
int mFillColor = Color.TRANSPARENT;
+ float mStrokeAlpha = 1.0f;
int mFillRule;
+ float mFillAlpha = 1.0f;
float mTrimPathStart = 0;
float mTrimPathEnd = 1;
float mTrimPathOffset = 0;
@@ -1259,8 +1283,10 @@
mStrokeColor = copy.mStrokeColor;
mStrokeWidth = copy.mStrokeWidth;
+ mStrokeAlpha = copy.mStrokeAlpha;
mFillColor = copy.mFillColor;
mFillRule = copy.mFillRule;
+ mFillAlpha = copy.mFillAlpha;
mTrimPathStart = copy.mTrimPathStart;
mTrimPathEnd = copy.mTrimPathEnd;
mTrimPathOffset = copy.mTrimPathOffset;
@@ -1321,6 +1347,8 @@
mFillColor = a.getColor(R.styleable.VectorDrawablePath_fillColor,
mFillColor);
+ mFillAlpha = a.getFloat(R.styleable.VectorDrawablePath_fillAlpha,
+ mFillAlpha);
mStrokeLineCap = getStrokeLineCap(a.getInt(
R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
mStrokeLineJoin = getStrokeLineJoin(a.getInt(
@@ -1329,6 +1357,8 @@
R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_strokeColor,
mStrokeColor);
+ mStrokeAlpha = a.getFloat(R.styleable.VectorDrawablePath_strokeAlpha,
+ mStrokeAlpha);
mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth,
mStrokeWidth);
mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd,
@@ -1373,6 +1403,16 @@
}
@SuppressWarnings("unused")
+ float getstrokeAlpha() {
+ return mStrokeAlpha;
+ }
+
+ @SuppressWarnings("unused")
+ void setstrokeAlpha(float strokeAlpha) {
+ mStrokeAlpha = strokeAlpha;
+ }
+
+ @SuppressWarnings("unused")
int getFill() {
return mFillColor;
}
@@ -1383,6 +1423,16 @@
}
@SuppressWarnings("unused")
+ float getfillAlpha() {
+ return mFillAlpha;
+ }
+
+ @SuppressWarnings("unused")
+ void setfillAlpha(float fillAlpha) {
+ mFillAlpha = fillAlpha;
+ }
+
+ @SuppressWarnings("unused")
float getTrimPathStart() {
return mTrimPathStart;
}
diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java
new file mode 100644
index 0000000..9837139
--- /dev/null
+++ b/graphics/java/android/graphics/pdf/PdfEditor.java
@@ -0,0 +1,162 @@
+/*
+ * 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.graphics.pdf;
+
+import android.annotation.NonNull;
+import android.os.ParcelFileDescriptor;
+import android.system.ErrnoException;
+import android.system.OsConstants;
+import dalvik.system.CloseGuard;
+import libcore.io.IoUtils;
+import libcore.io.Libcore;
+
+import java.io.IOException;
+
+/**
+ * Class for editing PDF files.
+ *
+ * @hide
+ */
+public final class PdfEditor {
+
+ private final CloseGuard mCloseGuard = CloseGuard.get();
+
+ private final long mNativeDocument;
+
+ private int mPageCount;
+
+ private ParcelFileDescriptor mInput;
+
+ /**
+ * Creates a new instance.
+ * <p>
+ * <strong>Note:</strong> The provided file descriptor must be <strong>seekable</strong>,
+ * i.e. its data being randomly accessed, e.g. pointing to a file. After finishing
+ * with this class you must call {@link #close()}.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> This class takes ownership of the passed in file descriptor
+ * and is responsible for closing it when the editor is closed.
+ * </p>
+ *
+ * @param input Seekable file descriptor to read from.
+ *
+ * @see #close()
+ */
+ public PdfEditor(@NonNull ParcelFileDescriptor input) throws IOException {
+ if (input == null) {
+ throw new NullPointerException("input cannot be null");
+ }
+
+ final long size;
+ try {
+ Libcore.os.lseek(input.getFileDescriptor(), 0, OsConstants.SEEK_SET);
+ size = Libcore.os.fstat(input.getFileDescriptor()).st_size;
+ } catch (ErrnoException ee) {
+ throw new IllegalArgumentException("file descriptor not seekable");
+ }
+
+ mInput = input;
+ mNativeDocument = nativeOpen(mInput.getFd(), size);
+ mPageCount = nativeGetPageCount(mNativeDocument);
+ mCloseGuard.open("close");
+ }
+
+ /**
+ * Gets the number of pages in the document.
+ *
+ * @return The page count.
+ */
+ public int getPageCount() {
+ throwIfClosed();
+ return mPageCount;
+ }
+
+ /**
+ * Removes the page with a given index.
+ *
+ * @param pageIndex The page to remove.
+ */
+ public void removePage(int pageIndex) {
+ throwIfClosed();
+ throwIfPageNotInDocument(pageIndex);
+ mPageCount = nativeRemovePage(mNativeDocument, pageIndex);
+ }
+
+ /**
+ * Writes the PDF file to the provided destination.
+ * <p>
+ * <strong>Note:</strong> This method takes ownership of the passed in file
+ * descriptor and is responsible for closing it when writing completes.
+ * </p>
+ * @param output The destination.
+ */
+ public void write(ParcelFileDescriptor output) throws IOException {
+ try {
+ throwIfClosed();
+ nativeWrite(mNativeDocument, output.getFd());
+ } finally {
+ IoUtils.closeQuietly(output);
+ }
+ }
+
+ /**
+ * Closes this editor. You should not use this instance
+ * after this method is called.
+ */
+ public void close() {
+ throwIfClosed();
+ doClose();
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ mCloseGuard.warnIfOpen();
+ if (mInput != null) {
+ doClose();
+ }
+ } finally {
+ super.finalize();
+ }
+ }
+
+ private void doClose() {
+ nativeClose(mNativeDocument);
+ IoUtils.closeQuietly(mInput);
+ mInput = null;
+ mCloseGuard.close();
+ }
+
+ private void throwIfClosed() {
+ if (mInput == null) {
+ throw new IllegalStateException("Already closed");
+ }
+ }
+
+ private void throwIfPageNotInDocument(int pageIndex) {
+ if (pageIndex < 0 || pageIndex >= mPageCount) {
+ throw new IllegalArgumentException("Invalid page index");
+ }
+ }
+
+ private static native long nativeOpen(int fd, long size);
+ private static native void nativeClose(long documentPtr);
+ private static native int nativeGetPageCount(long documentPtr);
+ private static native int nativeRemovePage(long documentPtr, int pageIndex);
+ private static native void nativeWrite(long documentPtr, int fd);
+}
diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java
index 1072b3c..359c294 100644
--- a/graphics/java/android/graphics/pdf/PdfRenderer.java
+++ b/graphics/java/android/graphics/pdf/PdfRenderer.java
@@ -239,7 +239,7 @@
}
private void throwIfPageNotInDocument(int pageIndex) {
- if (pageIndex >= mPageCount) {
+ if (pageIndex < 0 || pageIndex >= mPageCount) {
throw new IllegalArgumentException("Invalid page index");
}
}
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl
index 60fd7f7..20c94c5 100644
--- a/keystore/java/android/security/IKeyChainService.aidl
+++ b/keystore/java/android/security/IKeyChainService.aidl
@@ -15,6 +15,8 @@
*/
package android.security;
+import android.content.pm.ParceledListSlice;
+
/**
* Caller is required to ensure that {@link KeyStore#unlock
* KeyStore.unlock} was successful.
@@ -29,9 +31,17 @@
// APIs used by CertInstaller
void installCaCertificate(in byte[] caCertificate);
+ // APIs used by DevicePolicyManager
+ boolean installKeyPair(in byte[] privateKey, in byte[] userCert, String alias);
+
// APIs used by Settings
boolean deleteCaCertificate(String alias);
boolean reset();
+ ParceledListSlice getUserCaAliases();
+ ParceledListSlice getSystemCaAliases();
+ boolean containsCaAlias(String alias);
+ byte[] getEncodedCaCertificate(String alias, boolean includeDeletedSystem);
+ List<String> getCaCertificateChainAliases(String rootAlias, boolean includeDeletedSystem);
// APIs used by KeyChainActivity
void setGrant(int uid, String alias, boolean value);
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 0da2b99..131e689 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -397,7 +397,8 @@
return KeyStore.getInstance().isHardwareBacked(algorithm);
}
- private static X509Certificate toCertificate(byte[] bytes) {
+ /** @hide */
+ public static X509Certificate toCertificate(byte[] bytes) {
if (bytes == null) {
throw new IllegalArgumentException("bytes == null");
}
diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp
index 4873479..cb3a002 100644
--- a/libs/hwui/AmbientShadow.cpp
+++ b/libs/hwui/AmbientShadow.cpp
@@ -91,36 +91,13 @@
return getTransformedAlphaFromAlpha(getAlphaFromFactoredZ(factoredZ));
}
-inline int getExtraVertexNumber(const Vector2& vector1, const Vector2& vector2,
- float divisor) {
- // When there is no distance difference, there is no need for extra vertices.
- if (vector1.lengthSquared() == 0 || vector2.lengthSquared() == 0) {
- return 0;
- }
- // The formula is :
- // extraNumber = floor(acos(dot(n1, n2)) / (M_PI / EXTRA_VERTEX_PER_PI))
- // The value ranges for each step are:
- // dot( ) --- [-1, 1]
- // acos( ) --- [0, M_PI]
- // floor(...) --- [0, EXTRA_VERTEX_PER_PI]
- float dotProduct = vector1.dot(vector2);
- // TODO: Use look up table for the dotProduct to extraVerticesNumber
- // computation, if needed.
- float angle = acosf(dotProduct);
- return (int) floor(angle / divisor);
-}
-
-inline void checkOverflow(int used, int total, const char* bufferName) {
- LOG_ALWAYS_FATAL_IF(used > total, "Error: %s overflow!!! used %d, total %d",
- bufferName, used, total);
-}
-
inline int getEdgeExtraAndUpdateSpike(Vector2* currentSpike,
const Vector3& secondVertex, const Vector3& centroid) {
Vector2 secondSpike = {secondVertex.x - centroid.x, secondVertex.y - centroid.y};
secondSpike.normalize();
- int result = getExtraVertexNumber(secondSpike, *currentSpike, EDGE_RADIANS_DIVISOR);
+ int result = ShadowTessellator::getExtraVertexNumber(secondSpike, *currentSpike,
+ EDGE_RADIANS_DIVISOR);
*currentSpike = secondSpike;
return result;
}
@@ -231,8 +208,8 @@
Vector2 currentNormal = getNormalFromVertices(casterVertices, i,
(i + 1) % casterVertexCount);
- int extraVerticesNumber = getExtraVertexNumber(currentNormal, previousNormal,
- CORNER_RADIANS_DIVISOR);
+ int extraVerticesNumber = ShadowTessellator::getExtraVertexNumber(currentNormal,
+ previousNormal, CORNER_RADIANS_DIVISOR);
float expansionDist = innerVertex.z * heightFactor * geomFactor;
const int cornerSlicesNumber = extraVerticesNumber + 1; // Minimal as 1.
@@ -349,9 +326,9 @@
shadowVertexBuffer.updateVertexCount(vertexBufferIndex);
shadowVertexBuffer.updateIndexCount(indexBufferIndex);
- checkOverflow(vertexBufferIndex, totalVertexCount, "Vertex Buffer");
- checkOverflow(indexBufferIndex, totalIndexCount, "Index Buffer");
- checkOverflow(umbraIndex, totalUmbraCount, "Umbra Buffer");
+ ShadowTessellator::checkOverflow(vertexBufferIndex, totalVertexCount, "Vertex Buffer");
+ ShadowTessellator::checkOverflow(indexBufferIndex, totalIndexCount, "Index Buffer");
+ ShadowTessellator::checkOverflow(umbraIndex, totalUmbraCount, "Umbra Buffer");
#if DEBUG_SHADOW
for (int i = 0; i < vertexBufferIndex; i++) {
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 9855f71..9b0025f 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -342,6 +342,7 @@
void Caches::deleteLayerDeferred(Layer* layer) {
Mutex::Autolock _l(mGarbageLock);
+ layer->state = Layer::kState_InGarbageList;
mLayerGarbage.push(layer);
}
@@ -551,9 +552,13 @@
}
void Caches::bindTexture(GLenum target, GLuint texture) {
- if (mBoundTextures[mTextureUnit] != texture) {
+ if (target == GL_TEXTURE_2D) {
+ bindTexture(texture);
+ } else {
+ // GLConsumer directly calls glBindTexture() with
+ // target=GL_TEXTURE_EXTERNAL_OES, don't cache this target
+ // since the cached state could be stale
glBindTexture(target, texture);
- mBoundTextures[mTextureUnit] = texture;
}
}
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 726b74d..7aa628c 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -431,6 +431,7 @@
uint32_t mFunctorsCount;
+ // Caches texture bindings for the GL_TEXTURE_2D target
GLuint mBoundTextures[REQUIRED_TEXTURE_UNITS_COUNT];
OverdrawColorSet mOverdrawDebugColorSet;
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 25caae3..b5089aa 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -29,15 +29,16 @@
namespace android {
namespace uirenderer {
-Layer::Layer(RenderState& renderState, const uint32_t layerWidth, const uint32_t layerHeight)
- : caches(Caches::getInstance())
+Layer::Layer(Type layerType, RenderState& renderState, const uint32_t layerWidth, const uint32_t layerHeight)
+ : state(kState_Uncached)
+ , caches(Caches::getInstance())
, renderState(renderState)
- , texture(caches) {
+ , texture(caches)
+ , type(layerType) {
mesh = NULL;
meshElementCount = 0;
cacheable = true;
dirty = false;
- textureLayer = false;
renderTarget = GL_TEXTURE_2D;
texture.width = layerWidth;
texture.height = layerHeight;
@@ -55,11 +56,17 @@
caches.resourceCache.incrementRefcount(this);
rendererLightPosDirty = true;
wasBuildLayered = false;
- renderState.registerLayer(this);
+ if (!isTextureLayer()) {
+ // track only non-texture layer lifecycles in renderstate,
+ // because texture layers are destroyed via finalizer
+ renderState.registerLayer(this);
+ }
}
Layer::~Layer() {
- renderState.unregisterLayer(this);
+ if (!isTextureLayer()) {
+ renderState.unregisterLayer(this);
+ }
SkSafeUnref(colorFilter);
removeFbo();
deleteTexture();
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 911b99880..a8e1c26 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -54,7 +54,23 @@
*/
class Layer {
public:
- Layer(RenderState& renderState, const uint32_t layerWidth, const uint32_t layerHeight);
+ enum Type {
+ kType_Texture,
+ kType_DisplayList,
+ };
+
+ // layer lifecycle, controlled from outside
+ enum State {
+ kState_Uncached = 0,
+ kState_InCache = 1,
+ kState_FailedToCache = 2,
+ kState_RemovedFromCache = 3,
+ kState_DeletedFromCache = 4,
+ kState_InGarbageList = 5,
+ };
+ State state; // public for logging/debugging purposes
+
+ Layer(Type type, RenderState& renderState, const uint32_t layerWidth, const uint32_t layerHeight);
~Layer();
static uint32_t computeIdealWidth(uint32_t layerWidth);
@@ -219,11 +235,7 @@
}
inline bool isTextureLayer() const {
- return textureLayer;
- }
-
- inline void setTextureLayer(bool textureLayer) {
- this->textureLayer = textureLayer;
+ return type == kType_Texture;
}
inline SkColorFilter* getColorFilter() const {
@@ -343,10 +355,9 @@
bool cacheable;
/**
- * When set to true, this layer must be treated as a texture
- * layer.
+ * Denotes whether the layer is a DisplayList, or Texture layer.
*/
- bool textureLayer;
+ const Type type;
/**
* When set to true, this layer is dirty and should be cleared
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index efa30ac..833f64b 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -83,6 +83,7 @@
LAYER_LOGD("Destroying layer %dx%d, fbo %d", layer->getWidth(), layer->getHeight(),
layer->getFbo());
mSize -= layer->getWidth() * layer->getHeight() * 4;
+ layer->state = Layer::kState_DeletedFromCache;
Caches::getInstance().resourceCache.decrementRefcount(layer);
}
}
@@ -106,13 +107,14 @@
mCache.removeAt(index);
layer = entry.mLayer;
+ layer->state = Layer::kState_RemovedFromCache;
mSize -= layer->getWidth() * layer->getHeight() * 4;
LAYER_LOGD("Reusing layer %dx%d", layer->getWidth(), layer->getHeight());
} else {
LAYER_LOGD("Creating new layer %dx%d", entry.mWidth, entry.mHeight);
- layer = new Layer(renderState, entry.mWidth, entry.mHeight);
+ layer = new Layer(Layer::kType_DisplayList, renderState, entry.mWidth, entry.mHeight);
layer->setBlend(true);
layer->setEmpty(true);
layer->setFbo(0);
@@ -166,8 +168,11 @@
mCache.add(entry);
mSize += size;
+ layer->state = Layer::kState_InCache;
return true;
}
+
+ layer->state = Layer::kState_FailedToCache;
return false;
}
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index e3b0daf..103c843 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -272,9 +272,8 @@
Layer* LayerRenderer::createTextureLayer(RenderState& renderState) {
LAYER_RENDERER_LOGD("Creating new texture layer");
- Layer* layer = new Layer(renderState, 0, 0);
+ Layer* layer = new Layer(Layer::kType_Texture, renderState, 0, 0);
layer->setCacheable(false);
- layer->setTextureLayer(true);
layer->setEmpty(true);
layer->setFbo(0);
layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index dbd273d..31cc1c8 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -54,10 +54,6 @@
namespace android {
namespace uirenderer {
-///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
static GLenum getFilter(const SkPaint* paint) {
if (!paint || paint->getFilterLevel() != SkPaint::kNone_FilterLevel) {
return GL_LINEAR;
@@ -3044,21 +3040,35 @@
}
void OpenGLRenderer::setupPaintFilter(int clearBits, int setBits) {
+ // TODO: don't bother with boolean, it's redundant with clear/set bits
mDrawModifiers.mHasDrawFilter = true;
mDrawModifiers.mPaintFilterClearBits = clearBits & SkPaint::kAllFlags;
mDrawModifiers.mPaintFilterSetBits = setBits & SkPaint::kAllFlags;
}
const SkPaint* OpenGLRenderer::filterPaint(const SkPaint* paint) {
+ // TODO: use CompatFlagsDrawFilter here, and combine logic with android/graphics/DrawFilter.cpp
+ // to avoid clobbering 0x02 paint flag
+
+ // Equivalent to the Java Paint's FILTER_BITMAP_FLAG.
+ static const uint32_t sFilterBitmapFlag = 0x02;
+
if (CC_LIKELY(!mDrawModifiers.mHasDrawFilter || !paint)) {
return paint;
}
- uint32_t flags = paint->getFlags();
+ const uint32_t clearBits = mDrawModifiers.mPaintFilterClearBits;
+ const uint32_t setBits = mDrawModifiers.mPaintFilterSetBits;
+ const uint32_t flags = (paint->getFlags() & ~clearBits) | setBits;
mFilteredPaint = *paint;
- mFilteredPaint.setFlags((flags & ~mDrawModifiers.mPaintFilterClearBits) |
- mDrawModifiers.mPaintFilterSetBits);
+ mFilteredPaint.setFlags(flags);
+
+ // check if paint filter trying to override bitmap filter
+ if ((clearBits | setBits) & sFilterBitmapFlag) {
+ mFilteredPaint.setFilterLevel(flags & sFilterBitmapFlag
+ ? SkPaint::kLow_FilterLevel : SkPaint::kNone_FilterLevel);
+ }
return &mFilteredPaint;
}
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index e30ac19..281ca02 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -162,14 +162,21 @@
}
/**
- * Outset the bounds of point data (for line endpoints or points) to account for AA stroke
+ * Outset the bounds of point data (for line endpoints or points) to account for stroke
* geometry.
+ *
+ * bounds are in pre-scaled space.
*/
void expandBoundsForStroke(Rect* bounds) const {
- float outset = halfStrokeWidth;
- if (outset == 0) outset = 0.5f;
- bounds->outset(outset * inverseScaleX + Vertex::GeometryFudgeFactor(),
- outset * inverseScaleY + Vertex::GeometryFudgeFactor());
+ if (halfStrokeWidth == 0) {
+ // hairline, outset by (0.5f + fudge factor) in post-scaling space
+ bounds->outset(fabs(inverseScaleX) * (0.5f + Vertex::GeometryFudgeFactor()),
+ fabs(inverseScaleY) * (0.5f + Vertex::GeometryFudgeFactor()));
+ } else {
+ // non hairline, outset by half stroke width pre-scaled, and fudge factor post scaled
+ bounds->outset(halfStrokeWidth + fabs(inverseScaleX) * Vertex::GeometryFudgeFactor(),
+ halfStrokeWidth + fabs(inverseScaleY) * Vertex::GeometryFudgeFactor());
+ }
}
};
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index a10e70f..254492f 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -872,6 +872,8 @@
handler(new (alloc) DrawLayerOp(mLayer, 0, 0),
renderer.getSaveCount() - 1, properties().getClipToBounds());
} else {
+ const int saveCountOffset = renderer.getSaveCount() - 1;
+ const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
for (size_t chunkIndex = 0; chunkIndex < mDisplayListData->getChunks().size(); chunkIndex++) {
const DisplayListData::Chunk& chunk = mDisplayListData->getChunks()[chunkIndex];
@@ -882,8 +884,6 @@
issueOperationsOf3dChildren(kNegativeZChildren,
initialTransform, zTranslatedNodes, renderer, handler);
- const int saveCountOffset = renderer.getSaveCount() - 1;
- const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
for (int opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
DisplayListOp *op = mDisplayListData->displayListOps[opIndex];
diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/RenderState.cpp
index ec8307f..54af528 100644
--- a/libs/hwui/RenderState.cpp
+++ b/libs/hwui/RenderState.cpp
@@ -39,13 +39,16 @@
void RenderState::onGLContextDestroyed() {
AutoMutex _lock(mLayerLock);
- if (CC_UNLIKELY(!mActiveLayers.empty())) {
+ size_t size = mActiveLayers.size();
+ if (CC_UNLIKELY(size != 0)) {
+ ALOGE("Crashing, have %d contexts and %d layers at context destruction. isempty %d",
+ mRegisteredContexts.size(), size, mActiveLayers.empty());
mCaches->dumpMemoryUsage();
for (std::set<renderthread::CanvasContext*>::iterator cit = mRegisteredContexts.begin();
cit != mRegisteredContexts.end(); cit++) {
renderthread::CanvasContext* context = *cit;
- ALOGD("Context: %p (root = %p)", context, context->mRootRenderNode.get());
- ALOGD(" Prefeteched layers: %zu", context->mPrefetechedLayers.size());
+ ALOGE("Context: %p (root = %p)", context, context->mRootRenderNode.get());
+ ALOGE(" Prefeteched layers: %zu", context->mPrefetechedLayers.size());
for (std::set<RenderNode*>::iterator pit = context->mPrefetechedLayers.begin();
pit != context->mPrefetechedLayers.end(); pit++) {
(*pit)->debugDumpLayers(" ");
@@ -53,13 +56,17 @@
context->mRootRenderNode->debugDumpLayers(" ");
}
+
+ if (mActiveLayers.begin() == mActiveLayers.end()) {
+ ALOGE("set has become empty. wat.");
+ }
for (std::set<const Layer*>::iterator lit = mActiveLayers.begin();
lit != mActiveLayers.end(); lit++) {
const Layer* layer = *(lit);
- ALOGD("Layer %p, fbo %d, buildlayered %d",
- layer, layer->getFbo(), layer->wasBuildLayered);
+ ALOGE("Layer %p, state %d, texlayer %d, fbo %d, buildlayered %d",
+ layer, layer->state, layer->isTextureLayer(), layer->getFbo(), layer->wasBuildLayered);
}
- LOG_ALWAYS_FATAL("layers have survived gl context destruction");
+ LOG_ALWAYS_FATAL("%d layers have survived gl context destruction", size);
}
}
diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index 6cff815..c1ffa0a 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -252,5 +252,29 @@
}
}
+int ShadowTessellator::getExtraVertexNumber(const Vector2& vector1,
+ const Vector2& vector2, float divisor) {
+ // When there is no distance difference, there is no need for extra vertices.
+ if (vector1.lengthSquared() == 0 || vector2.lengthSquared() == 0) {
+ return 0;
+ }
+ // The formula is :
+ // extraNumber = floor(acos(dot(n1, n2)) / (M_PI / EXTRA_VERTEX_PER_PI))
+ // The value ranges for each step are:
+ // dot( ) --- [-1, 1]
+ // acos( ) --- [0, M_PI]
+ // floor(...) --- [0, EXTRA_VERTEX_PER_PI]
+ float dotProduct = vector1.dot(vector2);
+ // TODO: Use look up table for the dotProduct to extraVerticesNumber
+ // computation, if needed.
+ float angle = acosf(dotProduct);
+ return (int) floor(angle / divisor);
+}
+
+void ShadowTessellator::checkOverflow(int used, int total, const char* bufferName) {
+ LOG_ALWAYS_FATAL_IF(used > total, "Error: %s overflow!!! used %d, total %d",
+ bufferName, used, total);
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/ShadowTessellator.h b/libs/hwui/ShadowTessellator.h
index 141dff6..8f19b5c 100644
--- a/libs/hwui/ShadowTessellator.h
+++ b/libs/hwui/ShadowTessellator.h
@@ -101,6 +101,10 @@
*/
static void reverseVertexArray(Vertex* polygon, int len);
+ static int getExtraVertexNumber(const Vector2& vector1, const Vector2& vector2,
+ float divisor);
+
+ static void checkOverflow(int used, int total, const char* bufferName);
}; // ShadowTessellator
}; // namespace uirenderer
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index 2178cc7..dbedf94 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -16,10 +16,34 @@
#define LOG_TAG "OpenGLRenderer"
-#define SHADOW_SHRINK_SCALE 0.1f
+// The highest z value can't be higher than (CASTER_Z_CAP_RATIO * light.z)
#define CASTER_Z_CAP_RATIO 0.95f
-#define FAKE_UMBRA_SIZE_RATIO 0.01f
-#define OCLLUDED_UMBRA_SHRINK_FACTOR 0.95f
+
+// When there is no umbra, then just fake the umbra using
+// centroid * (1 - FAKE_UMBRA_SIZE_RATIO) + outline * FAKE_UMBRA_SIZE_RATIO
+#define FAKE_UMBRA_SIZE_RATIO 0.05f
+
+// When the polygon is about 90 vertices, the penumbra + umbra can reach 270 rays.
+// That is consider pretty fine tessllated polygon so far.
+// This is just to prevent using too much some memory when edge slicing is not
+// needed any more.
+#define FINE_TESSELLATED_POLYGON_RAY_NUMBER 270
+/**
+ * Extra vertices for the corner for smoother corner.
+ * Only for outer loop.
+ * Note that we use such extra memory to avoid an extra loop.
+ */
+// For half circle, we could add EXTRA_VERTEX_PER_PI vertices.
+// Set to 1 if we don't want to have any.
+#define SPOT_EXTRA_CORNER_VERTEX_PER_PI 18
+
+// For the whole polygon, the sum of all the deltas b/t normals is 2 * M_PI,
+// therefore, the maximum number of extra vertices will be twice bigger.
+#define SPOT_MAX_EXTRA_CORNER_VERTEX_NUMBER (2 * SPOT_EXTRA_CORNER_VERTEX_PER_PI)
+
+// For each RADIANS_DIVISOR, we would allocate one more vertex b/t the normals.
+#define SPOT_CORNER_RADIANS_DIVISOR (M_PI / SPOT_EXTRA_CORNER_VERTEX_PER_PI)
+
#include <math.h>
#include <stdlib.h>
@@ -51,6 +75,24 @@
};
/**
+ * For each vertex, we need to keep track of its angle, whether it is penumbra or
+ * umbra, and its corresponding vertex index.
+ */
+struct SpotShadow::VertexAngleData {
+ // The angle to the vertex from the centroid.
+ float mAngle;
+ // True is the vertex comes from penumbra, otherwise it comes from umbra.
+ bool mIsPenumbra;
+ // The index of the vertex described by this data.
+ int mVertexIndex;
+ void set(float angle, bool isPenumbra, int index) {
+ mAngle = angle;
+ mIsPenumbra = isPenumbra;
+ mVertexIndex = index;
+ }
+};
+
+/**
* Calculate the angle between and x and a y coordinate.
* The atan2 range from -PI to PI.
*/
@@ -407,8 +449,8 @@
double endX = poly[i].x;
double endY = poly[i].y;
- if (((endY > testy) != (startY > testy)) &&
- (testx < (startX - endX) * (testy - endY)
+ if (((endY > testy) != (startY > testy))
+ && (testx < (startX - endX) * (testy - endY)
/ (startY - endY) + endX)) {
c = !c;
}
@@ -508,138 +550,14 @@
}
/**
-* Generate the shadow from a spot light.
-*
-* @param poly x,y,z vertexes of a convex polygon that occludes the light source
-* @param polyLength number of vertexes of the occluding polygon
-* @param lightCenter the center of the light
-* @param lightSize the radius of the light source
-* @param lightVertexCount the vertex counter for the light polygon
-* @param shadowTriangleStrip return an (x,y,alpha) triangle strip representing the shadow. Return
-* empty strip if error.
-*
-*/
-
-void SpotShadow::createSpotShadow_old(bool isCasterOpaque, const Vector3* poly,
- int polyLength, const Vector3& lightCenter, float lightSize,
- int lightVertexCount, VertexBuffer& retStrips) {
- Vector3 light[lightVertexCount * 3];
- computeLightPolygon(lightVertexCount, lightCenter, lightSize, light);
- computeSpotShadow_old(isCasterOpaque, light, lightVertexCount, lightCenter, poly,
- polyLength, retStrips);
-}
-
-/**
- * Generate the shadow spot light of shape lightPoly and a object poly
+ * From light center, project one vertex to the z=0 surface and get the outline.
*
- * @param lightPoly x,y,z vertex of a convex polygon that is the light source
- * @param lightPolyLength number of vertexes of the light source polygon
- * @param poly x,y,z vertexes of a convex polygon that occludes the light source
- * @param polyLength number of vertexes of the occluding polygon
- * @param shadowTriangleStrip return an (x,y,alpha) triangle strip representing the shadow. Return
- * empty strip if error.
+ * @param outline The result which is the outline position.
+ * @param lightCenter The center of light.
+ * @param polyVertex The input polygon's vertex.
+ *
+ * @return float The ratio of (polygon.z / light.z - polygon.z)
*/
-void SpotShadow::computeSpotShadow_old(bool isCasterOpaque, const Vector3* lightPoly,
- int lightPolyLength, const Vector3& lightCenter, const Vector3* poly, int polyLength,
- VertexBuffer& shadowTriangleStrip) {
- // Point clouds for all the shadowed vertices
- Vector2 shadowRegion[lightPolyLength * polyLength];
- // Shadow polygon from one point light.
- Vector2 outline[polyLength];
- Vector2 umbraMem[polyLength * lightPolyLength];
- Vector2* umbra = umbraMem;
-
- int umbraLength = 0;
-
- // Validate input, receiver is always at z = 0 plane.
- bool inputPolyPositionValid = true;
- for (int i = 0; i < polyLength; i++) {
- if (poly[i].z >= lightPoly[0].z) {
- inputPolyPositionValid = false;
- ALOGW("polygon above the light");
- break;
- }
- }
-
- // If the caster's position is invalid, don't draw anything.
- if (!inputPolyPositionValid) {
- return;
- }
-
- // Calculate the umbra polygon based on intersections of all outlines
- int k = 0;
- for (int j = 0; j < lightPolyLength; j++) {
- int m = 0;
- for (int i = 0; i < polyLength; i++) {
- // After validating the input, deltaZ is guaranteed to be positive.
- float deltaZ = lightPoly[j].z - poly[i].z;
- float ratioZ = lightPoly[j].z / deltaZ;
- float x = lightPoly[j].x - ratioZ * (lightPoly[j].x - poly[i].x);
- float y = lightPoly[j].y - ratioZ * (lightPoly[j].y - poly[i].y);
-
- Vector2 newPoint = {x, y};
- shadowRegion[k] = newPoint;
- outline[m] = newPoint;
-
- k++;
- m++;
- }
-
- // For the first light polygon's vertex, use the outline as the umbra.
- // Later on, use the intersection of the outline and existing umbra.
- if (umbraLength == 0) {
- for (int i = 0; i < polyLength; i++) {
- umbra[i] = outline[i];
- }
- umbraLength = polyLength;
- } else {
- int col = ((j * 255) / lightPolyLength);
- umbraLength = intersection(outline, polyLength, umbra, umbraLength);
- if (umbraLength == 0) {
- break;
- }
- }
- }
-
- // Generate the penumbra area using the hull of all shadow regions.
- int shadowRegionLength = k;
- Vector2 penumbra[k];
- int penumbraLength = hull(shadowRegion, shadowRegionLength, penumbra);
-
- Vector2 fakeUmbra[polyLength];
- if (umbraLength < 3) {
- // If there is no real umbra, make a fake one.
- for (int i = 0; i < polyLength; i++) {
- float deltaZ = lightCenter.z - poly[i].z;
- float ratioZ = lightCenter.z / deltaZ;
- float x = lightCenter.x - ratioZ * (lightCenter.x - poly[i].x);
- float y = lightCenter.y - ratioZ * (lightCenter.y - poly[i].y);
-
- fakeUmbra[i].x = x;
- fakeUmbra[i].y = y;
- }
-
- // Shrink the centroid's shadow by 10%.
- // TODO: Study the magic number of 10%.
- Vector2 shadowCentroid =
- ShadowTessellator::centroid2d(fakeUmbra, polyLength);
- for (int i = 0; i < polyLength; i++) {
- fakeUmbra[i] = shadowCentroid * (1.0f - SHADOW_SHRINK_SCALE) +
- fakeUmbra[i] * SHADOW_SHRINK_SCALE;
- }
-#if DEBUG_SHADOW
- ALOGD("No real umbra make a fake one, centroid2d = %f , %f",
- shadowCentroid.x, shadowCentroid.y);
-#endif
- // Set the fake umbra, whose size is the same as the original polygon.
- umbra = fakeUmbra;
- umbraLength = polyLength;
- }
-
- generateTriangleStrip(isCasterOpaque, 1.0, penumbra, penumbraLength, umbra,
- umbraLength, poly, polyLength, shadowTriangleStrip);
-}
-
float SpotShadow::projectCasterToOutline(Vector2& outline,
const Vector3& lightCenter, const Vector3& polyVertex) {
float lightToPolyZ = lightCenter.z - polyVertex.z;
@@ -673,6 +591,12 @@
ALOGW("Relative Light Z is not positive. No spot shadow!");
return;
}
+ if (CC_UNLIKELY(polyLength < 3)) {
+#if DEBUG_SHADOW
+ ALOGW("Invalid polygon length. No spot shadow!");
+#endif
+ return;
+ }
OutlineData outlineData[polyLength];
Vector2 outlineCentroid;
// Calculate the projected outline for each polygon's vertices from the light center.
@@ -713,16 +637,20 @@
projectCasterToOutline(outlineCentroid, lightCenter, polyCentroid);
int penumbraIndex = 0;
- int penumbraLength = polyLength * 3;
- Vector2 penumbra[penumbraLength];
+ // Then each polygon's vertex produce at minmal 2 penumbra vertices.
+ // Since the size can be dynamic here, we keep track of the size and update
+ // the real size at the end.
+ int allocatedPenumbraLength = 2 * polyLength + SPOT_MAX_EXTRA_CORNER_VERTEX_NUMBER;
+ Vector2 penumbra[allocatedPenumbraLength];
+ int totalExtraCornerSliceNumber = 0;
Vector2 umbra[polyLength];
- float distOutline = 0;
- float ratioVI = 0;
+ // When centroid is covered by all circles from outline, then we consider
+ // the umbra is invalid, and we will tune down the shadow strength.
bool hasValidUmbra = true;
- // We need the maxRatioVI to decrease the spot shadow strength accordingly.
- float maxRaitoVI = 1.0;
+ // We need the minimal of RaitoVI to decrease the spot shadow strength accordingly.
+ float minRaitoVI = FLT_MAX;
for (int i = 0; i < polyLength; i++) {
// Generate all the penumbra's vertices only using the (outline vertex + normal * radius)
@@ -748,21 +676,35 @@
// | |
// (V3)-----------------------------------(V2)
int preNormalIndex = (i + polyLength - 1) % polyLength;
- penumbra[penumbraIndex++] = outlineData[i].position +
- outlineData[preNormalIndex].normal * outlineData[i].radius;
- int currentNormalIndex = i;
- // (TODO) Depending on how roundness we want for each corner, we can subdivide
+ const Vector2& previousNormal = outlineData[preNormalIndex].normal;
+ const Vector2& currentNormal = outlineData[i].normal;
+
+ // Depending on how roundness we want for each corner, we can subdivide
// further here and/or introduce some heuristic to decide how much the
// subdivision should be.
- Vector2 avgNormal =
- (outlineData[preNormalIndex].normal + outlineData[currentNormalIndex].normal) / 2;
+ int currentExtraSliceNumber = ShadowTessellator::getExtraVertexNumber(
+ previousNormal, currentNormal, SPOT_CORNER_RADIANS_DIVISOR);
- penumbra[penumbraIndex++] = outlineData[i].position +
- avgNormal * outlineData[i].radius;
+ int currentCornerSliceNumber = 1 + currentExtraSliceNumber;
+ totalExtraCornerSliceNumber += currentExtraSliceNumber;
+#if DEBUG_SHADOW
+ ALOGD("currentExtraSliceNumber should be %d", currentExtraSliceNumber);
+ ALOGD("currentCornerSliceNumber should be %d", currentCornerSliceNumber);
+ ALOGD("totalCornerSliceNumber is %d", totalExtraCornerSliceNumber);
+#endif
+ if (CC_UNLIKELY(totalExtraCornerSliceNumber > SPOT_MAX_EXTRA_CORNER_VERTEX_NUMBER)) {
+ currentCornerSliceNumber = 1;
+ }
+ for (int k = 0; k <= currentCornerSliceNumber; k++) {
+ Vector2 avgNormal =
+ (previousNormal * (currentCornerSliceNumber - k) + currentNormal * k) /
+ currentCornerSliceNumber;
+ avgNormal.normalize();
+ penumbra[penumbraIndex++] = outlineData[i].position +
+ avgNormal * outlineData[i].radius;
+ }
- penumbra[penumbraIndex++] = outlineData[i].position +
- outlineData[currentNormalIndex].normal * outlineData[i].radius;
// Compute the umbra by the intersection from the outline's centroid!
//
@@ -783,53 +725,70 @@
// Now, ratioVI = VI / VC, ratioIC = IC / VC
// Then the intersetion point can be computed as Ixy = Vxy * ratioIC + Cxy * ratioVI;
//
- // When one of the outline circle cover the the outline centroid, (like I is
+ // When all of the outline circles cover the the outline centroid, (like I is
// on the other side of C), there is no real umbra any more, so we just fake
// a small area around the centroid as the umbra, and tune down the spot
// shadow's umbra strength to simulate the effect the whole shadow will
// become lighter in this case.
// The ratio can be simulated by using the inverse of maximum of ratioVI for
// all (V).
- distOutline = (outlineData[i].position - outlineCentroid).length();
+ float distOutline = (outlineData[i].position - outlineCentroid).length();
if (CC_UNLIKELY(distOutline == 0)) {
// If the outline has 0 area, then there is no spot shadow anyway.
ALOGW("Outline has 0 area, no spot shadow!");
return;
}
- ratioVI = outlineData[i].radius / distOutline;
- if (ratioVI >= 1.0) {
- maxRaitoVI = ratioVI;
- hasValidUmbra = false;
+
+ float ratioVI = outlineData[i].radius / distOutline;
+ minRaitoVI = MathUtils::min(minRaitoVI, ratioVI);
+ if (ratioVI >= (1 - FAKE_UMBRA_SIZE_RATIO)) {
+ ratioVI = (1 - FAKE_UMBRA_SIZE_RATIO);
}
// When we know we don't have valid umbra, don't bother to compute the
// values below. But we can't skip the loop yet since we want to know the
// maximum ratio.
- if (hasValidUmbra) {
- float ratioIC = (distOutline - outlineData[i].radius) / distOutline;
- umbra[i] = outlineData[i].position * ratioIC + outlineCentroid * ratioVI;
- }
+ float ratioIC = 1 - ratioVI;
+ umbra[i] = outlineData[i].position * ratioIC + outlineCentroid * ratioVI;
}
+ hasValidUmbra = (minRaitoVI <= 1.0);
float shadowStrengthScale = 1.0;
if (!hasValidUmbra) {
+#if DEBUG_SHADOW
ALOGW("The object is too close to the light or too small, no real umbra!");
+#endif
for (int i = 0; i < polyLength; i++) {
umbra[i] = outlineData[i].position * FAKE_UMBRA_SIZE_RATIO +
- outlineCentroid * (1 - FAKE_UMBRA_SIZE_RATIO);
+ outlineCentroid * (1 - FAKE_UMBRA_SIZE_RATIO);
}
- shadowStrengthScale = 1.0 / maxRaitoVI;
+ shadowStrengthScale = 1.0 / minRaitoVI;
}
+ int penumbraLength = penumbraIndex;
+ int umbraLength = polyLength;
+
#if DEBUG_SHADOW
+ ALOGD("penumbraLength is %d , allocatedPenumbraLength %d", penumbraLength, allocatedPenumbraLength);
dumpPolygon(poly, polyLength, "input poly");
- dumpPolygon(outline, polyLength, "outline");
dumpPolygon(penumbra, penumbraLength, "penumbra");
- dumpPolygon(umbra, polyLength, "umbra");
+ dumpPolygon(umbra, umbraLength, "umbra");
ALOGD("hasValidUmbra is %d and shadowStrengthScale is %f", hasValidUmbra, shadowStrengthScale);
#endif
- generateTriangleStrip(isCasterOpaque, shadowStrengthScale, penumbra,
- penumbraLength, umbra, polyLength, poly, polyLength, shadowTriangleStrip);
+ // The penumbra and umbra needs to be in convex shape to keep consistency
+ // and quality.
+ // Since we are still shooting rays to penumbra, it needs to be convex.
+ // Umbra can be represented as a fan from the centroid, but visually umbra
+ // looks nicer when it is convex.
+ Vector2 finalUmbra[umbraLength];
+ Vector2 finalPenumbra[penumbraLength];
+ int finalUmbraLength = hull(umbra, umbraLength, finalUmbra);
+ int finalPenumbraLength = hull(penumbra, penumbraLength, finalPenumbra);
+
+ generateTriangleStrip(isCasterOpaque, shadowStrengthScale, finalPenumbra,
+ finalPenumbraLength, finalUmbra, finalUmbraLength, poly, polyLength,
+ shadowTriangleStrip, outlineCentroid);
+
}
/**
@@ -891,7 +850,7 @@
lastVertex = &poly[polyIndex];
}
- return true;
+ return true;
}
int SpotShadow::calculateOccludedUmbra(const Vector2* umbra, int umbraLength,
@@ -910,100 +869,6 @@
}
/**
- * Generate a triangle strip given two convex polygons
- *
- * @param penumbra The outer polygon x,y vertexes
- * @param penumbraLength The number of vertexes in the outer polygon
- * @param umbra The inner outer polygon x,y vertexes
- * @param umbraLength The number of vertexes in the inner polygon
- * @param shadowTriangleStrip return an (x,y,alpha) triangle strip representing the shadow. Return
- * empty strip if error.
-**/
-void SpotShadow::generateTriangleStrip(bool isCasterOpaque, float shadowStrengthScale,
- const Vector2* penumbra, int penumbraLength, const Vector2* umbra, int umbraLength,
- const Vector3* poly, int polyLength, VertexBuffer& shadowTriangleStrip) {
- const int rays = SHADOW_RAY_COUNT;
- const int size = 2 * rays;
- const float step = M_PI * 2 / rays;
- // Centroid of the umbra.
- Vector2 centroid = ShadowTessellator::centroid2d(umbra, umbraLength);
-#if DEBUG_SHADOW
- ALOGD("centroid2d = %f , %f", centroid.x, centroid.y);
-#endif
- // Intersection to the penumbra.
- float penumbraDistPerRay[rays];
- // Intersection to the umbra.
- float umbraDistPerRay[rays];
- // Intersection to the occluded umbra area.
- float occludedUmbraDistPerRay[rays];
-
- // convert CW polygons to ray distance encoding, aborting on conversion failure
- if (!convertPolyToRayDist(umbra, umbraLength, centroid, umbraDistPerRay)) return;
- if (!convertPolyToRayDist(penumbra, penumbraLength, centroid, penumbraDistPerRay)) return;
-
- bool hasOccludedUmbraArea = false;
- if (isCasterOpaque) {
- Vector2 occludedUmbra[polyLength + umbraLength];
- int occludedUmbraLength = calculateOccludedUmbra(umbra, umbraLength, poly, polyLength,
- occludedUmbra);
- // Make sure the centroid is inside the umbra, otherwise, fall back to the
- // approach as if there is no occluded umbra area.
- if (testPointInsidePolygon(centroid, occludedUmbra, occludedUmbraLength)) {
- hasOccludedUmbraArea = true;
- // Shrink the occluded umbra area to avoid pixel level artifacts.
- for (int i = 0; i < occludedUmbraLength; i ++) {
- occludedUmbra[i] = centroid + (occludedUmbra[i] - centroid) *
- OCLLUDED_UMBRA_SHRINK_FACTOR;
- }
- if (!convertPolyToRayDist(occludedUmbra, occludedUmbraLength, centroid,
- occludedUmbraDistPerRay)) {
- return;
- }
- }
- }
- AlphaVertex* shadowVertices =
- shadowTriangleStrip.alloc<AlphaVertex>(SHADOW_VERTEX_COUNT);
-
- // NOTE: Shadow alpha values are transformed when stored in alphavertices,
- // so that they can be consumed directly by gFS_Main_ApplyVertexAlphaShadowInterp
- float transformedMaxAlpha = M_PI * shadowStrengthScale;
-
- // Calculate the vertices (x, y, alpha) in the shadow area.
- AlphaVertex centroidXYA;
- AlphaVertex::set(¢roidXYA, centroid.x, centroid.y, transformedMaxAlpha);
- for (int rayIndex = 0; rayIndex < rays; rayIndex++) {
- float dx = cosf(step * rayIndex);
- float dy = sinf(step * rayIndex);
-
- // penumbra ring
- float penumbraDistance = penumbraDistPerRay[rayIndex];
- AlphaVertex::set(&shadowVertices[rayIndex],
- dx * penumbraDistance + centroid.x,
- dy * penumbraDistance + centroid.y, 0.0f);
-
- // umbra ring
- float umbraDistance = umbraDistPerRay[rayIndex];
- AlphaVertex::set(&shadowVertices[rays + rayIndex],
- dx * umbraDistance + centroid.x,
- dy * umbraDistance + centroid.y,
- transformedMaxAlpha);
-
- // occluded umbra ring
- if (hasOccludedUmbraArea) {
- float occludedUmbraDistance = occludedUmbraDistPerRay[rayIndex];
- AlphaVertex::set(&shadowVertices[2 * rays + rayIndex],
- dx * occludedUmbraDistance + centroid.x,
- dy * occludedUmbraDistance + centroid.y, transformedMaxAlpha);
- } else {
- // Put all vertices of the occluded umbra ring at the centroid.
- shadowVertices[2 * rays + rayIndex] = centroidXYA;
- }
- }
- shadowTriangleStrip.setMode(VertexBuffer::kTwoPolyRingShadow);
- shadowTriangleStrip.computeBounds<AlphaVertex>();
-}
-
-/**
* This is only for experimental purpose.
* After intersections are calculated, we could smooth the polygon if needed.
* So far, we don't think it is more appealing yet.
@@ -1024,15 +889,656 @@
}
}
+/**
+ * Generate a array of the angleData for either umbra or penumbra vertices.
+ *
+ * This array will be merged and used to guide where to shoot the rays, in clockwise order.
+ *
+ * @param angleDataList The result array of angle data.
+ *
+ * @return int The maximum angle's index in the array.
+ */
+int SpotShadow::setupAngleList(VertexAngleData* angleDataList,
+ int polyLength, const Vector2* polygon, const Vector2& centroid,
+ bool isPenumbra, const char* name) {
+ float maxAngle = FLT_MIN;
+ int maxAngleIndex = 0;
+ for (int i = 0; i < polyLength; i++) {
+ float currentAngle = angle(polygon[i], centroid);
+ if (currentAngle > maxAngle) {
+ maxAngle = currentAngle;
+ maxAngleIndex = i;
+ }
+ angleDataList[i].set(currentAngle, isPenumbra, i);
+#if DEBUG_SHADOW
+ ALOGD("%s AngleList i %d %f", name, i, currentAngle);
+#endif
+ }
+ return maxAngleIndex;
+}
+
+/**
+ * Make sure the polygons are indeed in clockwise order.
+ *
+ * Possible reasons to return false: 1. The input polygon is not setup properly. 2. The hull
+ * algorithm is not able to generate it properly.
+ *
+ * Anyway, since the algorithm depends on the clockwise, when these kind of unexpected error
+ * situation is found, we need to detect it and early return without corrupting the memory.
+ *
+ * @return bool True if the angle list is actually from big to small.
+ */
+bool SpotShadow::checkClockwise(int indexOfMaxAngle, int listLength, VertexAngleData* angleList,
+ const char* name) {
+ int currentIndex = indexOfMaxAngle;
+#if DEBUG_SHADOW
+ ALOGD("max index %d", currentIndex);
+#endif
+ for (int i = 0; i < listLength - 1; i++) {
+ // TODO: Cache the last angle.
+ float currentAngle = angleList[currentIndex].mAngle;
+ float nextAngle = angleList[(currentIndex + 1) % listLength].mAngle;
+ if (currentAngle < nextAngle) {
+#if DEBUG_SHADOW
+ ALOGE("%s, is not CW, at index %d", name, currentIndex);
+#endif
+ return false;
+ }
+ currentIndex = (currentIndex + 1) % listLength;
+ }
+ return true;
+}
+
+/**
+ * Check the polygon is clockwise.
+ *
+ * @return bool True is the polygon is clockwise.
+ */
+bool SpotShadow::checkPolyClockwise(int polyAngleLength, int maxPolyAngleIndex,
+ const float* polyAngleList) {
+ bool isPolyCW = true;
+ // Starting from maxPolyAngleIndex , check around to make sure angle decrease.
+ for (int i = 0; i < polyAngleLength - 1; i++) {
+ float currentAngle = polyAngleList[(i + maxPolyAngleIndex) % polyAngleLength];
+ float nextAngle = polyAngleList[(i + maxPolyAngleIndex + 1) % polyAngleLength];
+ if (currentAngle < nextAngle) {
+ isPolyCW = false;
+ }
+ }
+ return isPolyCW;
+}
+
+/**
+ * Given the sorted array of all the vertices angle data, calculate for each
+ * vertices, the offset value to array element which represent the start edge
+ * of the polygon we need to shoot the ray at.
+ *
+ * TODO: Calculate this for umbra and penumbra in one loop using one single array.
+ *
+ * @param distances The result of the array distance counter.
+ */
+void SpotShadow::calculateDistanceCounter(bool needsOffsetToUmbra, int angleLength,
+ const VertexAngleData* allVerticesAngleData, int* distances) {
+
+ bool firstVertexIsPenumbra = allVerticesAngleData[0].mIsPenumbra;
+ // If we want distance to inner, then we just set to 0 when we see inner.
+ bool needsSearch = needsOffsetToUmbra ? firstVertexIsPenumbra : !firstVertexIsPenumbra;
+ int distanceCounter = 0;
+ if (needsSearch) {
+ int foundIndex = -1;
+ for (int i = (angleLength - 1); i >= 0; i--) {
+ bool currentIsOuter = allVerticesAngleData[i].mIsPenumbra;
+ // If we need distance to inner, then we need to find a inner vertex.
+ if (currentIsOuter != firstVertexIsPenumbra) {
+ foundIndex = i;
+ break;
+ }
+ }
+ LOG_ALWAYS_FATAL_IF(foundIndex == -1, "Wrong index found, means either"
+ " umbra or penumbra's length is 0");
+ distanceCounter = angleLength - foundIndex;
+ }
+#if DEBUG_SHADOW
+ ALOGD("distances[0] is %d", distanceCounter);
+#endif
+
+ distances[0] = distanceCounter; // means never see a target poly
+
+ for (int i = 1; i < angleLength; i++) {
+ bool firstVertexIsPenumbra = allVerticesAngleData[i].mIsPenumbra;
+ // When we needs for distance for each outer vertex to inner, then we
+ // increase the distance when seeing outer vertices. Otherwise, we clear
+ // to 0.
+ bool needsIncrement = needsOffsetToUmbra ? firstVertexIsPenumbra : !firstVertexIsPenumbra;
+ // If counter is not -1, that means we have seen an other polygon's vertex.
+ if (needsIncrement && distanceCounter != -1) {
+ distanceCounter++;
+ } else {
+ distanceCounter = 0;
+ }
+ distances[i] = distanceCounter;
+ }
+}
+
+/**
+ * Given umbra and penumbra angle data list, merge them by sorting the angle
+ * from the biggest to smallest.
+ *
+ * @param allVerticesAngleData The result array of merged angle data.
+ */
+void SpotShadow::mergeAngleList(int maxUmbraAngleIndex, int maxPenumbraAngleIndex,
+ const VertexAngleData* umbraAngleList, int umbraLength,
+ const VertexAngleData* penumbraAngleList, int penumbraLength,
+ VertexAngleData* allVerticesAngleData) {
+
+ int totalRayNumber = umbraLength + penumbraLength;
+ int umbraIndex = maxUmbraAngleIndex;
+ int penumbraIndex = maxPenumbraAngleIndex;
+
+ float currentUmbraAngle = umbraAngleList[umbraIndex].mAngle;
+ float currentPenumbraAngle = penumbraAngleList[penumbraIndex].mAngle;
+
+ // TODO: Clean this up using a while loop with 2 iterators.
+ for (int i = 0; i < totalRayNumber; i++) {
+ if (currentUmbraAngle > currentPenumbraAngle) {
+ allVerticesAngleData[i] = umbraAngleList[umbraIndex];
+ umbraIndex = (umbraIndex + 1) % umbraLength;
+
+ // If umbraIndex round back, that means we are running out of
+ // umbra vertices to merge, so just copy all the penumbra leftover.
+ // Otherwise, we update the currentUmbraAngle.
+ if (umbraIndex != maxUmbraAngleIndex) {
+ currentUmbraAngle = umbraAngleList[umbraIndex].mAngle;
+ } else {
+ for (int j = i + 1; j < totalRayNumber; j++) {
+ allVerticesAngleData[j] = penumbraAngleList[penumbraIndex];
+ penumbraIndex = (penumbraIndex + 1) % penumbraLength;
+ }
+ break;
+ }
+ } else {
+ allVerticesAngleData[i] = penumbraAngleList[penumbraIndex];
+ penumbraIndex = (penumbraIndex + 1) % penumbraLength;
+ // If penumbraIndex round back, that means we are running out of
+ // penumbra vertices to merge, so just copy all the umbra leftover.
+ // Otherwise, we update the currentPenumbraAngle.
+ if (penumbraIndex != maxPenumbraAngleIndex) {
+ currentPenumbraAngle = penumbraAngleList[penumbraIndex].mAngle;
+ } else {
+ for (int j = i + 1; j < totalRayNumber; j++) {
+ allVerticesAngleData[j] = umbraAngleList[umbraIndex];
+ umbraIndex = (umbraIndex + 1) % umbraLength;
+ }
+ break;
+ }
+ }
+ }
+}
+
+#if DEBUG_SHADOW
+/**
+ * DEBUG ONLY: Verify all the offset compuation is correctly done by examining
+ * each vertex and its neighbor.
+ */
+static void verifyDistanceCounter(const VertexAngleData* allVerticesAngleData,
+ const int* distances, int angleLength, const char* name) {
+ int currentDistance = distances[0];
+ for (int i = 1; i < angleLength; i++) {
+ if (distances[i] != INT_MIN) {
+ if (!((currentDistance + 1) == distances[i]
+ || distances[i] == 0)) {
+ ALOGE("Wrong distance found at i %d name %s", i, name);
+ }
+ currentDistance = distances[i];
+ if (currentDistance != 0) {
+ bool currentOuter = allVerticesAngleData[i].mIsPenumbra;
+ for (int j = 1; j <= (currentDistance - 1); j++) {
+ bool neigborOuter =
+ allVerticesAngleData[(i + angleLength - j) % angleLength].mIsPenumbra;
+ if (neigborOuter != currentOuter) {
+ ALOGE("Wrong distance found at i %d name %s", i, name);
+ }
+ }
+ bool oppositeOuter =
+ allVerticesAngleData[(i + angleLength - currentDistance) % angleLength].mIsPenumbra;
+ if (oppositeOuter == currentOuter) {
+ ALOGE("Wrong distance found at i %d name %s", i, name);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * DEBUG ONLY: Verify all the angle data compuated are is correctly done
+ */
+static void verifyAngleData(int totalRayNumber, const VertexAngleData* allVerticesAngleData,
+ const int* distancesToInner, const int* distancesToOuter,
+ const VertexAngleData* umbraAngleList, int maxUmbraAngleIndex, int umbraLength,
+ const VertexAngleData* penumbraAngleList, int maxPenumbraAngleIndex,
+ int penumbraLength) {
+ for (int i = 0; i < totalRayNumber; i++) {
+ ALOGD("currentAngleList i %d, angle %f, isInner %d, index %d distancesToInner"
+ " %d distancesToOuter %d", i, allVerticesAngleData[i].mAngle,
+ !allVerticesAngleData[i].mIsPenumbra,
+ allVerticesAngleData[i].mVertexIndex, distancesToInner[i], distancesToOuter[i]);
+ }
+
+ verifyDistanceCounter(allVerticesAngleData, distancesToInner, totalRayNumber, "distancesToInner");
+ verifyDistanceCounter(allVerticesAngleData, distancesToOuter, totalRayNumber, "distancesToOuter");
+
+ for (int i = 0; i < totalRayNumber; i++) {
+ if ((distancesToInner[i] * distancesToOuter[i]) != 0) {
+ ALOGE("distancesToInner wrong at index %d distancesToInner[i] %d,"
+ " distancesToOuter[i] %d", i, distancesToInner[i], distancesToOuter[i]);
+ }
+ }
+ int currentUmbraVertexIndex =
+ umbraAngleList[maxUmbraAngleIndex].mVertexIndex;
+ int currentPenumbraVertexIndex =
+ penumbraAngleList[maxPenumbraAngleIndex].mVertexIndex;
+ for (int i = 0; i < totalRayNumber; i++) {
+ if (allVerticesAngleData[i].mIsPenumbra == true) {
+ if (allVerticesAngleData[i].mVertexIndex != currentPenumbraVertexIndex) {
+ ALOGW("wrong penumbra indexing i %d allVerticesAngleData[i].mVertexIndex %d "
+ "currentpenumbraVertexIndex %d", i,
+ allVerticesAngleData[i].mVertexIndex, currentPenumbraVertexIndex);
+ }
+ currentPenumbraVertexIndex = (currentPenumbraVertexIndex + 1) % penumbraLength;
+ } else {
+ if (allVerticesAngleData[i].mVertexIndex != currentUmbraVertexIndex) {
+ ALOGW("wrong umbra indexing i %d allVerticesAngleData[i].mVertexIndex %d "
+ "currentUmbraVertexIndex %d", i,
+ allVerticesAngleData[i].mVertexIndex, currentUmbraVertexIndex);
+ }
+ currentUmbraVertexIndex = (currentUmbraVertexIndex + 1) % umbraLength;
+ }
+ }
+ for (int i = 0; i < totalRayNumber - 1; i++) {
+ float currentAngle = allVerticesAngleData[i].mAngle;
+ float nextAngle = allVerticesAngleData[(i + 1) % totalRayNumber].mAngle;
+ if (currentAngle < nextAngle) {
+ ALOGE("Unexpected angle values!, currentAngle nextAngle %f %f", currentAngle, nextAngle);
+ }
+ }
+}
+#endif
+
+/**
+ * In order to compute the occluded umbra, we need to setup the angle data list
+ * for the polygon data. Since we only store one poly vertex per polygon vertex,
+ * this array only needs to be a float array which are the angles for each vertex.
+ *
+ * @param polyAngleList The result list
+ *
+ * @return int The index for the maximum angle in this array.
+ */
+int SpotShadow::setupPolyAngleList(float* polyAngleList, int polyAngleLength,
+ const Vector2* poly2d, const Vector2& centroid) {
+ int maxPolyAngleIndex = -1;
+ float maxPolyAngle = -FLT_MAX;
+ for (int i = 0; i < polyAngleLength; i++) {
+ polyAngleList[i] = angle(poly2d[i], centroid);
+ if (polyAngleList[i] > maxPolyAngle) {
+ maxPolyAngle = polyAngleList[i];
+ maxPolyAngleIndex = i;
+ }
+ }
+ return maxPolyAngleIndex;
+}
+
+/**
+ * For umbra and penumbra, given the offset info and the current ray number,
+ * find the right edge index (the (starting vertex) for the ray to shoot at.
+ *
+ * @return int The index of the starting vertex of the edge.
+ */
+inline int SpotShadow::getEdgeStartIndex(const int* offsets, int rayIndex, int totalRayNumber,
+ const VertexAngleData* allVerticesAngleData) {
+ int tempOffset = offsets[rayIndex];
+ int targetRayIndex = (rayIndex - tempOffset + totalRayNumber) % totalRayNumber;
+ return allVerticesAngleData[targetRayIndex].mVertexIndex;
+}
+
+/**
+ * For the occluded umbra, given the array of angles, find the index of the
+ * starting vertex of the edge, for the ray to shoo at.
+ *
+ * TODO: Save the last result to shorten the search distance.
+ *
+ * @return int The index of the starting vertex of the edge.
+ */
+inline int SpotShadow::getPolyEdgeStartIndex(int maxPolyAngleIndex, int polyLength,
+ const float* polyAngleList, float rayAngle) {
+ int minPolyAngleIndex = (maxPolyAngleIndex + polyLength - 1) % polyLength;
+ int resultIndex = -1;
+ if (rayAngle > polyAngleList[maxPolyAngleIndex]
+ || rayAngle <= polyAngleList[minPolyAngleIndex]) {
+ resultIndex = minPolyAngleIndex;
+ } else {
+ for (int i = 0; i < polyLength - 1; i++) {
+ int currentIndex = (maxPolyAngleIndex + i) % polyLength;
+ int nextIndex = (maxPolyAngleIndex + i + 1) % polyLength;
+ if (rayAngle <= polyAngleList[currentIndex]
+ && rayAngle > polyAngleList[nextIndex]) {
+ resultIndex = currentIndex;
+ }
+ }
+ }
+ if (CC_UNLIKELY(resultIndex == -1)) {
+ // TODO: Add more error handling here.
+ ALOGE("Wrong index found, means no edge can't be found for rayAngle %f", rayAngle);
+ }
+ return resultIndex;
+}
+
+/**
+ * Convert the incoming polygons into arrays of vertices, for each ray.
+ * Ray only shoots when there is one vertex either on penumbra on umbra.
+ *
+ * Finally, it will generate vertices per ray for umbra, penumbra and optionally
+ * occludedUmbra.
+ *
+ * Return true (success) when all vertices are generated
+ */
+int SpotShadow::convertPolysToVerticesPerRay(
+ bool hasOccludedUmbraArea, const Vector2* poly2d, int polyLength,
+ const Vector2* umbra, int umbraLength, const Vector2* penumbra,
+ int penumbraLength, const Vector2& centroid,
+ Vector2* umbraVerticesPerRay, Vector2* penumbraVerticesPerRay,
+ Vector2* occludedUmbraVerticesPerRay) {
+ int totalRayNumber = umbraLength + penumbraLength;
+
+ // For incoming umbra / penumbra polygons, we will build an intermediate data
+ // structure to help us sort all the vertices according to the vertices.
+ // Using this data structure, we can tell where (the angle) to shoot the ray,
+ // whether we shoot at penumbra edge or umbra edge, and which edge to shoot at.
+ //
+ // We first parse each vertices and generate a table of VertexAngleData.
+ // Based on that, we create 2 arrays telling us which edge to shoot at.
+ VertexAngleData allVerticesAngleData[totalRayNumber];
+ VertexAngleData umbraAngleList[umbraLength];
+ VertexAngleData penumbraAngleList[penumbraLength];
+
+ int polyAngleLength = hasOccludedUmbraArea ? polyLength : 0;
+ float polyAngleList[polyAngleLength];
+
+ const int maxUmbraAngleIndex =
+ setupAngleList(umbraAngleList, umbraLength, umbra, centroid, false, "umbra");
+ const int maxPenumbraAngleIndex =
+ setupAngleList(penumbraAngleList, penumbraLength, penumbra, centroid, true, "penumbra");
+ const int maxPolyAngleIndex = setupPolyAngleList(polyAngleList, polyAngleLength, poly2d, centroid);
+
+ // Check all the polygons here are CW.
+ bool isPolyCW = checkPolyClockwise(polyAngleLength, maxPolyAngleIndex, polyAngleList);
+ bool isUmbraCW = checkClockwise(maxUmbraAngleIndex, umbraLength,
+ umbraAngleList, "umbra");
+ bool isPenumbraCW = checkClockwise(maxPenumbraAngleIndex, penumbraLength,
+ penumbraAngleList, "penumbra");
+
+ if (!isUmbraCW || !isPenumbraCW || !isPolyCW) {
+#if DEBUG_SHADOW
+ ALOGE("One polygon is not CW isUmbraCW %d isPenumbraCW %d isPolyCW %d",
+ isUmbraCW, isPenumbraCW, isPolyCW);
+#endif
+ return false;
+ }
+
+ mergeAngleList(maxUmbraAngleIndex, maxPenumbraAngleIndex,
+ umbraAngleList, umbraLength, penumbraAngleList, penumbraLength,
+ allVerticesAngleData);
+
+ // Calculate the offset to the left most Inner vertex for each outerVertex.
+ // Then the offset to the left most Outer vertex for each innerVertex.
+ int offsetToInner[totalRayNumber];
+ int offsetToOuter[totalRayNumber];
+ calculateDistanceCounter(true, totalRayNumber, allVerticesAngleData, offsetToInner);
+ calculateDistanceCounter(false, totalRayNumber, allVerticesAngleData, offsetToOuter);
+
+ // Generate both umbraVerticesPerRay and penumbraVerticesPerRay
+ for (int i = 0; i < totalRayNumber; i++) {
+ float rayAngle = allVerticesAngleData[i].mAngle;
+ bool isUmbraVertex = !allVerticesAngleData[i].mIsPenumbra;
+
+ float dx = cosf(rayAngle);
+ float dy = sinf(rayAngle);
+ float distanceToIntersectUmbra = -1;
+
+ if (isUmbraVertex) {
+ // We can just copy umbra easily, and calculate the distance for the
+ // occluded umbra computation.
+ int startUmbraIndex = allVerticesAngleData[i].mVertexIndex;
+ umbraVerticesPerRay[i] = umbra[startUmbraIndex];
+ if (hasOccludedUmbraArea) {
+ distanceToIntersectUmbra = (umbraVerticesPerRay[i] - centroid).length();
+ }
+
+ //shoot ray to penumbra only
+ int startPenumbraIndex = getEdgeStartIndex(offsetToOuter, i, totalRayNumber,
+ allVerticesAngleData);
+ float distanceToIntersectPenumbra = rayIntersectPoints(centroid, dx, dy,
+ penumbra[startPenumbraIndex],
+ penumbra[(startPenumbraIndex + 1) % penumbraLength]);
+ if (distanceToIntersectPenumbra < 0) {
+#if DEBUG_SHADOW
+ ALOGW("convertPolyToRayDist for penumbra failed rayAngle %f dx %f dy %f",
+ rayAngle, dx, dy);
+#endif
+ distanceToIntersectPenumbra = 0;
+ }
+ penumbraVerticesPerRay[i].x = centroid.x + dx * distanceToIntersectPenumbra;
+ penumbraVerticesPerRay[i].y = centroid.y + dy * distanceToIntersectPenumbra;
+ } else {
+ // We can just copy the penumbra
+ int startPenumbraIndex = allVerticesAngleData[i].mVertexIndex;
+ penumbraVerticesPerRay[i] = penumbra[startPenumbraIndex];
+
+ // And shoot ray to umbra only
+ int startUmbraIndex = getEdgeStartIndex(offsetToInner, i, totalRayNumber,
+ allVerticesAngleData);
+
+ distanceToIntersectUmbra = rayIntersectPoints(centroid, dx, dy,
+ umbra[startUmbraIndex], umbra[(startUmbraIndex + 1) % umbraLength]);
+ if (distanceToIntersectUmbra < 0) {
+#if DEBUG_SHADOW
+ ALOGW("convertPolyToRayDist for umbra failed rayAngle %f dx %f dy %f",
+ rayAngle, dx, dy);
+#endif
+ distanceToIntersectUmbra = 0;
+ }
+ umbraVerticesPerRay[i].x = centroid.x + dx * distanceToIntersectUmbra;
+ umbraVerticesPerRay[i].y = centroid.y + dy * distanceToIntersectUmbra;
+ }
+
+ if (hasOccludedUmbraArea) {
+ // Shoot the same ray to the poly2d, and get the distance.
+ int startPolyIndex = getPolyEdgeStartIndex(maxPolyAngleIndex, polyLength,
+ polyAngleList, rayAngle);
+
+ float distanceToIntersectPoly = rayIntersectPoints(centroid, dx, dy,
+ poly2d[startPolyIndex], poly2d[(startPolyIndex + 1) % polyLength]);
+ if (distanceToIntersectPoly < 0) {
+ distanceToIntersectPoly = 0;
+ }
+ distanceToIntersectPoly = MathUtils::min(distanceToIntersectUmbra, distanceToIntersectPoly);
+ occludedUmbraVerticesPerRay[i].x = centroid.x + dx * distanceToIntersectPoly;
+ occludedUmbraVerticesPerRay[i].y = centroid.y + dy * distanceToIntersectPoly;
+ }
+ }
+
+#if DEBUG_SHADOW
+ verifyAngleData(totalRayNumber, allVerticesAngleData, offsetToInner,
+ offsetToOuter, umbraAngleList, maxUmbraAngleIndex, umbraLength,
+ penumbraAngleList, maxPenumbraAngleIndex, penumbraLength);
+#endif
+ return true; // success
+
+}
+
+/**
+ * Generate a triangle strip given two convex polygon
+**/
+void SpotShadow::generateTriangleStrip(bool isCasterOpaque, float shadowStrengthScale,
+ Vector2* penumbra, int penumbraLength, Vector2* umbra, int umbraLength,
+ const Vector3* poly, int polyLength, VertexBuffer& shadowTriangleStrip,
+ const Vector2& centroid) {
+
+ bool hasOccludedUmbraArea = false;
+ Vector2 poly2d[polyLength];
+
+ if (isCasterOpaque) {
+ for (int i = 0; i < polyLength; i++) {
+ poly2d[i].x = poly[i].x;
+ poly2d[i].y = poly[i].y;
+ }
+ // Make sure the centroid is inside the umbra, otherwise, fall back to the
+ // approach as if there is no occluded umbra area.
+ if (testPointInsidePolygon(centroid, poly2d, polyLength)) {
+ hasOccludedUmbraArea = true;
+ }
+ }
+
+ int totalRayNum = umbraLength + penumbraLength;
+ Vector2 umbraVertices[totalRayNum];
+ Vector2 penumbraVertices[totalRayNum];
+ Vector2 occludedUmbraVertices[totalRayNum];
+ bool convertSuccess = convertPolysToVerticesPerRay(hasOccludedUmbraArea, poly2d,
+ polyLength, umbra, umbraLength, penumbra, penumbraLength,
+ centroid, umbraVertices, penumbraVertices, occludedUmbraVertices);
+ if (!convertSuccess) {
+ return;
+ }
+
+ // Minimal value is 1, for each vertex show up once.
+ // The bigger this value is , the smoother the look is, but more memory
+ // is consumed.
+ // When the ray number is high, that means the polygon has been fine
+ // tessellated, we don't need this extra slice, just keep it as 1.
+ int sliceNumberPerEdge = (totalRayNum > FINE_TESSELLATED_POLYGON_RAY_NUMBER) ? 1 : 2;
+
+ // For each polygon, we at most add (totalRayNum * sliceNumberPerEdge) vertices.
+ int slicedVertexCountPerPolygon = totalRayNum * sliceNumberPerEdge;
+ int totalVertexCount = slicedVertexCountPerPolygon * 2 + totalRayNum;
+ int totalIndexCount = 2 * (slicedVertexCountPerPolygon * 2 + 2);
+ AlphaVertex* shadowVertices =
+ shadowTriangleStrip.alloc<AlphaVertex>(totalVertexCount);
+ uint16_t* indexBuffer =
+ shadowTriangleStrip.allocIndices<uint16_t>(totalIndexCount);
+
+ int indexBufferIndex = 0;
+ int vertexBufferIndex = 0;
+
+ uint16_t slicedUmbraVertexIndex[totalRayNum * sliceNumberPerEdge];
+ // Should be something like 0 0 0 1 1 1 2 3 3 3...
+ int rayNumberPerSlicedUmbra[totalRayNum * sliceNumberPerEdge];
+ int realUmbraVertexCount = 0;
+ for (int i = 0; i < totalRayNum; i++) {
+ Vector2 currentPenumbra = penumbraVertices[i];
+ Vector2 currentUmbra = umbraVertices[i];
+
+ Vector2 nextPenumbra = penumbraVertices[(i + 1) % totalRayNum];
+ Vector2 nextUmbra = umbraVertices[(i + 1) % totalRayNum];
+ // NextUmbra/Penumbra will be done in the next loop!!
+ for (int weight = 0; weight < sliceNumberPerEdge; weight++) {
+ const Vector2& slicedPenumbra = (currentPenumbra * (sliceNumberPerEdge - weight)
+ + nextPenumbra * weight) / sliceNumberPerEdge;
+
+ const Vector2& slicedUmbra = (currentUmbra * (sliceNumberPerEdge - weight)
+ + nextUmbra * weight) / sliceNumberPerEdge;
+
+ // In the vertex buffer, we fill the Penumbra first, then umbra.
+ indexBuffer[indexBufferIndex++] = vertexBufferIndex;
+ AlphaVertex::set(&shadowVertices[vertexBufferIndex++], slicedPenumbra.x,
+ slicedPenumbra.y, 0.0f);
+
+ // When we add umbra vertex, we need to remember its current ray number.
+ // And its own vertexBufferIndex. This is for occluded umbra usage.
+ indexBuffer[indexBufferIndex++] = vertexBufferIndex;
+ rayNumberPerSlicedUmbra[realUmbraVertexCount] = i;
+ slicedUmbraVertexIndex[realUmbraVertexCount] = vertexBufferIndex;
+ realUmbraVertexCount++;
+ AlphaVertex::set(&shadowVertices[vertexBufferIndex++], slicedUmbra.x,
+ slicedUmbra.y, M_PI);
+ }
+ }
+
+ indexBuffer[indexBufferIndex++] = 0;
+ //RealUmbraVertexIndex[0] must be 1, so we connect back well at the
+ //beginning of occluded area.
+ indexBuffer[indexBufferIndex++] = 1;
+
+ float occludedUmbraAlpha = M_PI;
+ if (hasOccludedUmbraArea) {
+ // Now the occludedUmbra area;
+ int currentRayNumber = -1;
+ int firstOccludedUmbraIndex = -1;
+ for (int i = 0; i < realUmbraVertexCount; i++) {
+ indexBuffer[indexBufferIndex++] = slicedUmbraVertexIndex[i];
+
+ // If the occludedUmbra vertex has not been added yet, then add it.
+ // Otherwise, just use the previously added occludedUmbra vertices.
+ if (rayNumberPerSlicedUmbra[i] != currentRayNumber) {
+ currentRayNumber++;
+ indexBuffer[indexBufferIndex++] = vertexBufferIndex;
+ // We need to remember the begining of the occludedUmbra vertices
+ // to close this loop.
+ if (currentRayNumber == 0) {
+ firstOccludedUmbraIndex = vertexBufferIndex;
+ }
+ AlphaVertex::set(&shadowVertices[vertexBufferIndex++],
+ occludedUmbraVertices[currentRayNumber].x,
+ occludedUmbraVertices[currentRayNumber].y,
+ occludedUmbraAlpha);
+ } else {
+ indexBuffer[indexBufferIndex++] = (vertexBufferIndex - 1);
+ }
+ }
+ // Close the loop here!
+ indexBuffer[indexBufferIndex++] = slicedUmbraVertexIndex[0];
+ indexBuffer[indexBufferIndex++] = firstOccludedUmbraIndex;
+ } else {
+ int lastCentroidIndex = vertexBufferIndex;
+ AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid.x,
+ centroid.y, occludedUmbraAlpha);
+ for (int i = 0; i < realUmbraVertexCount; i++) {
+ indexBuffer[indexBufferIndex++] = slicedUmbraVertexIndex[i];
+ indexBuffer[indexBufferIndex++] = lastCentroidIndex;
+ }
+ // Close the loop here!
+ indexBuffer[indexBufferIndex++] = slicedUmbraVertexIndex[0];
+ indexBuffer[indexBufferIndex++] = lastCentroidIndex;
+ }
+
+#if DEBUG_SHADOW
+ ALOGD("allocated IB %d allocated VB is %d", totalIndexCount, totalVertexCount);
+ ALOGD("IB index %d VB index is %d", indexBufferIndex, vertexBufferIndex);
+ for (int i = 0; i < vertexBufferIndex; i++) {
+ ALOGD("vertexBuffer i %d, (%f, %f %f)", i, shadowVertices[i].x, shadowVertices[i].y,
+ shadowVertices[i].alpha);
+ }
+ for (int i = 0; i < indexBufferIndex; i++) {
+ ALOGD("indexBuffer i %d, indexBuffer[i] %d", i, indexBuffer[i]);
+ }
+#endif
+
+ // At the end, update the real index and vertex buffer size.
+ shadowTriangleStrip.updateVertexCount(vertexBufferIndex);
+ shadowTriangleStrip.updateIndexCount(indexBufferIndex);
+ ShadowTessellator::checkOverflow(vertexBufferIndex, totalVertexCount, "Spot Vertex Buffer");
+ ShadowTessellator::checkOverflow(indexBufferIndex, totalIndexCount, "Spot Index Buffer");
+
+ shadowTriangleStrip.setMode(VertexBuffer::kIndices);
+ shadowTriangleStrip.computeBounds<AlphaVertex>();
+}
+
#if DEBUG_SHADOW
#define TEST_POINT_NUMBER 128
-
/**
* Calculate the bounds for generating random test points.
*/
void SpotShadow::updateBound(const Vector2 inVector, Vector2& lowerBound,
- Vector2& upperBound ) {
+ Vector2& upperBound) {
if (inVector.x < lowerBound.x) {
lowerBound.x = inVector.x;
}
@@ -1127,14 +1633,14 @@
if (!testPointInsidePolygon(testPoint, poly1, poly1Length)) {
dumpPoly = true;
ALOGW("(Error Type 1): one point (%f, %f) in the intersection is"
- " not in the poly1",
+ " not in the poly1",
testPoint.x, testPoint.y);
}
if (!testPointInsidePolygon(testPoint, poly2, poly2Length)) {
dumpPoly = true;
ALOGW("(Error Type 1): one point (%f, %f) in the intersection is"
- " not in the poly2",
+ " not in the poly2",
testPoint.x, testPoint.y);
}
}
diff --git a/libs/hwui/SpotShadow.h b/libs/hwui/SpotShadow.h
index 355be8d..23fdca9 100644
--- a/libs/hwui/SpotShadow.h
+++ b/libs/hwui/SpotShadow.h
@@ -26,22 +26,51 @@
class SpotShadow {
public:
- static void createSpotShadow_old(bool isCasterOpaque, const Vector3* poly,
- int polyLength, const Vector3& lightCenter, float lightSize,
- int lightVertexCount, VertexBuffer& retStrips);
static void createSpotShadow(bool isCasterOpaque, const Vector3& lightCenter,
float lightSize, const Vector3* poly, int polyLength,
const Vector3& polyCentroid, VertexBuffer& retstrips);
private:
+ struct VertexAngleData;
+
static float projectCasterToOutline(Vector2& outline,
const Vector3& lightCenter, const Vector3& polyVertex);
static int calculateOccludedUmbra(const Vector2* umbra, int umbraLength,
const Vector3* poly, int polyLength, Vector2* occludedUmbra);
- static void computeSpotShadow_old(bool isCasterOpaque, const Vector3* lightPoly,
- int lightPolyLength, const Vector3& lightCenter, const Vector3* poly,
- int polyLength, VertexBuffer& shadowTriangleStrip);
+ static int setupAngleList(VertexAngleData* angleDataList,
+ int polyLength, const Vector2* polygon, const Vector2& centroid,
+ bool isPenumbra, const char* name);
+
+ static int convertPolysToVerticesPerRay(
+ bool hasOccludedUmbraArea, const Vector2* poly2d, int polyLength,
+ const Vector2* umbra, int umbraLength, const Vector2* penumbra,
+ int penumbraLength, const Vector2& centroid,
+ Vector2* umbraVerticesPerRay, Vector2* penumbraVerticesPerRay,
+ Vector2* occludedUmbraVerticesPerRay);
+
+ static bool checkClockwise(int maxIndex, int listLength,
+ VertexAngleData* angleList, const char* name);
+
+ static void calculateDistanceCounter(bool needsOffsetToUmbra, int angleLength,
+ const VertexAngleData* allVerticesAngleData, int* distances);
+
+ static void mergeAngleList(int maxUmbraAngleIndex, int maxPenumbraAngleIndex,
+ const VertexAngleData* umbraAngleList, int umbraLength,
+ const VertexAngleData* penumbraAngleList, int penumbraLength,
+ VertexAngleData* allVerticesAngleData);
+
+ static int setupPolyAngleList(float* polyAngleList, int polyAngleLength,
+ const Vector2* poly2d, const Vector2& centroid);
+
+ static bool checkPolyClockwise(int polyAngleLength, int maxPolyAngleIndex,
+ const float* polyAngleList);
+
+ static int getEdgeStartIndex(const int* offsets, int rayIndex, int totalRayNumber,
+ const VertexAngleData* allVerticesAngleData);
+
+ static int getPolyEdgeStartIndex(int maxPolyAngleIndex, int polyLength,
+ const float* polyAngleList, float rayAngle);
static void computeLightPolygon(int points, const Vector3& lightCenter,
float size, Vector3* ret);
@@ -67,11 +96,10 @@
double x3, double y3, double x4, double y4, Vector2& ret);
static void generateTriangleStrip(bool isCasterOpaque, float shadowStrengthScale,
- const Vector2* penumbra, int penumbraLength, const Vector2* umbra, int umbraLength,
- const Vector3* poly, int polyLength, VertexBuffer& retstrips);
+ Vector2* penumbra, int penumbraLength, Vector2* umbra, int umbraLength,
+ const Vector3* poly, int polyLength, VertexBuffer& retstrips, const Vector2& centroid);
#if DEBUG_SHADOW
- // Verification utility function.
static bool testConvex(const Vector2* polygon, int polygonLength,
const char* name);
static void testIntersection(const Vector2* poly1, int poly1Length,
diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
index 9e62f36..1e38f9e 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -216,7 +216,7 @@
// tessellate caster outline into a 2d polygon
Vector<Vertex> casterVertices2d;
- const float casterRefinementThresholdSquared = 20.0f; // TODO: experiment with this value
+ const float casterRefinementThresholdSquared = 4.0f;
PathTessellator::approximatePathOutlineVertices(*casterPerimeter,
casterRefinementThresholdSquared, casterVertices2d);
if (!ShadowTessellator::isClockwisePath(*casterPerimeter)) {
diff --git a/libs/hwui/VertexBuffer.h b/libs/hwui/VertexBuffer.h
index 966fa4e..8c3a272 100644
--- a/libs/hwui/VertexBuffer.h
+++ b/libs/hwui/VertexBuffer.h
@@ -133,7 +133,7 @@
mIndexCount = MathUtils::min(newCount, mAllocatedIndexCount);
}
void updateVertexCount(unsigned int newCount) {
- newCount = MathUtils::min(newCount, mAllocatedVertexCount);
+ mVertexCount = MathUtils::min(newCount, mAllocatedVertexCount);
}
Mode getMode() const { return mMode; }
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 082a158..2c805bb 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1109,9 +1109,9 @@
* {@link #requestLocationUpdates(String, long, float, LocationListener)}.
*
* <p>
- * Before API version 20, this method would throw {@link SecurityException}
- * if the location permissions were not sufficient to use the specified
- * provider.
+ * Before API version {@link android.os.Build.VERSION_CODES#L}, this
+ * method would throw {@link SecurityException} if the location permissions
+ * were not sufficient to use the specified provider.
*
* @param provider the name of the provider
* @return true if the provider exists and is enabled
@@ -1119,7 +1119,6 @@
* @throws IllegalArgumentException if provider is null
*/
public boolean isProviderEnabled(String provider) {
- // STOPSHIP: finalize API version number in javadoc
checkProvider(provider);
try {
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 5a286ee..e0901d0 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -21,15 +21,24 @@
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.location.LocationManager;
+import android.location.INetInitiatedListener;
+import android.telephony.TelephonyManager;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.PhoneStateListener;
import android.os.Bundle;
+import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.SystemProperties;
import android.util.Log;
import com.android.internal.R;
import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.TelephonyProperties;
/**
* A GPS Network-initiated Handler class used by LocationManager.
@@ -45,55 +54,67 @@
// NI verify activity for bringing up UI (not used yet)
public static final String ACTION_NI_VERIFY = "android.intent.action.NETWORK_INITIATED_VERIFY";
-
+
// string constants for defining data fields in NI Intent
public static final String NI_INTENT_KEY_NOTIF_ID = "notif_id";
public static final String NI_INTENT_KEY_TITLE = "title";
public static final String NI_INTENT_KEY_MESSAGE = "message";
public static final String NI_INTENT_KEY_TIMEOUT = "timeout";
public static final String NI_INTENT_KEY_DEFAULT_RESPONSE = "default_resp";
-
+
// the extra command to send NI response to GpsLocationProvider
public static final String NI_RESPONSE_EXTRA_CMD = "send_ni_response";
-
+
// the extra command parameter names in the Bundle
public static final String NI_EXTRA_CMD_NOTIF_ID = "notif_id";
public static final String NI_EXTRA_CMD_RESPONSE = "response";
-
+
// these need to match GpsNiType constants in gps_ni.h
public static final int GPS_NI_TYPE_VOICE = 1;
public static final int GPS_NI_TYPE_UMTS_SUPL = 2;
public static final int GPS_NI_TYPE_UMTS_CTRL_PLANE = 3;
-
- // these need to match GpsUserResponseType constants in gps_ni.h
+ public static final int GPS_NI_TYPE_EMERGENCY_SUPL = 4;
+
+ // these need to match GpsUserResponseType constants in gps_ni.h
public static final int GPS_NI_RESPONSE_ACCEPT = 1;
public static final int GPS_NI_RESPONSE_DENY = 2;
- public static final int GPS_NI_RESPONSE_NORESP = 3;
-
+ public static final int GPS_NI_RESPONSE_NORESP = 3;
+ public static final int GPS_NI_RESPONSE_IGNORE = 4;
+
// these need to match GpsNiNotifyFlags constants in gps_ni.h
public static final int GPS_NI_NEED_NOTIFY = 0x0001;
public static final int GPS_NI_NEED_VERIFY = 0x0002;
public static final int GPS_NI_PRIVACY_OVERRIDE = 0x0004;
-
+
// these need to match GpsNiEncodingType in gps_ni.h
public static final int GPS_ENC_NONE = 0;
public static final int GPS_ENC_SUPL_GSM_DEFAULT = 1;
public static final int GPS_ENC_SUPL_UTF8 = 2;
public static final int GPS_ENC_SUPL_UCS2 = 3;
public static final int GPS_ENC_UNKNOWN = -1;
-
+
private final Context mContext;
-
+ private final TelephonyManager mTelephonyManager;
+ private final PhoneStateListener mPhoneStateListener;
+
// parent gps location provider
private final LocationManager mLocationManager;
-
+
// configuration of notificaiton behavior
private boolean mPlaySounds = false;
private boolean mPopupImmediately = true;
-
- // Set to true if string from HAL is encoded as Hex, e.g., "3F0039"
+
+ // read the SUPL_ES form gps.conf
+ private volatile boolean mIsSuplEsEnabled;
+
+ // Set to true if the phone is having emergency call.
+ private volatile boolean mIsInEmergency;
+
+ private final INetInitiatedListener mNetInitiatedListener;
+
+ // Set to true if string from HAL is encoded as Hex, e.g., "3F0039"
static private boolean mIsHexInput = true;
-
+
public static class GpsNiNotification
{
public int notificationId;
@@ -109,58 +130,95 @@
public int textEncoding;
public Bundle extras;
};
-
+
public static class GpsNiResponse {
/* User reponse, one of the values in GpsUserResponseType */
int userResponse;
/* Optional extra data to pass with the user response */
Bundle extras;
};
-
+
+ private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
+
+ @Override public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
+ String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
+ /*
+ Emergency Mode is when during emergency call or in emergency call back mode.
+ For checking if it is during emergency call:
+ mIsInEmergency records if the phone is in emergency call or not. It will
+ be set to true when the phone is having emergency call, and then will
+ be set to false by mPhoneStateListener when the emergency call ends.
+ For checking if it is in emergency call back mode:
+ Emergency call back mode will be checked by reading system properties
+ when necessary: SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)
+ */
+ mIsInEmergency |= PhoneNumberUtils.isEmergencyNumber(phoneNumber);
+ if (DEBUG) Log.v(TAG, "ACTION_NEW_OUTGOING_CALL - " + mIsInEmergency);
+ }
+ }
+ };
+
/**
* The notification that is shown when a network-initiated notification
- * (and verification) event is received.
+ * (and verification) event is received.
* <p>
* This is lazily created, so use {@link #setNINotification()}.
*/
private Notification mNiNotification;
-
- public GpsNetInitiatedHandler(Context context) {
+
+ public GpsNetInitiatedHandler(Context context,
+ INetInitiatedListener netInitiatedListener,
+ boolean isSuplEsEnabled) {
mContext = context;
+
+ if (netInitiatedListener == null) {
+ throw new IllegalArgumentException("netInitiatedListener is null");
+ } else {
+ mNetInitiatedListener = netInitiatedListener;
+ }
+
+ mIsSuplEsEnabled = isSuplEsEnabled;
mLocationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
+ mTelephonyManager =
+ (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
+
+ mPhoneStateListener = new PhoneStateListener() {
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ if (DEBUG) Log.d(TAG, "onCallStateChanged(): state is "+ state);
+ // listening for emergency call ends
+ if (state == TelephonyManager.CALL_STATE_IDLE) {
+ mIsInEmergency = false;
+ }
+ }
+ };
+ mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_NEW_OUTGOING_CALL);
+ mContext.registerReceiver(mBroadcastReciever, intentFilter);
}
-
+
+ public void setSuplEsEnablement(boolean isEnabled)
+ {
+ mIsSuplEsEnabled = isEnabled;
+ }
+
// Handles NI events from HAL
public void handleNiNotification(GpsNiNotification notif)
{
- if (DEBUG) Log.d(TAG, "handleNiNotification" + " notificationId: " + notif.notificationId
- + " requestorId: " + notif.requestorId + " text: " + notif.text);
+ if (DEBUG) Log.d(TAG, "in handleNiNotification () :"
+ + " notificationId: " + notif.notificationId
+ + " requestorId: " + notif.requestorId
+ + " text: " + notif.text
+ + " mIsSuplEsEnabled" + mIsSuplEsEnabled);
- // Notify and verify with immediate pop-up
- if (notif.needNotify && notif.needVerify && mPopupImmediately)
- {
- // Popup the dialog box now
- openNiDialog(notif);
- }
-
- // Notify only, or delayed pop-up (change mPopupImmediately to FALSE)
- if (notif.needNotify && !notif.needVerify ||
- notif.needNotify && notif.needVerify && !mPopupImmediately)
- {
- // Show the notification
-
- // if mPopupImmediately == FALSE and needVerify == TRUE, a dialog will be opened
- // when the user opens the notification message
-
- setNiNotification(notif);
- }
-
- // ACCEPT cases: 1. Notify, no verify; 2. no notify, no verify; 3. privacy override.
- if ( notif.needNotify && !notif.needVerify ||
- !notif.needNotify && !notif.needVerify ||
- notif.privacyOverride)
- {
- mLocationManager.sendNiResponse(notif.notificationId, GPS_NI_RESPONSE_ACCEPT);
+ if (mIsSuplEsEnabled == false) {
+ handleNi(notif);
+ } else {
+ handleNiInEs(notif);
}
//////////////////////////////////////////////////////////////////////////
@@ -176,6 +234,72 @@
//
}
+ // handle NI form HAL when SUPL_ES is disabled.
+ private void handleNi(GpsNiNotification notif) {
+ if (DEBUG) Log.d(TAG, "in handleNi () :"
+ + " needNotify: " + notif.needNotify
+ + " needVerify: " + notif.needVerify
+ + " privacyOverride: " + notif.privacyOverride
+ + " mPopupImmediately: " + mPopupImmediately);
+
+ // legacy behaviour
+ if (notif.needNotify) {
+ // If NI does not need verify or the dialog is not requested
+ // to pop up immediately, the dialog box will not pop up.
+ if (notif.needVerify && mPopupImmediately) {
+ // Popup the dialog box now
+ openNiDialog(notif);
+ } else {
+ // Show the notification
+ setNiNotification(notif);
+ }
+ }
+ // ACCEPT cases: 1. Notify, no verify; 2. no notify, no verify;
+ // 3. privacy override.
+ if (!notif.needVerify || notif.privacyOverride) {
+ try {
+ mNetInitiatedListener.sendNiResponse(notif.notificationId,
+ GPS_NI_RESPONSE_ACCEPT);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in sendNiResponse");
+ }
+ }
+ }
+
+ // handle NI from HAL when the SUPL_ES is enabled
+ private void handleNiInEs(GpsNiNotification notif) {
+
+ if (DEBUG) Log.d(TAG, "in handleNiInEs () :"
+ + " niType: " + notif.niType
+ + " notificationId: " + notif.notificationId);
+
+ // UE is in emergency mode when in emergency call mode or in emergency call back mode
+ boolean isUEInEmergencyMode = mIsInEmergency ||
+ Boolean.parseBoolean(SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE));
+
+ /*
+ 1. When SUPL ES bit is off and UE is not in emergency mode:
+ Call handleNi() to do legacy behaviour.
+ 2. When SUPL ES bit is on and UE is in emergency mode:
+ Call handleNi() to do acceptance behaviour.
+ 3. When SUPL ES bit is off but UE is in emergency mode:
+ Ignore the emergency SUPL INIT.
+ 4. When SUPL ES bit is on but UE is not in emergency mode:
+ Ignore the emergency SUPL INIT.
+ */
+ boolean isNiTypeES = (notif.niType == GPS_NI_TYPE_EMERGENCY_SUPL);
+ if (isNiTypeES != isUEInEmergencyMode) {
+ try {
+ mNetInitiatedListener.sendNiResponse(notif.notificationId,
+ GPS_NI_RESPONSE_IGNORE);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in sendNiResponse");
+ }
+ } else {
+ handleNi(notif);
+ }
+ }
+
// Sets the NI notification.
private synchronized void setNiNotification(GpsNiNotification notif) {
NotificationManager notificationManager = (NotificationManager) mContext
@@ -202,7 +326,7 @@
mNiNotification.defaults |= Notification.DEFAULT_SOUND;
} else {
mNiNotification.defaults &= ~Notification.DEFAULT_SOUND;
- }
+ }
mNiNotification.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_AUTO_CANCEL;
mNiNotification.tickerText = getNotifTicker(notif, mContext);
@@ -230,7 +354,7 @@
mContext.startActivity(intent);
}
- // Construct the intent for bringing up the dialog activity, which shows the
+ // Construct the intent for bringing up the dialog activity, which shows the
// notification and takes user input
private Intent getDlgIntent(GpsNiNotification notif)
{
@@ -239,7 +363,7 @@
String message = getDialogMessage(notif, mContext);
// directly bring up the NI activity
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setClass(mContext, com.android.internal.app.NetInitiatedActivity.class);
// put data in the intent
@@ -409,7 +533,7 @@
decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
decodeString(notif.text, mIsHexInput, notif.textEncoding));
return message;
- }
+ }
// change this to configure dialog display (for verification)
static public String getDialogTitle(GpsNiNotification notif, Context context)
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 9b644f4..d7ede34 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -162,16 +162,13 @@
public final static int FLAG_BEACON = 0x1 << 3;
/**
- * @hide
- * CANDIDATE FOR PUBLIC API
* Flag requesting the use of an output stream supporting hardware A/V synchronization.
*/
- // TODO add in FLAG_ALL_PUBLIC when in public API
public final static int FLAG_HW_AV_SYNC = 0x1 << 4;
private final static int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO |
FLAG_BEACON | FLAG_HW_AV_SYNC;
- private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED;
+ private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED | FLAG_HW_AV_SYNC;
private int mUsage = USAGE_UNKNOWN;
private int mContentType = CONTENT_TYPE_UNKNOWN;
diff --git a/media/java/android/media/AudioDevice.java b/media/java/android/media/AudioDevice.java
index e078354..df4d60d 100644
--- a/media/java/android/media/AudioDevice.java
+++ b/media/java/android/media/AudioDevice.java
@@ -20,90 +20,91 @@
/**
* Class to provide information about the audio devices.
+ * @hide
*/
public class AudioDevice {
/**
* A device type associated with an unknown or uninitialized device.
*/
- public static final int DEVICE_TYPE_UNKNOWN = 0;
+ public static final int TYPE_UNKNOWN = 0;
/**
* A device type describing the attached earphone speaker.
*/
- public static final int DEVICE_TYPE_BUILTIN_EARPIECE = 1;
+ public static final int TYPE_BUILTIN_EARPIECE = 1;
/**
* A device type describing the speaker system (i.e. a mono speaker or stereo speakers) built
* in a device.
*/
- public static final int DEVICE_TYPE_BUILTIN_SPEAKER = 2;
+ public static final int TYPE_BUILTIN_SPEAKER = 2;
/**
* A device type describing a headset, which is the combination of a headphones and microphone.
*/
- public static final int DEVICE_TYPE_WIRED_HEADSET = 3;
+ public static final int TYPE_WIRED_HEADSET = 3;
/**
* A device type describing a pair of wired headphones .
*/
- public static final int DEVICE_TYPE_WIRED_HEADPHONES = 4;
+ public static final int TYPE_WIRED_HEADPHONES = 4;
/**
* A device type describing an analog line-level connection.
*/
- public static final int DEVICE_TYPE_LINE_ANALOG = 5;
+ public static final int TYPE_LINE_ANALOG = 5;
/**
* A device type describing a digital line connection (e.g. SPDIF).
*/
- public static final int DEVICE_TYPE_LINE_DIGITAL = 6;
+ public static final int TYPE_LINE_DIGITAL = 6;
/**
* A device type describing a Bluetooth device typically used for telephony .
*/
- public static final int DEVICE_TYPE_BLUETOOTH_SCO = 7;
+ public static final int TYPE_BLUETOOTH_SCO = 7;
/**
* A device type describing a Bluetooth device supporting the A2DP profile.
*/
- public static final int DEVICE_TYPE_BLUETOOTH_A2DP = 8;
+ public static final int TYPE_BLUETOOTH_A2DP = 8;
/**
* A device type describing an HDMI connection .
*/
- public static final int DEVICE_TYPE_HDMI = 9;
+ public static final int TYPE_HDMI = 9;
/**
* A device type describing the Audio Return Channel of an HDMI connection.
*/
- public static final int DEVICE_TYPE_HDMI_ARC = 10;
+ public static final int TYPE_HDMI_ARC = 10;
/**
* A device type describing a USB audio device.
*/
- public static final int DEVICE_TYPE_USB_DEVICE = 11;
+ public static final int TYPE_USB_DEVICE = 11;
/**
* A device type describing a USB audio device in accessory mode.
*/
- public static final int DEVICE_TYPE_USB_ACCESSORY = 12;
+ public static final int TYPE_USB_ACCESSORY = 12;
/**
* A device type describing the audio device associated with a dock.
*/
- public static final int DEVICE_TYPE_DOCK = 13;
+ public static final int TYPE_DOCK = 13;
/**
* A device type associated with the transmission of audio signals over FM.
*/
- public static final int DEVICE_TYPE_FM = 14;
+ public static final int TYPE_FM = 14;
/**
* A device type describing the microphone(s) built in a device.
*/
- public static final int DEVICE_TYPE_BUILTIN_MIC = 15;
+ public static final int TYPE_BUILTIN_MIC = 15;
/**
* A device type for accessing the audio content transmitted over FM.
*/
- public static final int DEVICE_TYPE_FM_TUNER = 16;
+ public static final int TYPE_FM_TUNER = 16;
/**
* A device type for accessing the audio content transmitted over the TV tuner system.
*/
- public static final int DEVICE_TYPE_TV_TUNER = 17;
+ public static final int TYPE_TV_TUNER = 17;
/**
* A device type describing the transmission of audio signals over the telephony network.
*/
- public static final int DEVICE_TYPE_TELEPHONY = 18;
+ public static final int TYPE_TELEPHONY = 18;
/**
* A device type describing the auxiliary line-level connectors.
*/
- public static final int DEVICE_TYPE_AUX_LINE = 19;
+ public static final int TYPE_AUX_LINE = 19;
AudioDevicePortConfig mConfig;
@@ -135,7 +136,7 @@
* @return
*/
public int getDeviceType() {
- return INT_TO_EXT_DEVICE_MAPPING.get(mConfig.port().type(), DEVICE_TYPE_UNKNOWN);
+ return INT_TO_EXT_DEVICE_MAPPING.get(mConfig.port().type(), TYPE_UNKNOWN);
}
/**
@@ -154,7 +155,7 @@
/** @hide */
public static int convertInternalDeviceToDeviceType(int intDevice) {
- return INT_TO_EXT_DEVICE_MAPPING.get(intDevice, DEVICE_TYPE_UNKNOWN);
+ return INT_TO_EXT_DEVICE_MAPPING.get(intDevice, TYPE_UNKNOWN);
}
private static final SparseIntArray INT_TO_EXT_DEVICE_MAPPING;
@@ -163,43 +164,43 @@
static {
INT_TO_EXT_DEVICE_MAPPING = new SparseIntArray();
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_EARPIECE, DEVICE_TYPE_BUILTIN_EARPIECE);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPEAKER, DEVICE_TYPE_BUILTIN_SPEAKER);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_WIRED_HEADSET, DEVICE_TYPE_WIRED_HEADSET);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, DEVICE_TYPE_WIRED_HEADPHONES);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, DEVICE_TYPE_BLUETOOTH_SCO);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET, DEVICE_TYPE_BLUETOOTH_SCO);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT, DEVICE_TYPE_BLUETOOTH_SCO);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, DEVICE_TYPE_BLUETOOTH_A2DP);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, DEVICE_TYPE_BLUETOOTH_A2DP);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, DEVICE_TYPE_BLUETOOTH_A2DP);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_HDMI, DEVICE_TYPE_HDMI);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET, DEVICE_TYPE_DOCK);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET, DEVICE_TYPE_DOCK);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_USB_ACCESSORY, DEVICE_TYPE_USB_ACCESSORY);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_USB_DEVICE, DEVICE_TYPE_USB_DEVICE);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_TELEPHONY_TX, DEVICE_TYPE_TELEPHONY);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_LINE, DEVICE_TYPE_LINE_ANALOG);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_HDMI_ARC, DEVICE_TYPE_HDMI_ARC);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPDIF, DEVICE_TYPE_LINE_DIGITAL);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_FM, DEVICE_TYPE_FM);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_AUX_LINE, DEVICE_TYPE_AUX_LINE);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_EARPIECE, TYPE_BUILTIN_EARPIECE);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPEAKER, TYPE_BUILTIN_SPEAKER);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_WIRED_HEADSET, TYPE_WIRED_HEADSET);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, TYPE_WIRED_HEADPHONES);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, TYPE_BLUETOOTH_SCO);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET, TYPE_BLUETOOTH_SCO);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT, TYPE_BLUETOOTH_SCO);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, TYPE_BLUETOOTH_A2DP);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, TYPE_BLUETOOTH_A2DP);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, TYPE_BLUETOOTH_A2DP);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_HDMI, TYPE_HDMI);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET, TYPE_DOCK);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET, TYPE_DOCK);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_USB_ACCESSORY, TYPE_USB_ACCESSORY);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_USB_DEVICE, TYPE_USB_DEVICE);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_TELEPHONY_TX, TYPE_TELEPHONY);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_LINE, TYPE_LINE_ANALOG);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_HDMI_ARC, TYPE_HDMI_ARC);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPDIF, TYPE_LINE_DIGITAL);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_FM, TYPE_FM);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_AUX_LINE, TYPE_AUX_LINE);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, DEVICE_TYPE_BUILTIN_MIC);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, DEVICE_TYPE_BLUETOOTH_SCO);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_WIRED_HEADSET, DEVICE_TYPE_WIRED_HEADSET);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_HDMI, DEVICE_TYPE_HDMI);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_TELEPHONY_RX, DEVICE_TYPE_TELEPHONY);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BACK_MIC, DEVICE_TYPE_BUILTIN_MIC);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET, DEVICE_TYPE_DOCK);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET, DEVICE_TYPE_DOCK);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_USB_ACCESSORY, DEVICE_TYPE_USB_ACCESSORY);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_USB_DEVICE, DEVICE_TYPE_USB_DEVICE);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_FM_TUNER, DEVICE_TYPE_FM_TUNER);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_TV_TUNER, DEVICE_TYPE_TV_TUNER);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_LINE, DEVICE_TYPE_LINE_ANALOG);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_SPDIF, DEVICE_TYPE_LINE_DIGITAL);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, DEVICE_TYPE_BLUETOOTH_A2DP);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, TYPE_BUILTIN_MIC);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, TYPE_BLUETOOTH_SCO);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_WIRED_HEADSET, TYPE_WIRED_HEADSET);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_HDMI, TYPE_HDMI);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_TELEPHONY_RX, TYPE_TELEPHONY);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BACK_MIC, TYPE_BUILTIN_MIC);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET, TYPE_DOCK);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET, TYPE_DOCK);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_USB_ACCESSORY, TYPE_USB_ACCESSORY);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_USB_DEVICE, TYPE_USB_DEVICE);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_FM_TUNER, TYPE_FM_TUNER);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_TV_TUNER, TYPE_TV_TUNER);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_LINE, TYPE_LINE_ANALOG);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_SPDIF, TYPE_LINE_DIGITAL);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, TYPE_BLUETOOTH_A2DP);
// not covered here, legacy
//AudioSystem.DEVICE_OUT_REMOTE_SUBMIX
@@ -207,25 +208,25 @@
// privileges mapping to output device
EXT_TO_INT_DEVICE_MAPPING = new SparseIntArray();
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BUILTIN_EARPIECE, AudioSystem.DEVICE_OUT_EARPIECE);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BUILTIN_SPEAKER, AudioSystem.DEVICE_OUT_SPEAKER);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_WIRED_HEADSET, AudioSystem.DEVICE_OUT_WIRED_HEADSET);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_WIRED_HEADPHONES, AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_LINE_ANALOG, AudioSystem.DEVICE_OUT_LINE);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_LINE_DIGITAL, AudioSystem.DEVICE_OUT_SPDIF);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BLUETOOTH_SCO, AudioSystem.DEVICE_OUT_BLUETOOTH_SCO);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BLUETOOTH_A2DP, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_HDMI, AudioSystem.DEVICE_OUT_HDMI);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_HDMI_ARC, AudioSystem.DEVICE_OUT_HDMI_ARC);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_USB_DEVICE, AudioSystem.DEVICE_OUT_USB_DEVICE);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_USB_ACCESSORY, AudioSystem.DEVICE_OUT_USB_ACCESSORY);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_DOCK, AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_FM, AudioSystem.DEVICE_OUT_FM);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BUILTIN_MIC, AudioSystem.DEVICE_IN_BUILTIN_MIC);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_FM_TUNER, AudioSystem.DEVICE_IN_FM_TUNER);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_TV_TUNER, AudioSystem.DEVICE_IN_TV_TUNER);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_TELEPHONY, AudioSystem.DEVICE_OUT_TELEPHONY_TX);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_AUX_LINE, AudioSystem.DEVICE_OUT_AUX_LINE);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BUILTIN_EARPIECE, AudioSystem.DEVICE_OUT_EARPIECE);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BUILTIN_SPEAKER, AudioSystem.DEVICE_OUT_SPEAKER);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_WIRED_HEADSET, AudioSystem.DEVICE_OUT_WIRED_HEADSET);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_WIRED_HEADPHONES, AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_LINE_ANALOG, AudioSystem.DEVICE_OUT_LINE);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_LINE_DIGITAL, AudioSystem.DEVICE_OUT_SPDIF);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLUETOOTH_SCO, AudioSystem.DEVICE_OUT_BLUETOOTH_SCO);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLUETOOTH_A2DP, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_HDMI, AudioSystem.DEVICE_OUT_HDMI);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_HDMI_ARC, AudioSystem.DEVICE_OUT_HDMI_ARC);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_USB_DEVICE, AudioSystem.DEVICE_OUT_USB_DEVICE);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_USB_ACCESSORY, AudioSystem.DEVICE_OUT_USB_ACCESSORY);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_DOCK, AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_FM, AudioSystem.DEVICE_OUT_FM);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BUILTIN_MIC, AudioSystem.DEVICE_IN_BUILTIN_MIC);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_FM_TUNER, AudioSystem.DEVICE_IN_FM_TUNER);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_TV_TUNER, AudioSystem.DEVICE_IN_TV_TUNER);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_TELEPHONY, AudioSystem.DEVICE_OUT_TELEPHONY_TX);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_AUX_LINE, AudioSystem.DEVICE_OUT_AUX_LINE);
}
}
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index d93d81b..58ed4f8 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -320,15 +320,26 @@
/**
* Builder class for {@link AudioFormat} objects.
+ * Use this class to configure and create an AudioFormat instance. By setting format
+ * characteristics such as audio encoding, channel mask or sample rate, you indicate which
+ * of those are to vary from the default behavior on this device wherever this audio format
+ * is used.
+ * <p>{@link AudioFormat} is for instance used in
+ * {@link AudioTrack#AudioTrack(AudioAttributes, AudioFormat, int, int, int)}. In this
+ * constructor, every format characteristic set on the <code>Builder</code> (e.g. with
+ * {@link #setSampleRate(int)}) will alter the default values used by an
+ * <code>AudioTrack</code>. In this case for audio playback with <code>AudioTrack</code>, the
+ * sample rate set in the <code>Builder</code> would override the platform output sample rate
+ * which would otherwise be selected by default.
*/
public static class Builder {
- private int mEncoding = ENCODING_PCM_16BIT;
+ private int mEncoding = ENCODING_INVALID;
private int mSampleRate = 0;
private int mChannelMask = CHANNEL_INVALID;
private int mPropertySetMask = AUDIO_FORMAT_HAS_PROPERTY_NONE;
/**
- * Constructs a new Builder with the defaults format values.
+ * Constructs a new Builder with none of the format characteristics set.
*/
public Builder() {
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index e3b8985..559c247 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -19,6 +19,7 @@
import android.Manifest;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.app.PendingIntent;
import android.bluetooth.BluetoothDevice;
import android.content.ComponentName;
@@ -36,6 +37,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.ServiceManager;
@@ -1959,7 +1961,42 @@
return;
}
- if (!querySoundEffectsEnabled()) {
+ if (!querySoundEffectsEnabled(Process.myUserHandle().getIdentifier())) {
+ return;
+ }
+
+ IAudioService service = getService();
+ try {
+ service.playSoundEffect(effectType);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in playSoundEffect"+e);
+ }
+ }
+
+ /**
+ * Plays a sound effect (Key clicks, lid open/close...)
+ * @param effectType The type of sound effect. One of
+ * {@link #FX_KEY_CLICK},
+ * {@link #FX_FOCUS_NAVIGATION_UP},
+ * {@link #FX_FOCUS_NAVIGATION_DOWN},
+ * {@link #FX_FOCUS_NAVIGATION_LEFT},
+ * {@link #FX_FOCUS_NAVIGATION_RIGHT},
+ * {@link #FX_KEYPRESS_STANDARD},
+ * {@link #FX_KEYPRESS_SPACEBAR},
+ * {@link #FX_KEYPRESS_DELETE},
+ * {@link #FX_KEYPRESS_RETURN},
+ * {@link #FX_KEYPRESS_INVALID},
+ * @param userId The current user to pull sound settings from
+ * NOTE: This version uses the UI settings to determine
+ * whether sounds are heard or not.
+ * @hide
+ */
+ public void playSoundEffect(int effectType, int userId) {
+ if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
+ return;
+ }
+
+ if (!querySoundEffectsEnabled(userId)) {
return;
}
@@ -2006,8 +2043,9 @@
/**
* Settings has an in memory cache, so this is fast.
*/
- private boolean querySoundEffectsEnabled() {
- return Settings.System.getInt(mContext.getContentResolver(), Settings.System.SOUND_EFFECTS_ENABLED, 0) != 0;
+ private boolean querySoundEffectsEnabled(int user) {
+ return Settings.System.getIntForUser(mContext.getContentResolver(),
+ Settings.System.SOUND_EFFECTS_ENABLED, 0, user) != 0;
}
@@ -3121,6 +3159,21 @@
}
/**
+ * Returns true if Hdmi Cec system audio mode is supported.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean isHdmiSystemAudioSupported() {
+ try {
+ return getService().isHdmiSystemAudioSupported();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error querying system audio mode", e);
+ return false;
+ }
+ }
+
+ /**
* Return codes for listAudioPorts(), createAudioPatch() ...
*/
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index cd4f31e..91a8468 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -5105,6 +5105,11 @@
return device;
}
+ @Override
+ public boolean isHdmiSystemAudioSupported() {
+ return mHdmiSystemAudioSupported;
+ }
+
//==========================================================================================
// Camera shutter sound policy.
// config_camera_sound_forced configuration option in config.xml defines if the camera shutter
diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java
index 8883d28..5651fc9 100644
--- a/media/java/android/media/CamcorderProfile.java
+++ b/media/java/android/media/CamcorderProfile.java
@@ -177,9 +177,15 @@
*/
public static final int QUALITY_HIGH_SPEED_1080P = 2004;
+ /**
+ * High speed ( >= 100fps) quality level corresponding to the 2160p (3840 x 2160)
+ * resolution.
+ */
+ public static final int QUALITY_HIGH_SPEED_2160P = 2005;
+
// Start and end of high speed quality list
private static final int QUALITY_HIGH_SPEED_LIST_START = QUALITY_HIGH_SPEED_LOW;
- private static final int QUALITY_HIGH_SPEED_LIST_END = QUALITY_HIGH_SPEED_1080P;
+ private static final int QUALITY_HIGH_SPEED_LIST_END = QUALITY_HIGH_SPEED_2160P;
/**
* Default recording duration in seconds before the session is terminated.
@@ -313,6 +319,7 @@
* @see #QUALITY_HIGH_SPEED_480P
* @see #QUALITY_HIGH_SPEED_720P
* @see #QUALITY_HIGH_SPEED_1080P
+ * @see #QUALITY_HIGH_SPEED_2160P
*/
public static CamcorderProfile get(int cameraId, int quality) {
if (!((quality >= QUALITY_LIST_START &&
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 6477055..75fc03c 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -201,6 +201,8 @@
int setHdmiSystemAudioSupported(boolean on);
- boolean registerAudioPolicy(in AudioPolicyConfig policyConfig, IBinder cb);
+ boolean isHdmiSystemAudioSupported();
+
+ boolean registerAudioPolicy(in AudioPolicyConfig policyConfig, IBinder cb);
oneway void unregisterAudioPolicyAsync(in IBinder cb);
}
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 675916b..b4fef36 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -672,6 +672,11 @@
super(detailMessage);
mErrorCode = errorCode;
mActionCode = actionCode;
+
+ // TODO get this from codec
+ final String sign = errorCode < 0 ? "neg_" : "";
+ mDiagnosticInfo =
+ "android.media.MediaCodec.error_" + sign + Math.abs(errorCode);
}
/**
@@ -696,15 +701,28 @@
* Retrieve the error code associated with a CodecException.
* This is opaque diagnostic information and may depend on
* hardware or API level.
+ *
+ * @hide
*/
public int getErrorCode() {
return mErrorCode;
}
+ /**
+ * Retrieve a human readable diagnostic information string
+ * associated with the exception. DO NOT SHOW THIS TO END-USERS!
+ * This string will not be localized or generally comprehensible
+ * to end-users.
+ */
+ public String getDiagnosticInfo() {
+ return mDiagnosticInfo;
+ }
+
/* Must be in sync with android_media_MediaCodec.cpp */
private final static int ACTION_TRANSIENT = 1;
private final static int ACTION_RECOVERABLE = 2;
+ private final String mDiagnosticInfo;
private final int mErrorCode;
private final int mActionCode;
}
@@ -737,6 +755,13 @@
public static final int ERROR_RESOURCE_BUSY = 3;
/**
+ * This indicates that the output protection levels supported by the
+ * device are not sufficient to meet the requirements set by the
+ * content owner in the license policy.
+ */
+ public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4;
+
+ /**
* Retrieve the error code associated with a CryptoException
*/
public int getErrorCode() {
@@ -1731,7 +1756,7 @@
if (cropRect != null) {
cropRect.offset(-xOffset, -yOffset);
}
- setCropRect(cropRect);
+ super.setCropRect(cropRect);
// save offsets and info
mXOffset = xOffset;
diff --git a/media/java/android/media/MediaCodecList.java b/media/java/android/media/MediaCodecList.java
index 85e9b16..0dcbd65 100644
--- a/media/java/android/media/MediaCodecList.java
+++ b/media/java/android/media/MediaCodecList.java
@@ -118,6 +118,7 @@
/** @hide */
public static MediaCodecInfo getInfoFor(String codec) {
+ initCodecList();
return sAllCodecInfos[findCodecByName(codec)];
}
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index ca707d8..1490732 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -188,18 +188,37 @@
*/
public static final class MediaDrmStateException extends java.lang.IllegalStateException {
private final int mErrorCode;
+ private final String mDiagnosticInfo;
public MediaDrmStateException(int errorCode, String detailMessage) {
super(detailMessage);
mErrorCode = errorCode;
+
+ // TODO get this from DRM session
+ final String sign = errorCode < 0 ? "neg_" : "";
+ mDiagnosticInfo =
+ "android.media.MediaDrm.error_" + sign + Math.abs(errorCode);
+
}
/**
* Retrieve the associated error code
+ *
+ * @hide
*/
public int getErrorCode() {
return mErrorCode;
}
+
+ /**
+ * Retrieve a human readable diagnostic information string
+ * associated with the exception. DO NOT SHOW THIS TO END-USERS!
+ * This string will not be localized or generally comprehensible
+ * to end-users.
+ */
+ public String getDiagnosticInfo() {
+ return mDiagnosticInfo;
+ }
}
/**
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 9343aa4..afa0b6e 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1929,6 +1929,7 @@
mSubtitleController.setAnchor(anchor);
}
+ private final Object mInbandSubtitleLock = new Object();
private SubtitleTrack[] mInbandSubtitleTracks;
private int mSelectedSubtitleTrackIndex = -1;
private Vector<SubtitleTrack> mOutOfBandSubtitleTracks;
@@ -2036,19 +2037,21 @@
}
TrackInfo[] tracks = getInbandTrackInfo();
- SubtitleTrack[] inbandTracks = new SubtitleTrack[tracks.length];
- for (int i=0; i < tracks.length; i++) {
- if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
- if (i < mInbandSubtitleTracks.length) {
- inbandTracks[i] = mInbandSubtitleTracks[i];
- } else {
- SubtitleTrack track = mSubtitleController.addTrack(
- tracks[i].getFormat());
- inbandTracks[i] = track;
+ synchronized (mInbandSubtitleLock) {
+ SubtitleTrack[] inbandTracks = new SubtitleTrack[tracks.length];
+ for (int i=0; i < tracks.length; i++) {
+ if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
+ if (i < mInbandSubtitleTracks.length) {
+ inbandTracks[i] = mInbandSubtitleTracks[i];
+ } else {
+ SubtitleTrack track = mSubtitleController.addTrack(
+ tracks[i].getFormat());
+ inbandTracks[i] = track;
+ }
}
}
+ mInbandSubtitleTracks = inbandTracks;
}
- mInbandSubtitleTracks = inbandTracks;
mSubtitleController.selectDefaultTrack();
}
@@ -2224,9 +2227,9 @@
try {
Libcore.os.lseek(fd3, offset2, OsConstants.SEEK_SET);
byte[] buffer = new byte[4096];
- for (int total = 0; total < length2;) {
- int remain = (int)length2 - total;
- int bytes = IoBridge.read(fd3, buffer, 0, Math.min(buffer.length, remain));
+ for (long total = 0; total < length2;) {
+ int bytesToRead = (int) Math.min(buffer.length, length2 - total);
+ int bytes = IoBridge.read(fd3, buffer, 0, bytesToRead);
if (bytes < 0) {
break;
} else {
@@ -2358,6 +2361,18 @@
throws IllegalStateException {
// handle subtitle track through subtitle controller
SubtitleTrack track = null;
+ synchronized (mInbandSubtitleLock) {
+ if (mInbandSubtitleTracks.length == 0) {
+ TrackInfo[] tracks = getInbandTrackInfo();
+ mInbandSubtitleTracks = new SubtitleTrack[tracks.length];
+ for (int i=0; i < tracks.length; i++) {
+ if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
+ mInbandSubtitleTracks[i] = mSubtitleController.addTrack(tracks[i].getFormat());
+ }
+ }
+ }
+ }
+
if (index < mInbandSubtitleTracks.length) {
track = mInbandSubtitleTracks[index];
} else if (index < mInbandSubtitleTracks.length + mOutOfBandSubtitleTracks.size()) {
@@ -3256,9 +3271,7 @@
if (DEBUG) Log.d(TAG, "scheduleUpdate");
int i = registerListener(listener);
- if (mStopped) {
- scheduleNotification(NOTIFY_STOP, 0 /* delay */);
- } else {
+ if (!mStopped) {
mTimes[i] = 0;
scheduleNotification(NOTIFY_TIME, 0 /* delay */);
}
diff --git a/media/java/android/media/SubtitleController.java b/media/java/android/media/SubtitleController.java
index 37adb8c..f82dbe0 100644
--- a/media/java/android/media/SubtitleController.java
+++ b/media/java/android/media/SubtitleController.java
@@ -275,7 +275,7 @@
mSelectedTrack.getFormat().getInteger(
MediaFormat.KEY_IS_FORCED_SUBTITLE, 0) != 0)) {
show();
- } else {
+ } else if (mSelectedTrack != null && !mSelectedTrack.isTimedText()) {
hide();
}
mVisibilityIsExplicit = false;
diff --git a/media/java/android/media/audiofx/Virtualizer.java b/media/java/android/media/audiofx/Virtualizer.java
index b314c02..be5adc8 100644
--- a/media/java/android/media/audiofx/Virtualizer.java
+++ b/media/java/android/media/audiofx/Virtualizer.java
@@ -16,11 +16,14 @@
package android.media.audiofx;
+import android.annotation.IntDef;
import android.media.AudioDevice;
import android.media.AudioFormat;
import android.media.audiofx.AudioEffect;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.StringTokenizer;
@@ -248,14 +251,114 @@
}
/**
- * Checks if the combination of a channel mask and device type is supported by this virtualizer.
+ * A virtualization mode indicating virtualization processing is not active.
+ * See {@link #getVirtualizationMode()} as one of the possible return value.
+ */
+ public static final int VIRTUALIZATION_MODE_OFF = 0;
+
+ /**
+ * A virtualization mode used to indicate the virtualizer effect must stop forcing the
+ * processing to a particular mode in {@link #forceVirtualizationMode(int)}.
+ */
+ public static final int VIRTUALIZATION_MODE_AUTO = 1;
+ /**
+ * A virtualization mode typically used over headphones.
+ * Binaural virtualization describes an audio processing configuration for virtualization
+ * where the left and right channels are respectively reaching the left and right ear of the
+ * user, without also feeding the opposite ear (as is the case when listening over speakers).
+ * <p>Such a mode is therefore meant to be used when audio is playing over stereo wired
+ * headphones or headsets, but also stereo headphones through a wireless A2DP Bluetooth link.
+ * <p>See {@link #canVirtualize(int, int)} to verify this mode is supported by this Virtualizer.
+ */
+ public final static int VIRTUALIZATION_MODE_BINAURAL = 2;
+
+ /**
+ * A virtualization mode typically used over speakers.
+ * Transaural virtualization describes an audio processing configuration that differs from
+ * binaural (as described in {@link #VIRTUALIZATION_MODE_BINAURAL} in that cross-talk is
+ * present, i.e. audio played from the left channel also reaches the right ear of the user,
+ * and vice-versa.
+ * <p>When supported, such a mode is therefore meant to be used when audio is playing over the
+ * built-in stereo speakers of a device, if they are featured.
+ * <p>See {@link #canVirtualize(int, int)} to verify this mode is supported by this Virtualizer.
+ */
+ public final static int VIRTUALIZATION_MODE_TRANSAURAL = 3;
+
+ /** @hide */
+ @IntDef( {
+ VIRTUALIZATION_MODE_BINAURAL,
+ VIRTUALIZATION_MODE_TRANSAURAL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface VirtualizationMode {}
+
+ /** @hide */
+ @IntDef( {
+ VIRTUALIZATION_MODE_AUTO,
+ VIRTUALIZATION_MODE_BINAURAL,
+ VIRTUALIZATION_MODE_TRANSAURAL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ForceVirtualizationMode {}
+
+ private static int getDeviceForModeQuery(@VirtualizationMode int virtualizationMode)
+ throws IllegalArgumentException {
+ switch (virtualizationMode) {
+ case VIRTUALIZATION_MODE_BINAURAL:
+ return AudioDevice.TYPE_WIRED_HEADPHONES;
+ case VIRTUALIZATION_MODE_TRANSAURAL:
+ return AudioDevice.TYPE_BUILTIN_SPEAKER;
+ default:
+ throw (new IllegalArgumentException(
+ "Virtualizer: illegal virtualization mode " + virtualizationMode));
+ }
+ }
+
+ private static int getDeviceForModeForce(@ForceVirtualizationMode int virtualizationMode)
+ throws IllegalArgumentException {
+ if (virtualizationMode == VIRTUALIZATION_MODE_AUTO) {
+ return AudioDevice.TYPE_UNKNOWN;
+ } else {
+ return getDeviceForModeQuery(virtualizationMode);
+ }
+ }
+
+ private static int deviceToMode(int deviceType) {
+ switch (deviceType) {
+ case AudioDevice.TYPE_WIRED_HEADSET:
+ case AudioDevice.TYPE_WIRED_HEADPHONES:
+ case AudioDevice.TYPE_BLUETOOTH_SCO:
+ case AudioDevice.TYPE_BUILTIN_EARPIECE:
+ return VIRTUALIZATION_MODE_BINAURAL;
+ case AudioDevice.TYPE_BUILTIN_SPEAKER:
+ case AudioDevice.TYPE_LINE_ANALOG:
+ case AudioDevice.TYPE_LINE_DIGITAL:
+ case AudioDevice.TYPE_BLUETOOTH_A2DP:
+ case AudioDevice.TYPE_HDMI:
+ case AudioDevice.TYPE_HDMI_ARC:
+ case AudioDevice.TYPE_USB_DEVICE:
+ case AudioDevice.TYPE_USB_ACCESSORY:
+ case AudioDevice.TYPE_DOCK:
+ case AudioDevice.TYPE_FM:
+ case AudioDevice.TYPE_AUX_LINE:
+ return VIRTUALIZATION_MODE_TRANSAURAL;
+ case AudioDevice.TYPE_UNKNOWN:
+ default:
+ return VIRTUALIZATION_MODE_OFF;
+ }
+ }
+
+ /**
+ * Checks if the combination of a channel mask and virtualization mode is supported by this
+ * virtualizer.
* Some virtualizer implementations may only support binaural processing (i.e. only support
- * headphone output), some may support transaural processing (i.e. for speaker output) for the
+ * headphone output, see {@link #VIRTUALIZATION_MODE_BINAURAL}), some may support transaural
+ * processing (i.e. for speaker output, see {@link #VIRTUALIZATION_MODE_TRANSAURAL}) for the
* built-in speakers. Use this method to query the virtualizer implementation capabilities.
* @param inputChannelMask the channel mask of the content to virtualize.
- * @param deviceType the device type for which virtualization processing is to be performed.
- * Valid values are the device types defined in {@link AudioDevice}.
- * @return true if the combination of channel mask and output device type is supported, false
+ * @param virtualizationMode the mode for which virtualization processing is to be performed,
+ * one of {@link #VIRTUALIZATION_MODE_BINAURAL}, {@link #VIRTUALIZATION_MODE_TRANSAURAL}.
+ * @return true if the combination of channel mask and virtualization mode is supported, false
* otherwise.
* <br>An indication that a certain channel mask is not supported doesn't necessarily mean
* you cannot play content with that channel mask, it more likely implies the content will
@@ -268,22 +371,22 @@
* @throws IllegalArgumentException
* @throws UnsupportedOperationException
*/
- public boolean canVirtualize(int inputChannelMask, int deviceType)
+ public boolean canVirtualize(int inputChannelMask, @VirtualizationMode int virtualizationMode)
throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
- return getAnglesInt(inputChannelMask, deviceType, null);
+ return getAnglesInt(inputChannelMask, getDeviceForModeQuery(virtualizationMode), null);
}
/**
* Queries the virtual speaker angles (azimuth and elevation) for a combination of a channel
- * mask and device type.
- * If the virtualization configuration (mask and device) is supported (see
+ * mask and virtualization mode.
+ * If the virtualization configuration (mask and mode) is supported (see
* {@link #canVirtualize(int, int)}, the array angles will contain upon return the
* definition of each virtual speaker and its azimuth and elevation angles relative to the
* listener.
* <br>Note that in some virtualizer implementations, the angles may be strength-dependent.
* @param inputChannelMask the channel mask of the content to virtualize.
- * @param deviceType the device type for which virtualization processing is to be performed.
- * Valid values are the device types defined in {@link AudioDevice}.
+ * @param virtualizationMode the mode for which virtualization processing is to be performed,
+ * one of {@link #VIRTUALIZATION_MODE_BINAURAL}, {@link #VIRTUALIZATION_MODE_TRANSAURAL}.
* @param angles a non-null array whose length is 3 times the number of channels in the channel
* mask.
* If the method indicates the configuration is supported, the array will contain upon return
@@ -297,37 +400,39 @@
* <li>the element at index <code>3*i+2</code> contains its corresponding elevation angle
* where +90 is directly above the listener, 0 is the horizontal plane, and -90 is
* directly below the listener.</li>
- * @return true if the combination of channel mask and output device type is supported, false
+ * @return true if the combination of channel mask and virtualization mode is supported, false
* otherwise.
* @throws IllegalStateException
* @throws IllegalArgumentException
* @throws UnsupportedOperationException
*/
- public boolean getSpeakerAngles(int inputChannelMask, int deviceType, int[] angles)
+ public boolean getSpeakerAngles(int inputChannelMask,
+ @VirtualizationMode int virtualizationMode, int[] angles)
throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
if (angles == null) {
throw (new IllegalArgumentException(
"Virtualizer: illegal null channel / angle array"));
}
- return getAnglesInt(inputChannelMask, deviceType, angles);
+ return getAnglesInt(inputChannelMask, getDeviceForModeQuery(virtualizationMode), angles);
}
/**
- * Forces the virtualizer effect to use the processing mode used for the given device type.
+ * Forces the virtualizer effect to use the given processing mode.
* The effect must be enabled for the forced mode to be applied.
- * @param deviceType one of the device types defined in {@link AudioDevice}.
- * Use {@link AudioDevice#DEVICE_TYPE_UNKNOWN} to return to the non-forced mode.
- * @return true if the processing mode for the device type is supported, and it is successfully
- * set, or forcing was successfully disabled with {@link AudioDevice#DEVICE_TYPE_UNKNOWN},
- * false otherwise.
+ * @param virtualizationMode one of {@link #VIRTUALIZATION_MODE_BINAURAL},
+ * {@link #VIRTUALIZATION_MODE_TRANSAURAL} to force a particular processing mode, or
+ * {@value #VIRTUALIZATION_MODE_AUTO} to stop forcing a mode.
+ * @return true if the processing mode is supported, and it is successfully set, or
+ * forcing was successfully disabled, false otherwise.
* @throws IllegalStateException
* @throws IllegalArgumentException
* @throws UnsupportedOperationException
*/
- public boolean forceVirtualizationMode(int deviceType)
+ public boolean forceVirtualizationMode(@ForceVirtualizationMode int virtualizationMode)
throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
// convert Java device type to internal representation
+ int deviceType = getDeviceForModeForce(virtualizationMode);
int internalDevice = AudioDevice.convertDeviceTypeToInternalDevice(deviceType);
int status = setParameter(PARAM_FORCE_VIRTUALIZATION_MODE, internalDevice);
@@ -335,8 +440,8 @@
if (status >= 0) {
return true;
} else if (status == AudioEffect.ERROR_BAD_VALUE) {
- // a BAD_VALUE return from setParameter indicates the mode can't be forced to that
- // of this device, don't throw an exception, just return false
+ // a BAD_VALUE return from setParameter indicates the mode can't be forced
+ // don't throw an exception, just return false
return false;
} else {
// something wrong may have happened
@@ -349,31 +454,25 @@
}
/**
- * Return the device type which reflects the virtualization mode being used, if any.
- * @return a device type (as defined in {@link AudioDevice}) which reflects the virtualization
- * mode being used.
- * If virtualization is not active, the device type will be
- * {@link AudioDevice#DEVICE_TYPE_UNKNOWN}. Virtualization may not be active either because
- * the effect is not enabled or because the current output device is not compatible with
- * this virtualization implementation.
- * <p>Note that the return value may differ from a device type successfully set with
- * {@link #forceVirtualizationMode(int)} as the implementation
- * may use a single mode for multiple devices. An example of this is with
- * {@link AudioDevice#DEVICE_TYPE_WIRED_HEADSET} that would typically be handled
- * like {@link AudioDevice#DEVICE_TYPE_WIRED_HEADPHONES} from a virtualization
- * standpoint.
+ * Return the virtualization mode being used, if any.
+ * @return the virtualization mode being used.
+ * If virtualization is not active, the virtualization mode will be
+ * {@link #VIRTUALIZATION_MODE_OFF}. Otherwise the value will be
+ * {@link #VIRTUALIZATION_MODE_BINAURAL} or {@link #VIRTUALIZATION_MODE_TRANSAURAL}.
+ * Virtualization may not be active either because the effect is not enabled or
+ * because the current output device is not compatible with this virtualization
+ * implementation.
* @throws IllegalStateException
- * @throws IllegalArgumentException
* @throws UnsupportedOperationException
*/
public int getVirtualizationMode()
- throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
+ throws IllegalStateException, UnsupportedOperationException {
int[] value = new int[1];
int status = getParameter(PARAM_VIRTUALIZATION_MODE, value);
if (status >= 0) {
- return AudioDevice.convertInternalDeviceToDeviceType(value[0]);
+ return deviceToMode(AudioDevice.convertInternalDeviceToDeviceType(value[0]));
} else if (status == AudioEffect.ERROR_BAD_VALUE) {
- return AudioDevice.DEVICE_TYPE_UNKNOWN;
+ return VIRTUALIZATION_MODE_OFF;
} else {
// something wrong may have happened
checkStatus(status);
@@ -381,7 +480,7 @@
// unexpected virtualizer behavior
Log.e(TAG, "unexpected status code " + status
+ " after getParameter(PARAM_VIRTUALIZATION_MODE)");
- return AudioDevice.DEVICE_TYPE_UNKNOWN;
+ return VIRTUALIZATION_MODE_OFF;
}
/**
diff --git a/media/java/android/media/projection/IMediaProjection.aidl b/media/java/android/media/projection/IMediaProjection.aidl
index 3d25aa6..19fc052 100644
--- a/media/java/android/media/projection/IMediaProjection.aidl
+++ b/media/java/android/media/projection/IMediaProjection.aidl
@@ -26,6 +26,6 @@
boolean canProjectVideo();
boolean canProjectSecureVideo();
int applyVirtualDisplayFlags(int flags);
- void addCallback(IMediaProjectionCallback callback);
- void removeCallback(IMediaProjectionCallback callback);
+ void registerCallback(IMediaProjectionCallback callback);
+ void unregisterCallback(IMediaProjectionCallback callback);
}
diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java
index 3a74d93..e6dadf9 100644
--- a/media/java/android/media/projection/MediaProjection.java
+++ b/media/java/android/media/projection/MediaProjection.java
@@ -40,7 +40,7 @@
*
* <p>
* A screen capture session can be started through {@link
- * MediaProjectionManager#getScreenCaptureIntent}. This grants the ability to
+ * MediaProjectionManager#createScreenCaptureIntent}. This grants the ability to
* capture screen contents, but not system audio.
* </p>
*/
@@ -70,9 +70,9 @@
* @param handler The handler on which the callback should be invoked, or
* null if the callback should be invoked on the calling thread's looper.
*
- * @see #removeCallback
+ * @see #unregisterCallback
*/
- public void addCallback(Callback callback, Handler handler) {
+ public void registerCallback(Callback callback, Handler handler) {
if (callback == null) {
throw new IllegalArgumentException("callback should not be null");
}
@@ -83,9 +83,9 @@
*
* @param callback The callback to unregister.
*
- * @see #addCallback
+ * @see #registerCallback
*/
- public void removeCallback(Callback callback) {
+ public void unregisterCallback(Callback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback should not be null");
}
diff --git a/media/java/android/media/projection/MediaProjectionManager.java b/media/java/android/media/projection/MediaProjectionManager.java
index 50d66c6..a1cfc35 100644
--- a/media/java/android/media/projection/MediaProjectionManager.java
+++ b/media/java/android/media/projection/MediaProjectionManager.java
@@ -75,7 +75,7 @@
* the user whether to allow screen capture. The result of this
* activity should be passed to getMediaProjection.
*/
- public Intent getScreenCaptureIntent() {
+ public Intent createScreenCaptureIntent() {
Intent i = new Intent();
i.setClassName("com.android.systemui",
"com.android.systemui.media.MediaProjectionPermissionActivity");
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 8cb039ab..2c38697 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -191,11 +191,8 @@
return;
}
if (mCallback != null) {
- if (mCallback.mCallback == callback) {
- Log.w(TAG, "Tried to set same callback, ignoring");
- return;
- }
- // We're changing callbacks, clear the session from the old one.
+ // We're updating the callback, clear the session from the old
+ // one.
mCallback.mCallback.mSession = null;
}
if (handler == null) {
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
index aa196a9..06e40c5 100644
--- a/media/java/android/media/session/MediaSessionLegacyHelper.java
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -467,10 +467,7 @@
mSessions.remove(mPi);
} else if (mCb == null) {
mCb = new SessionCallback();
- Handler handler = null;
- if (Looper.myLooper() == null) {
- handler = new Handler(Looper.getMainLooper());
- }
+ Handler handler = new Handler(Looper.getMainLooper());
mSession.setCallback(mCb, handler);
}
}
diff --git a/media/java/android/media/tv/ITvInputManagerCallback.aidl b/media/java/android/media/tv/ITvInputManagerCallback.aidl
index 50a7636..6792680 100644
--- a/media/java/android/media/tv/ITvInputManagerCallback.aidl
+++ b/media/java/android/media/tv/ITvInputManagerCallback.aidl
@@ -24,4 +24,5 @@
void onInputStateChanged(in String inputId, int state);
void onInputAdded(in String inputId);
void onInputRemoved(in String inputId);
+ void onInputUpdated(in String inputId);
}
diff --git a/media/java/android/media/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java
index 7d1c7c6..b4ec2b3 100644
--- a/media/java/android/media/tv/TvContentRating.java
+++ b/media/java/android/media/tv/TvContentRating.java
@@ -247,6 +247,10 @@
* <td>TV content rating system for Iceland</td>
* </tr>
* <tr>
+ * <td>JP_TV</td>
+ * <td>TV content rating system for Japan</td>
+ * </tr>
+ * <tr>
* <td>KR_TV</td>
* <td>TV content rating system for South Korea</td>
* </tr>
@@ -912,6 +916,23 @@
* <td>Programs suitable for ages 18 and older</td>
* </tr>
* <tr>
+ * <td valign="top" rowspan="4">JP_TV</td>
+ * <td>JP_TV_G</td>
+ * <td>General, suitable for all ages</td>
+ * </tr>
+ * <tr>
+ * <td>JP_TV_PG12</td>
+ * <td>Parental guidance requested for young people under 12 years</td>
+ * </tr>
+ * <tr>
+ * <td>JP_TV_R15</td>
+ * <td>For persons aged 15 and above only</td>
+ * </tr>
+ * <tr>
+ * <td>JP_TV_R18</td>
+ * <td>For persons aged 18 and above only</td>
+ * </tr>
+ * <tr>
* <td valign="top" rowspan="5">KR_TV</td>
* <td>KR_TV_ALL</td>
* <td>Appropriate for all ages</td>
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index d2deb66..78714d2 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -477,6 +477,18 @@
*/
public void onInputRemoved(String inputId) {
}
+
+ /**
+ * This is called when a TV input is updated. The update of TV input happens when it is
+ * reinstalled or the media on which the newer version of TV input exists is
+ * available/unavailable.
+ *
+ * @param inputId The id of the TV input.
+ * @hide
+ */
+ @SystemApi
+ public void onInputUpdated(String inputId) {
+ }
}
private static final class TvInputCallbackRecord {
@@ -518,6 +530,15 @@
}
});
}
+
+ public void postInputUpdated(final String inputId) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onInputUpdated(inputId);
+ }
+ });
+ }
}
/**
@@ -707,9 +728,20 @@
}
}
}
+
+ @Override
+ public void onInputUpdated(String inputId) {
+ synchronized (mLock) {
+ for (TvInputCallbackRecord record : mCallbackRecords) {
+ record.postInputUpdated(inputId);
+ }
+ }
+ }
};
try {
- mService.registerCallback(mManagerCallback, mUserId);
+ if (mService != null) {
+ mService.registerCallback(mManagerCallback, mUserId);
+ }
} catch (RemoteException e) {
Log.e(TAG, "mService.registerCallback failed: " + e);
}
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 72a6f88..317d472 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -389,8 +389,11 @@
}
/**
- * Informs the application that video is available and the playback of the TV stream has
- * been started.
+ * Informs the application that the video is now available for watching. This is primarily
+ * used to signal the application to unblock the screen. The TV input service must call this
+ * method as soon as the content rendered onto its surface gets ready for viewing.
+ *
+ * @see #notifyVideoUnavailable
*/
public void notifyVideoAvailable() {
runOnMainThread(new Runnable() {
@@ -407,16 +410,18 @@
}
/**
- * Informs the application that video is not available, so the TV input cannot continue
- * playing the TV stream.
+ * Informs the application that the video became unavailable for some reason. This is
+ * primarily used to signal the application to block the screen not to show any intermittent
+ * video artifacts.
*
- * @param reason The reason that the TV input stopped the playback:
- * <ul>
- * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN}
- * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNING}
- * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL}
- * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_BUFFERING}
- * </ul>
+ * @param reason The reason why the video became unavailable:
+ * <ul>
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN}
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNING}
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL}
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_BUFFERING}
+ * </ul>
+ * @see #notifyVideoAvailable
*/
public void notifyVideoUnavailable(final int reason) {
if (reason < TvInputManager.VIDEO_UNAVAILABLE_REASON_START
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 4171e6d..213e34c 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -312,7 +312,9 @@
// is newly assigned for every createSession request and compared with
// MySessionCreateCallback.this.
mSessionCallback = new MySessionCallback(inputId, channelUri, params);
- mTvInputManager.createSession(inputId, mSessionCallback, mHandler);
+ if (mTvInputManager != null) {
+ mTvInputManager.createSession(inputId, mSessionCallback, mHandler);
+ }
}
}
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index f1e1099..1cf589d 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -62,6 +62,7 @@
jint cryptoErrorNoKey;
jint cryptoErrorKeyExpired;
jint cryptoErrorResourceBusy;
+ jint cryptoErrorInsufficientOutputProtection;
} gCryptoErrorCodes;
static struct CodecActionCodes {
@@ -756,6 +757,9 @@
case ERROR_DRM_RESOURCE_BUSY:
err = gCryptoErrorCodes.cryptoErrorResourceBusy;
break;
+ case ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+ err = gCryptoErrorCodes.cryptoErrorInsufficientOutputProtection;
+ break;
default: /* Other negative DRM error codes go out as is. */
break;
}
@@ -1434,6 +1438,11 @@
gCryptoErrorCodes.cryptoErrorResourceBusy =
env->GetStaticIntField(clazz.get(), field);
+ field = env->GetStaticFieldID(clazz.get(), "ERROR_INSUFFICIENT_OUTPUT_PROTECTION", "I");
+ CHECK(field != NULL);
+ gCryptoErrorCodes.cryptoErrorInsufficientOutputProtection =
+ env->GetStaticIntField(clazz.get(), field);
+
clazz.reset(env->FindClass("android/media/MediaCodec$CodecException"));
CHECK(clazz.get() != NULL);
field = env->GetStaticFieldID(clazz.get(), "ACTION_TRANSIENT", "I");
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index be37aa8..c9cefbd 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -705,11 +705,12 @@
}
static jobjectArray
-android_media_AudioEffect_native_queryEffects(JNIEnv *env, jclass clazz)
+android_media_AudioEffect_native_queryEffects(JNIEnv *env, jclass clazz __unused)
{
effect_descriptor_t desc;
char str[EFFECT_STRING_LEN_MAX];
- uint32_t numEffects = 0;
+ uint32_t totalEffectsCount = 0;
+ uint32_t returnedEffectsCount = 0;
uint32_t i = 0;
jstring jdescType;
jstring jdescUuid;
@@ -717,19 +718,20 @@
jstring jdescName;
jstring jdescImplementor;
jobject jdesc;
+ jobjectArray ret;
- if (AudioEffect::queryNumberEffects(&numEffects) != NO_ERROR) {
+ if (AudioEffect::queryNumberEffects(&totalEffectsCount) != NO_ERROR) {
return NULL;
}
- jobjectArray ret = env->NewObjectArray(numEffects, fields.clazzDesc, NULL);
- if (ret == NULL) {
- return ret;
+ jobjectArray temp = env->NewObjectArray(totalEffectsCount, fields.clazzDesc, NULL);
+ if (temp == NULL) {
+ return temp;
}
- ALOGV("queryEffects() numEffects: %d", numEffects);
+ ALOGV("queryEffects() totalEffectsCount: %d", totalEffectsCount);
- for (i = 0; i < numEffects; i++) {
+ for (i = 0; i < totalEffectsCount; i++) {
if (AudioEffect::queryEffect(i, &desc) != NO_ERROR) {
goto queryEffects_failure;
}
@@ -770,15 +772,26 @@
goto queryEffects_failure;
}
- env->SetObjectArrayElement(ret, i, jdesc);
+ env->SetObjectArrayElement(temp, returnedEffectsCount++, jdesc);
}
+ if (returnedEffectsCount == 0) {
+ goto queryEffects_failure;
+ }
+ ret = env->NewObjectArray(returnedEffectsCount, fields.clazzDesc, NULL);
+ if (ret == NULL) {
+ goto queryEffects_failure;
+ }
+ for (i = 0; i < returnedEffectsCount; i++) {
+ env->SetObjectArrayElement(ret, i, env->GetObjectArrayElement(temp, i));
+ }
+ env->DeleteLocalRef(temp);
return ret;
queryEffects_failure:
- if (ret != NULL) {
- env->DeleteLocalRef(ret);
+ if (temp != NULL) {
+ env->DeleteLocalRef(temp);
}
return NULL;
@@ -787,7 +800,8 @@
static jobjectArray
-android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz, jint audioSession)
+android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz __unused,
+ jint audioSession)
{
// kDefaultNumEffects is a "reasonable" value ensuring that only one query will be enough on
// most devices to get all active audio pre processing on a given session.
@@ -895,7 +909,7 @@
return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
}
-jint JNI_OnLoad(JavaVM* vm, void* reserved)
+jint JNI_OnLoad(JavaVM* vm, void* reserved __unused)
{
JNIEnv* env = NULL;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index f81690a..d72db1d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -116,9 +116,6 @@
* Gather roots from storage providers belonging to given package name.
*/
public void updatePackageAsync(String packageName) {
- // Need at least first load, since we're going to be using previously
- // cached values for non-matching packages.
- waitForFirstLoad();
new UpdateTask(packageName).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@@ -183,6 +180,12 @@
protected Void doInBackground(Void... params) {
final long start = SystemClock.elapsedRealtime();
+ if (mFilterPackage != null) {
+ // Need at least first load, since we're going to be using
+ // previously cached values for non-matching packages.
+ waitForFirstLoad();
+ }
+
mTaskRoots.put(mRecentsRoot.authority, mRecentsRoot);
final ContentResolver resolver = mContext.getContentResolver();
diff --git a/packages/Keyguard/res/drawable-hdpi/kg_bouncer_bg_white.9.png b/packages/Keyguard/res/drawable-hdpi/kg_bouncer_bg_white.9.png
deleted file mode 100644
index cfd5db3..0000000
--- a/packages/Keyguard/res/drawable-hdpi/kg_bouncer_bg_white.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/drawable-mdpi/kg_bouncer_bg_white.9.png b/packages/Keyguard/res/drawable-mdpi/kg_bouncer_bg_white.9.png
deleted file mode 100644
index e3cb6db..0000000
--- a/packages/Keyguard/res/drawable-mdpi/kg_bouncer_bg_white.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/drawable-xhdpi/kg_bouncer_bg_white.9.png b/packages/Keyguard/res/drawable-xhdpi/kg_bouncer_bg_white.9.png
deleted file mode 100644
index b9e30e2..0000000
--- a/packages/Keyguard/res/drawable-xhdpi/kg_bouncer_bg_white.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml b/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
index 8c8ec7a..0c85dab 100644
--- a/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
@@ -36,7 +36,6 @@
<FrameLayout
android:id="@+id/keyguard_bouncer_frame"
- android:background="@drawable/kg_bouncer_bg_white"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
diff --git a/packages/Keyguard/res/layout/keyguard_password_view.xml b/packages/Keyguard/res/layout/keyguard_password_view.xml
index 9e886f2..b7d5d30 100644
--- a/packages/Keyguard/res/layout/keyguard_password_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_password_view.xml
@@ -42,7 +42,6 @@
<!-- Password entry field -->
<FrameLayout
android:id="@+id/keyguard_bouncer_frame"
- android:background="@drawable/kg_bouncer_bg_white"
android:layout_height="wrap_content"
android:layout_width="280dp"
android:layout_gravity="center_horizontal"
diff --git a/packages/Keyguard/res/layout/keyguard_pattern_view.xml b/packages/Keyguard/res/layout/keyguard_pattern_view.xml
index a126465..bd585b5 100644
--- a/packages/Keyguard/res/layout/keyguard_pattern_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_pattern_view.xml
@@ -49,7 +49,6 @@
<FrameLayout
android:id="@+id/keyguard_bouncer_frame"
- android:background="@drawable/kg_bouncer_bg_white"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
diff --git a/packages/Keyguard/res/layout/keyguard_selector_view.xml b/packages/Keyguard/res/layout/keyguard_selector_view.xml
index d3064ed..5330363 100644
--- a/packages/Keyguard/res/layout/keyguard_selector_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_selector_view.xml
@@ -48,8 +48,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
- android:background="@drawable/kg_bouncer_bg_white"/>
+ android:layout_marginRight="16dp"/>
<include layout="@layout/keyguard_glow_pad_container" />
diff --git a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
index 2d20b02..d539856 100644
--- a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
+++ b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
@@ -152,6 +152,11 @@
mKlondikeText.layout(left, top, left + mKlondikeText.getMeasuredWidth(), bottom);
}
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
// Cause a VIRTUAL_KEY vibration
public void doHapticKeyClick() {
if (mEnableHaptics) {
diff --git a/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
index f3ba3a7..6497f46 100644
--- a/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
@@ -145,6 +145,11 @@
}
}
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
private Rect getCharBounds() {
float textHeight = mTextHeightRaw * getResources().getDisplayMetrics().scaledDensity;
mDrawPaint.setTextSize(textHeight);
diff --git a/packages/PrintSpooler/Android.mk b/packages/PrintSpooler/Android.mk
index c4a55d1..27d1b23 100644
--- a/packages/PrintSpooler/Android.mk
+++ b/packages/PrintSpooler/Android.mk
@@ -19,7 +19,9 @@
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SRC_FILES += src/com/android/printspooler/renderer/IPdfRenderer.aidl
+LOCAL_SRC_FILES += \
+ src/com/android/printspooler/renderer/IPdfRenderer.aidl \
+ src/com/android/printspooler/renderer/IPdfEditor.aidl
LOCAL_PACKAGE_NAME := PrintSpooler
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index 9efda2f..adff596 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -54,7 +54,7 @@
</service>
<service
- android:name=".renderer.PdfRendererService"
+ android:name=".renderer.PdfManipulationService"
android:isolatedProcess="true">
</service>
diff --git a/packages/PrintSpooler/res/layout/preview_page.xml b/packages/PrintSpooler/res/layout/preview_page.xml
index df9848b..edce289 100644
--- a/packages/PrintSpooler/res/layout/preview_page.xml
+++ b/packages/PrintSpooler/res/layout/preview_page.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.printspooler.widget.PreviewPageFrame xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/preview_page"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -33,7 +33,8 @@
android:layout_width="fill_parent"
android:layout_height="@dimen/preview_page_footer_height"
android:background="@color/material_grey_500"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:duplicateParentState="true">
<TextView
android:id="@+id/page_number"
@@ -51,9 +52,10 @@
android:layout_marginRight="8dip"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
- android:background="@drawable/page_selector_background">
+ android:background="@drawable/page_selector_background"
+ android:duplicateParentState="true">
</ImageView>
</RelativeLayout>
-</LinearLayout>
+</com.android.printspooler.widget.PreviewPageFrame>
diff --git a/packages/PrintSpooler/res/layout/print_activity.xml b/packages/PrintSpooler/res/layout/print_activity.xml
index 30b96292..6b8aa47 100644
--- a/packages/PrintSpooler/res/layout/print_activity.xml
+++ b/packages/PrintSpooler/res/layout/print_activity.xml
@@ -98,7 +98,7 @@
android:id="@+id/print_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginEnd="16dip"
+ android:layout_marginStart="16dip"
android:elevation="@dimen/preview_controls_elevation"
android:background="@drawable/print_button">
</ImageButton>
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index 27e1d51..ab633ea 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -76,10 +76,36 @@
<!-- Title for the print dialog announced to the user for accessibility. Not shown in the UI. [CHAR LIMIT=none] -->
<string name="print_dialog">Print dialog</string>
- <!-- Template for the message that shows the current page out of the total number of pages -->
+ <!-- Template for the message that shows the current page out of the total number of pages [CHAR LIMIT=none] -->
<string name="current_page_template"><xliff:g id="current_page">%1$d</xliff:g>
/<xliff:g id="page_count">%2$d</xliff:g></string>
+ <!-- Description of the current page - spoken to the user [CHAR LIMIT=none] -->
+ <string name="page_description_template">Page <xliff:g id="current_page" example="1">%1$d</xliff:g>
+ of <xliff:g id="page_count" example="100">%2$d</xliff:g></string>
+
+ <!-- Template for the message to announce the print options summary - spoken to the user. [CHAR LIMIT=none] -->
+ <string name="summary_template">Summary, copies <xliff:g id="copies" example="1">%1$s</xliff:g>,
+ paper size <xliff:g id="paper_size" example="A4">%2$s</xliff:g></string>
+
+ <!-- Description for the handle to expand all print options - spoken to the user. [CHAR LIMIT=none] -->
+ <string name="expand_handle">Expand handle</string>
+
+ <!-- Description for the handle to collapse all print options - spoken to the user. [CHAR LIMIT=none] -->
+ <string name="collapse_handle">Collapse handle</string>
+
+ <!-- Description for the print button - spoken to the user. [CHAR LIMIT=none] -->
+ <string name="print_button">Print</string>
+
+ <!-- Description for the save to PDF button - spoken to the user. [CHAR LIMIT=none] -->
+ <string name="savetopdf_button">Save to PDF</string>
+
+ <!-- Message to announce print options are expanded - spoken to the user. [CHAR LIMIT=none] -->
+ <string name="print_options_expanded">Print options expanded</string>
+
+ <!-- Message to announce print options are collapsed - spoken to the user. [CHAR LIMIT=none] -->
+ <string name="print_options_collapsed">Print options collapsed</string>
+
<!-- Select printer activity -->
<!-- Title for the share action bar menu item. [CHAR LIMIT=20] -->
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
index a581e8a..1d8261b 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
@@ -37,7 +37,7 @@
import android.view.View;
import com.android.internal.annotations.GuardedBy;
import com.android.printspooler.renderer.IPdfRenderer;
-import com.android.printspooler.renderer.PdfRendererService;
+import com.android.printspooler.renderer.PdfManipulationService;
import com.android.printspooler.util.BitmapSerializeUtils;
import dalvik.system.CloseGuard;
import libcore.io.IoUtils;
@@ -490,7 +490,8 @@
new AsyncTask<Void, Void, Integer>() {
@Override
protected void onPreExecute() {
- Intent intent = new Intent(mContext, PdfRendererService.class);
+ Intent intent = new Intent(PdfManipulationService.ACTION_GET_RENDERER);
+ intent.setClass(mContext, PdfManipulationService.class);
mContext.bindService(intent, AsyncRenderer.this, Context.BIND_AUTO_CREATE);
}
@@ -555,7 +556,7 @@
callback.run();
}
}
- }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
}
public void destroy() {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl
new file mode 100644
index 0000000..b450ccb
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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.printspooler.renderer;
+
+import android.os.ParcelFileDescriptor;
+import android.print.PageRange;
+
+/**
+ * Interface for communication with a remote pdf editor.
+ */
+interface IPdfEditor {
+ int openDocument(in ParcelFileDescriptor source);
+ void removePages(in PageRange[] pages);
+ void write(in ParcelFileDescriptor destination);
+ void closeDocument();
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfRenderer.aidl b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfRenderer.aidl
index 1fba2b1..8e595d7 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfRenderer.aidl
+++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfRenderer.aidl
@@ -29,5 +29,4 @@
oneway void renderPage(int pageIndex, int bitmapWidth, int bitmapHeight,
in PrintAttributes attributes, in ParcelFileDescriptor destination);
oneway void closeDocument();
- oneway void writePages(in PageRange[] pages);
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfRendererService.java b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
similarity index 62%
rename from packages/PrintSpooler/src/com/android/printspooler/renderer/PdfRendererService.java
rename to packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
index 4d02c01..62716b2 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfRendererService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
@@ -23,6 +23,7 @@
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Rect;
+import android.graphics.pdf.PdfEditor;
import android.graphics.pdf.PdfRenderer;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -32,15 +33,21 @@
import android.print.PrintAttributes.Margins;
import android.util.Log;
import android.view.View;
+import com.android.printspooler.util.PageRangeUtils;
import libcore.io.IoUtils;
import com.android.printspooler.util.BitmapSerializeUtils;
import java.io.IOException;
/**
- * Service for rendering PDF documents in an isolated process.
+ * Service for manipulation of PDF documents in an isolated process.
*/
-public final class PdfRendererService extends Service {
- private static final String LOG_TAG = "PdfRendererService";
+public final class PdfManipulationService extends Service {
+ public static final String ACTION_GET_RENDERER =
+ "com.android.printspooler.renderer.ACTION_GET_RENDERER";
+ public static final String ACTION_GET_EDITOR =
+ "com.android.printspooler.renderer.ACTION_GET_EDITOR";
+
+ private static final String LOG_TAG = "PdfManipulationService";
private static final boolean DEBUG = false;
private static final int MILS_PER_INCH = 1000;
@@ -48,7 +55,18 @@
@Override
public IBinder onBind(Intent intent) {
- return new PdfRendererImpl();
+ String action = intent.getAction();
+ switch (action) {
+ case ACTION_GET_RENDERER: {
+ return new PdfRendererImpl();
+ }
+ case ACTION_GET_EDITOR: {
+ return new PdfEditorImpl();
+ }
+ default: {
+ throw new IllegalArgumentException("Invalid intent action:" + action);
+ }
+ }
}
private final class PdfRendererImpl extends IPdfRenderer.Stub {
@@ -60,15 +78,17 @@
@Override
public int openDocument(ParcelFileDescriptor source) throws RemoteException {
synchronized (mLock) {
- throwIfOpened();
- if (DEBUG) {
- Log.i(LOG_TAG, "openDocument()");
- }
try {
+ throwIfOpened();
+ if (DEBUG) {
+ Log.i(LOG_TAG, "openDocument()");
+ }
mRenderer = new PdfRenderer(source);
return mRenderer.getPageCount();
- } catch (IOException ioe) {
- throw new RemoteException("Cannot open file");
+ } catch (IOException|IllegalStateException e) {
+ IoUtils.closeQuietly(source);
+ Log.e(LOG_TAG, "Cannot open file", e);
+ throw new RemoteException(e.toString());
}
}
}
@@ -108,7 +128,7 @@
}
matrix.postScale(displayScale, displayScale);
- Configuration configuration = PdfRendererService.this.getResources()
+ Configuration configuration = PdfManipulationService.this.getResources()
.getConfiguration();
if (configuration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
matrix.postTranslate(bitmapWidth - srcWidthPts * displayScale, 0);
@@ -147,24 +167,13 @@
synchronized (mLock) {
throwIfNotOpened();
if (DEBUG) {
- Log.i(LOG_TAG, "openDocument()");
+ Log.i(LOG_TAG, "closeDocument()");
}
mRenderer.close();
mRenderer = null;
}
}
- @Override
- public void writePages(PageRange[] pages) {
- synchronized (mLock) {
- throwIfNotOpened();
- if (DEBUG) {
- Log.i(LOG_TAG, "writePages()");
- }
- // TODO: Implement dropping undesired pages.
- }
- }
-
private Bitmap getBitmapForSize(int width, int height) {
if (mBitmap != null) {
if (mBitmap.getWidth() == width && mBitmap.getHeight() == height) {
@@ -191,6 +200,91 @@
}
}
+ private final class PdfEditorImpl extends IPdfEditor.Stub {
+ private final Object mLock = new Object();
+
+ private PdfEditor mEditor;
+
+ @Override
+ public int openDocument(ParcelFileDescriptor source) throws RemoteException {
+ synchronized (mLock) {
+ try {
+ throwIfOpened();
+ if (DEBUG) {
+ Log.i(LOG_TAG, "openDocument()");
+ }
+ mEditor = new PdfEditor(source);
+ return mEditor.getPageCount();
+ } catch (IOException|IllegalStateException e) {
+ IoUtils.closeQuietly(source);
+ Log.e(LOG_TAG, "Cannot open file", e);
+ throw new RemoteException(e.toString());
+ }
+ }
+ }
+
+ @Override
+ public void removePages(PageRange[] ranges) {
+ synchronized (mLock) {
+ throwIfNotOpened();
+ if (DEBUG) {
+ Log.i(LOG_TAG, "removePages()");
+ }
+
+ ranges = PageRangeUtils.normalize(ranges);
+
+ final int rangeCount = ranges.length;
+ for (int i = rangeCount - 1; i >= 0; i--) {
+ PageRange range = ranges[i];
+ for (int j = range.getEnd(); j >= range.getStart(); j--) {
+ mEditor.removePage(j);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void write(ParcelFileDescriptor destination) throws RemoteException {
+ synchronized (mLock) {
+ try {
+ throwIfNotOpened();
+ if (DEBUG) {
+ Log.i(LOG_TAG, "write()");
+ }
+ mEditor.write(destination);
+ } catch (IOException | IllegalStateException e) {
+ IoUtils.closeQuietly(destination);
+ Log.e(LOG_TAG, "Error writing PDF to file.", e);
+ throw new RemoteException(e.toString());
+ }
+ }
+ }
+
+ @Override
+ public void closeDocument() {
+ synchronized (mLock) {
+ throwIfNotOpened();
+ if (DEBUG) {
+ Log.i(LOG_TAG, "closeDocument()");
+ }
+ mEditor.close();
+ mEditor = null;
+ }
+ }
+
+ private void throwIfOpened() {
+ if (mEditor != null) {
+ throw new IllegalStateException("Already opened");
+ }
+ }
+
+ private void throwIfNotOpened() {
+ if (mEditor == null) {
+ throw new IllegalStateException("Not opened");
+ }
+ }
+ }
+
private static int pointsFromMils(int mils) {
return (int) (((float) mils / MILS_PER_INCH) * POINTS_IN_INCH);
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index ce0b9b6..22a74d6 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -41,6 +41,7 @@
import com.android.printspooler.model.PageContentRepository.PageContentProvider;
import com.android.printspooler.util.PageRangeUtils;
import com.android.printspooler.widget.PageContentView;
+import com.android.printspooler.widget.PreviewPageFrame;
import dalvik.system.CloseGuard;
import java.util.ArrayList;
@@ -94,12 +95,6 @@
private int mDocumentPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN;
private int mSelectedPageCount;
- private float mSelectedPageElevation;
- private float mSelectedPageAlpha;
-
- private float mUnselectedPageElevation;
- private float mUnselectedPageAlpha;
-
private int mPreviewPageMargin;
private int mPreviewPageMinWidth;
private int mPreviewListPadding;
@@ -134,16 +129,6 @@
Context.LAYOUT_INFLATER_SERVICE);
mPageContentRepository = new PageContentRepository(context, this);
- mSelectedPageElevation = mContext.getResources().getDimension(
- R.dimen.selected_page_elevation);
- mSelectedPageAlpha = mContext.getResources().getFraction(
- R.fraction.page_selected_alpha, 1, 1);
-
- mUnselectedPageElevation = mContext.getResources().getDimension(
- R.dimen.unselected_page_elevation);
- mUnselectedPageAlpha = mContext.getResources().getFraction(
- R.fraction.page_unselected_alpha, 1, 1);
-
mPreviewPageMargin = mContext.getResources().getDimensionPixelSize(
R.dimen.preview_page_margin);
@@ -296,7 +281,7 @@
MyViewHolder myHolder = (MyViewHolder) holder;
- View page = holder.itemView;
+ PreviewPageFrame page = (PreviewPageFrame) holder.itemView;
page.setOnClickListener(mPageClickListener);
page.setTag(holder);
@@ -340,20 +325,15 @@
}
content.init(provider, mEmptyState, mMediaSize, mMinMargins);
- View pageSelector = page.findViewById(R.id.page_selector);
- pageSelector.setTag(myHolder);
- pageSelector.setOnClickListener(mPageClickListener);
-
if (mConfirmedPagesInDocument.indexOfKey(pageInDocument) >= 0) {
- pageSelector.setSelected(true);
- page.setTranslationZ(mSelectedPageElevation);
- page.setAlpha(mSelectedPageAlpha);
+ page.setSelected(true, false);
} else {
- pageSelector.setSelected(false);
- page.setTranslationZ(mUnselectedPageElevation);
- page.setAlpha(mUnselectedPageAlpha);
+ page.setSelected(false, false);
}
+ page.setContentDescription(mContext.getString(R.string.page_description_template,
+ pageInDocument + 1, mDocumentPageCount));
+
TextView pageNumberView = (TextView) page.findViewById(R.id.page_number);
String text = mContext.getString(R.string.current_page_template,
pageInDocument + 1, mDocumentPageCount);
@@ -442,7 +422,8 @@
* mPreviewPageMargin);
final int verticalPadding;
- if (mPageContentHeight + mFooterHeight + mPreviewListPadding > availableHeight) {
+ if (mPageContentHeight + mFooterHeight + mPreviewListPadding
+ + 2 * mPreviewPageMargin > availableHeight) {
verticalPadding = Math.max(0,
(availableHeight - mPageContentHeight - mFooterHeight) / 2
- mPreviewPageMargin);
@@ -792,24 +773,20 @@
private final class PageClickListener implements OnClickListener {
@Override
- public void onClick(View page) {
+ public void onClick(View view) {
+ PreviewPageFrame page = (PreviewPageFrame) view;
MyViewHolder holder = (MyViewHolder) page.getTag();
final int pageInAdapter = holder.mPageInAdapter;
final int pageInDocument = computePageIndexInDocument(pageInAdapter);
- View pageSelector = page.findViewById(R.id.page_selector);
if (mConfirmedPagesInDocument.indexOfKey(pageInDocument) < 0) {
mConfirmedPagesInDocument.put(pageInDocument, null);
- pageSelector.setSelected(true);
- page.animate().translationZ(mSelectedPageElevation)
- .alpha(mSelectedPageAlpha);
+ page.setSelected(true, true);
} else {
if (mConfirmedPagesInDocument.size() <= 1) {
return;
}
mConfirmedPagesInDocument.remove(pageInDocument);
- pageSelector.setSelected(false);
- page.animate().translationZ(mUnselectedPageElevation)
- .alpha(mUnselectedPageAlpha);
+ page.setSelected(false, true);
}
}
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 535081f..967efd4 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -23,6 +23,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.ServiceConnection;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
@@ -30,9 +31,12 @@
import android.database.DataSetObserver;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
import android.print.IPrintDocumentAdapter;
import android.print.PageRange;
import android.print.PrintAttributes;
@@ -57,6 +61,7 @@
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
@@ -74,6 +79,8 @@
import com.android.printspooler.model.PrintSpoolerService;
import com.android.printspooler.model.RemotePrintDocument;
import com.android.printspooler.model.RemotePrintDocument.RemotePrintDocumentInfo;
+import com.android.printspooler.renderer.IPdfEditor;
+import com.android.printspooler.renderer.PdfManipulationService;
import com.android.printspooler.util.MediaSizeUtils;
import com.android.printspooler.util.MediaSizeUtils.MediaSizeComparator;
import com.android.printspooler.util.PageRangeUtils;
@@ -81,8 +88,15 @@
import com.android.printspooler.widget.PrintContentView;
import com.android.printspooler.widget.PrintContentView.OptionsStateChangeListener;
import com.android.printspooler.widget.PrintContentView.OptionsStateController;
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -178,6 +192,7 @@
private PrintContentView mOptionsContent;
+ private View mSummaryContainer;
private TextView mSummaryCopies;
private TextView mSummaryPaperSize;
@@ -186,6 +201,7 @@
private ImageView mPrintButton;
private ProgressMessageController mProgressMessageController;
+ private MutexFileProvider mFileProvider;
private MediaSizeComparator mMediaSizeComparator;
@@ -205,8 +221,6 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setState(STATE_CONFIGURING);
-
Bundle extras = getIntent().getExtras();
mPrintJob = extras.getParcelable(PrintManager.EXTRA_PRINT_JOB);
@@ -257,9 +271,8 @@
setTitle(R.string.print_dialog);
setContentView(R.layout.print_activity);
- final MutexFileProvider fileProvider;
try {
- fileProvider = new MutexFileProvider(
+ mFileProvider = new MutexFileProvider(
PrintSpoolerService.generateFileForPrintJob(
PrintActivity.this, mPrintJob.getId()));
} catch (IOException ioe) {
@@ -268,12 +281,13 @@
}
mPrintPreviewController = new PrintPreviewController(PrintActivity.this,
- fileProvider);
+ mFileProvider);
mPrintedDocument = new RemotePrintDocument(PrintActivity.this,
IPrintDocumentAdapter.Stub.asInterface(documentAdapter),
- fileProvider, new RemotePrintDocument.DocumentObserver() {
+ mFileProvider, new RemotePrintDocument.DocumentObserver() {
@Override
public void onDestroy() {
+ setState(STATE_PRINT_CANCELED);
finish();
}
}, PrintActivity.this);
@@ -297,13 +311,17 @@
@Override
public void onPause() {
+ PrintSpoolerService spooler = mSpoolerProvider.getSpooler();
+
if (mState == STATE_INITIALIZING) {
+ if (isFinishing()) {
+ spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_CANCELED, null);
+ }
super.onPause();
return;
}
if (isFinishing()) {
- PrintSpoolerService spooler = mSpoolerProvider.getSpooler();
spooler.updatePrintJobUserConfigurableOptionsNoPersistence(mPrintJob);
switch (mState) {
@@ -329,6 +347,10 @@
mPrinterRegistry.setTrackedPrinter(null);
mPrintPreviewController.destroy();
mSpoolerProvider.destroy();
+
+ if (mPrintedDocument.isUpdating()) {
+ mPrintedDocument.cancel();
+ }
mPrintedDocument.finish();
mPrintedDocument.destroy();
}
@@ -350,7 +372,8 @@
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (mState == STATE_INITIALIZING) {
- return super.onKeyUp(keyCode, event);
+ finish();
+ return true;
}
if (keyCode == KeyEvent.KEYCODE_BACK
@@ -369,7 +392,7 @@
@Override
public void onRequestContentUpdate() {
if (canUpdateDocument()) {
- updateDocument(true, false);
+ updateDocument(false);
}
}
@@ -386,7 +409,7 @@
@Override
public void onActionPerformed() {
if (mState == STATE_UPDATE_FAILED
- && canUpdateDocument() && updateDocument(true, true)) {
+ && canUpdateDocument() && updateDocument(true)) {
ensurePreviewUiShown();
setState(STATE_CONFIGURING);
updateOptionsUi();
@@ -557,14 +580,13 @@
if (resultCode == RESULT_OK && data != null) {
setState(STATE_PRINT_COMPLETED);
updateOptionsUi();
- Uri uri = data.getData();
- mPrintedDocument.writeContent(getContentResolver(), uri);
+ final Uri uri = data.getData();
// Calling finish here does not invoke lifecycle callbacks but we
// update the print job in onPause if finishing, hence post a message.
mDestinationSpinner.post(new Runnable() {
@Override
public void run() {
- finish();
+ shredPagesAndFinish(uri);
}
});
} else if (resultCode == RESULT_CANCELED) {
@@ -708,7 +730,7 @@
// Update the content if needed.
if (canUpdateDocument()) {
- updateDocument(true, false);
+ updateDocument(false);
}
}
@@ -840,7 +862,7 @@
if (mCurrentPrinter == mDestinationSpinnerAdapter.getPdfPrinter()) {
startCreateDocumentActivity();
} else {
- finish();
+ shredPagesAndFinish(null);
}
}
@@ -893,7 +915,7 @@
attributes.setMinMargins(defaults.getMinMargins());
}
- private boolean updateDocument(boolean preview, boolean clearLastError) {
+ private boolean updateDocument(boolean clearLastError) {
if (!clearLastError && mPrintedDocument.hasUpdateError()) {
return false;
}
@@ -902,6 +924,7 @@
mPrintedDocument.clearUpdateError();
}
+ final boolean preview = mState != STATE_PRINT_CONFIRMED;
final PageRange[] pages;
if (preview) {
pages = mPrintPreviewController.getRequestedPages();
@@ -959,7 +982,7 @@
mPrintPreviewController.closeOptions();
if (canUpdateDocument()) {
- updateDocument(false, false);
+ updateDocument(false);
}
if (!mPrintedDocument.isUpdating()) {
@@ -969,6 +992,7 @@
private void bindUi() {
// Summary
+ mSummaryContainer = findViewById(R.id.summary_content);
mSummaryCopies = (TextView) findViewById(R.id.copies_count_summary);
mSummaryPaperSize = (TextView) findViewById(R.id.paper_size_summary);
@@ -1067,15 +1091,7 @@
void updateOptionsUi() {
// Always update the summary.
- if (!TextUtils.isEmpty(mCopiesEditText.getText())) {
- mSummaryCopies.setText(mCopiesEditText.getText());
- }
-
- final int selectedMediaIndex = mMediaSizeSpinner.getSelectedItemPosition();
- if (selectedMediaIndex >= 0) {
- SpinnerItem<MediaSize> mediaItem = mMediaSizeSpinnerAdapter.getItem(selectedMediaIndex);
- mSummaryPaperSize.setText(mediaItem.label);
- }
+ updateSummary();
if (mState == STATE_PRINT_CONFIRMED
|| mState == STATE_PRINT_COMPLETED
@@ -1316,8 +1332,10 @@
// Print
if (mDestinationSpinnerAdapter.getPdfPrinter() != mCurrentPrinter) {
mPrintButton.setImageResource(com.android.internal.R.drawable.ic_print);
+ mPrintButton.setContentDescription(getString(R.string.print_button));
} else {
mPrintButton.setImageResource(R.drawable.ic_menu_savetopdf);
+ mPrintButton.setContentDescription(getString(R.string.savetopdf_button));
}
if ((mRangeOptionsSpinner.getSelectedItemPosition() == 1
&& (TextUtils.isEmpty(mPageRangeEditText.getText()) || hasErrors()))
@@ -1343,6 +1361,28 @@
}
}
+ private void updateSummary() {
+ CharSequence copiesText = null;
+ CharSequence mediaSizeText = null;
+
+ if (!TextUtils.isEmpty(mCopiesEditText.getText())) {
+ copiesText = mCopiesEditText.getText();
+ mSummaryCopies.setText(copiesText);
+ }
+
+ final int selectedMediaIndex = mMediaSizeSpinner.getSelectedItemPosition();
+ if (selectedMediaIndex >= 0) {
+ SpinnerItem<MediaSize> mediaItem = mMediaSizeSpinnerAdapter.getItem(selectedMediaIndex);
+ mediaSizeText = mediaItem.label;
+ mSummaryPaperSize.setText(mediaSizeText);
+ }
+
+ if (!TextUtils.isEmpty(copiesText) && !TextUtils.isEmpty(mediaSizeText)) {
+ String summaryText = getString(R.string.summary_template, copiesText, mediaSizeText);
+ mSummaryContainer.setContentDescription(summaryText);
+ }
+ }
+
private void updatePageRangeOptions(int pageCount) {
ArrayAdapter<SpinnerItem<Integer>> rangeOptionsSpinnerAdapter =
(ArrayAdapter) mRangeOptionsSpinner.getAdapter();
@@ -1433,7 +1473,7 @@
if (mCurrentPrinter.equals(printer)) {
setState(STATE_CONFIGURING);
if (canUpdateDocument()) {
- updateDocument(true, false);
+ updateDocument(false);
}
ensurePreviewUiShown();
updateOptionsUi();
@@ -1492,6 +1532,18 @@
return true;
}
+ private void shredPagesAndFinish(final Uri writeToUri) {
+ new PageShredder(this, mPrintJob, mFileProvider, new Runnable() {
+ @Override
+ public void run() {
+ if (writeToUri != null) {
+ mPrintedDocument.writeContent(getContentResolver(), writeToUri);
+ }
+ finish();
+ }
+ }).shred();
+ }
+
private final class SpinnerItem<T> {
final T value;
final CharSequence label;
@@ -1942,7 +1994,7 @@
|| (becameActive && hasCapab) || (isActive && gotCapab));
if (updateNeeded && canUpdateDocument()) {
- updateDocument(true, false);
+ updateDocument(false);
}
updateOptionsUi();
@@ -2033,7 +2085,7 @@
}
if (canUpdateDocument()) {
- updateDocument(true, false);
+ updateDocument(false);
}
updateOptionsUi();
@@ -2158,7 +2210,7 @@
updateOptionsUi();
if (hadErrors && canUpdateDocument()) {
- updateDocument(true, false);
+ updateDocument(false);
}
}
}
@@ -2198,4 +2250,176 @@
updateOptionsUi();
}
}
+
+ private static final class PageShredder implements ServiceConnection {
+ private static final String TEMP_FILE_PREFIX = "print_job";
+ private static final String TEMP_FILE_EXTENSION = ".pdf";
+
+ private final Context mContext;
+
+ private final MutexFileProvider mFileProvider;
+
+ private final PrintJobInfo mPrintJob;
+
+ private final PageRange[] mPagesToShred;
+
+ private final Runnable mCallback;
+
+ public PageShredder(Context context, PrintJobInfo printJob,
+ MutexFileProvider fileProvider, Runnable callback) {
+ mContext = context;
+ mPrintJob = printJob;
+ mFileProvider = fileProvider;
+ mCallback = callback;
+ mPagesToShred = computePagesToShred(mPrintJob);
+ }
+
+ public void shred() {
+ // If we have only the pages we want, done.
+ if (mPagesToShred.length <= 0) {
+ mCallback.run();
+ return;
+ }
+
+ // Bind to the manipulation service and the work
+ // will be performed upon connection to the service.
+ Intent intent = new Intent(PdfManipulationService.ACTION_GET_EDITOR);
+ intent.setClass(mContext, PdfManipulationService.class);
+ mContext.bindService(intent, this, Context.BIND_AUTO_CREATE);
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ final IPdfEditor editor = IPdfEditor.Stub.asInterface(service);
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ try {
+ // It's OK to access the data members as they are
+ // final and this code is the last one to touch
+ // them as shredding is the very last step, so the
+ // UI is not interactive at this point.
+ shredPages(editor);
+ updatePrintJob();
+ } finally {
+ mContext.unbindService(PageShredder.this);
+ mCallback.run();
+ }
+ return null;
+ }
+ }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ /* do nothing */
+ }
+
+ private void shredPages(IPdfEditor editor) {
+ File tempFile = null;
+ ParcelFileDescriptor src = null;
+ ParcelFileDescriptor dst = null;
+ InputStream in = null;
+ OutputStream out = null;
+ try {
+ File jobFile = mFileProvider.acquireFile(null);
+ src = ParcelFileDescriptor.open(jobFile, ParcelFileDescriptor.MODE_READ_WRITE);
+
+ // Open the document.
+ editor.openDocument(src);
+
+ // We passed the fd over IPC, close this one.
+ src.close();
+
+ // Drop the pages.
+ editor.removePages(mPagesToShred);
+
+ // Write the modified PDF to a temp file.
+ tempFile = File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_EXTENSION,
+ mContext.getCacheDir());
+ dst = ParcelFileDescriptor.open(tempFile, ParcelFileDescriptor.MODE_READ_WRITE);
+ editor.write(dst);
+ dst.close();
+
+ // Close the document.
+ editor.closeDocument();
+
+ // Copy the temp file over the print job file.
+ jobFile.delete();
+ in = new FileInputStream(tempFile);
+ out = new FileOutputStream(jobFile);
+ Streams.copy(in, out);
+ } catch (IOException|RemoteException e) {
+ Log.e(LOG_TAG, "Error dropping pages", e);
+ } finally {
+ IoUtils.closeQuietly(src);
+ IoUtils.closeQuietly(dst);
+ IoUtils.closeQuietly(in);
+ IoUtils.closeQuietly(out);
+ if (tempFile != null) {
+ tempFile.delete();
+ }
+ }
+ }
+
+ private void updatePrintJob() {
+ // Update the print job pages.
+ final int newPageCount = PageRangeUtils.getNormalizedPageCount(
+ mPrintJob.getPages(), 0);
+ mPrintJob.setPages(new PageRange[]{PageRange.ALL_PAGES});
+
+ // Update the print job document info.
+ PrintDocumentInfo oldDocInfo = mPrintJob.getDocumentInfo();
+ PrintDocumentInfo newDocInfo = new PrintDocumentInfo
+ .Builder(oldDocInfo.getName())
+ .setContentType(oldDocInfo.getContentType())
+ .setPageCount(newPageCount)
+ .build();
+ mPrintJob.setDocumentInfo(newDocInfo);
+ }
+
+ private static PageRange[] computePagesToShred(PrintJobInfo printJob) {
+ List<PageRange> rangesToShred = new ArrayList<>();
+ PageRange previousRange = null;
+
+ final int pageCount = printJob.getDocumentInfo().getPageCount();
+
+ PageRange[] printedPages = printJob.getPages();
+ final int rangeCount = printedPages.length;
+ for (int i = 0; i < rangeCount; i++) {
+ PageRange range = PageRangeUtils.asAbsoluteRange(printedPages[i], pageCount);
+
+ if (previousRange == null) {
+ final int startPageIdx = 0;
+ final int endPageIdx = range.getStart() - 1;
+ if (startPageIdx <= endPageIdx) {
+ PageRange removedRange = new PageRange(startPageIdx, endPageIdx);
+ rangesToShred.add(removedRange);
+ }
+ } else {
+ final int startPageIdx = previousRange.getEnd() + 1;
+ final int endPageIdx = range.getStart() - 1;
+ if (startPageIdx <= endPageIdx) {
+ PageRange removedRange = new PageRange(startPageIdx, endPageIdx);
+ rangesToShred.add(removedRange);
+ }
+ }
+
+ if (i == rangeCount - 1) {
+ final int startPageIdx = range.getEnd() + 1;
+ final int endPageIdx = printJob.getDocumentInfo().getPageCount() - 1;
+ if (startPageIdx <= endPageIdx) {
+ PageRange removedRange = new PageRange(startPageIdx, endPageIdx);
+ rangesToShred.add(removedRange);
+ }
+ }
+
+ previousRange = range;
+ }
+
+ PageRange[] result = new PageRange[rangesToShred.size()];
+ rangesToShred.toArray(result);
+ return result;
+ }
+ }
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java
index a25e05e..5d858ca 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java
@@ -185,8 +185,10 @@
public void run() {
// At this point the other end will write to the file, hence
// we have to close it and reopen after the write completes.
- Message operation = mHandler.obtainMessage(MyHandler.MSG_CLOSE);
- mHandler.enqueueOperation(operation);
+ if (mPageAdapter.isOpened()) {
+ Message operation = mHandler.obtainMessage(MyHandler.MSG_CLOSE);
+ mHandler.enqueueOperation(operation);
+ }
}
});
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
index e2ae758..c22c0e2 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
@@ -35,6 +35,7 @@
*/
public class PageContentView extends View
implements PageContentRepository.OnPageContentAvailableCallback {
+
private PageContentProvider mProvider;
private MediaSize mMediaSize;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PreviewPageFrame.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PreviewPageFrame.java
new file mode 100644
index 0000000..feb0316
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PreviewPageFrame.java
@@ -0,0 +1,89 @@
+/*
+ * 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.printspooler.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.CompoundButton;
+import android.widget.LinearLayout;
+import com.android.printspooler.R;
+
+/**
+ * This class represents the frame of page in the print preview list
+ * that contains the page and a footer.
+ */
+public final class PreviewPageFrame extends LinearLayout {
+ private final float mSelectedElevation;
+ private final float mNotSelectedElevation;
+
+ private final float mSelectedPageAlpha;
+ private final float mNotSelectedAlpha;
+
+ public PreviewPageFrame(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mSelectedElevation = mContext.getResources().getDimension(
+ R.dimen.selected_page_elevation);
+ mNotSelectedElevation = mContext.getResources().getDimension(
+ R.dimen.unselected_page_elevation);
+ mSelectedPageAlpha = mContext.getResources().getFraction(
+ R.fraction.page_selected_alpha, 1, 1);
+ mNotSelectedAlpha = mContext.getResources().getFraction(
+ R.fraction.page_unselected_alpha, 1, 1);
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ event.setClassName(CompoundButton.class.getName());
+ event.setChecked(isSelected());
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.setClassName(CompoundButton.class.getName());
+ info.setSelected(false);
+ info.setCheckable(true);
+ info.setChecked(isSelected());
+ }
+
+ public void setSelected(boolean selected, boolean animate) {
+ if (isSelected() == selected) {
+ return;
+ }
+ setSelected(selected);
+ if (selected) {
+ if (animate) {
+ animate().translationZ(mSelectedElevation)
+ .alpha(mSelectedPageAlpha);
+ } else {
+ setTranslationZ(mSelectedElevation);
+ setAlpha(mSelectedPageAlpha);
+ }
+ } else {
+ if (animate) {
+ animate().translationZ(mNotSelectedElevation)
+ .alpha(mNotSelectedAlpha);
+ } else {
+ setTranslationZ(mNotSelectedElevation);
+ setAlpha(mNotSelectedAlpha);
+ }
+ }
+ }
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
index c84b06a..bfcd334 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
@@ -283,8 +283,13 @@
mDynamicContent.layout(left, dynContentTop, right, dynContentBottom);
MarginLayoutParams params = (MarginLayoutParams) mPrintButton.getLayoutParams();
- final int rightMargin = params.rightMargin;
- final int printButtonLeft = right - mPrintButton.getMeasuredWidth() - rightMargin;
+
+ final int printButtonLeft;
+ if (getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
+ printButtonLeft = right - mPrintButton.getMeasuredWidth() - params.getMarginStart();
+ } else {
+ printButtonLeft = left + params.getMarginStart();
+ }
final int printButtonTop = dynContentBottom - mPrintButton.getMeasuredHeight() / 2;
final int printButtonRight = printButtonLeft + mPrintButton.getMeasuredWidth();
final int printButtonBottom = printButtonTop + mPrintButton.getMeasuredHeight();
@@ -336,6 +341,9 @@
if (mOptionsStateChangeListener != null) {
mOptionsStateChangeListener.onOptionsOpened();
}
+ mExpandCollapseHandle.setContentDescription(
+ mContext.getString(R.string.collapse_handle));
+ announceForAccessibility(mContext.getString(R.string.print_options_expanded));
mSummaryContent.setVisibility(View.GONE);
mEmbeddedContentScrim.setOnClickListener(this);
mExpandCollapseIcon.setBackgroundResource(R.drawable.ic_expand_less);
@@ -347,6 +355,9 @@
if (mOptionsStateChangeListener != null) {
mOptionsStateChangeListener.onOptionsClosed();
}
+ mExpandCollapseHandle.setContentDescription(
+ mContext.getString(R.string.expand_handle));
+ announceForAccessibility(mContext.getString(R.string.print_options_collapsed));
if (mMoreOptionsButton.getVisibility() != View.GONE) {
mMoreOptionsButton.setVisibility(View.INVISIBLE);
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintOptionsLayout.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintOptionsLayout.java
index 71f4aa7..7a80a8b 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintOptionsLayout.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintOptionsLayout.java
@@ -89,7 +89,7 @@
columnWidth - childParams.getMarginStart() - childParams.getMarginEnd(),
MeasureSpec.EXACTLY);
} else {
- childWidthMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
+ childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
getPaddingStart() + getPaddingEnd() + width, childParams.width);
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 17593fe..6d08970 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -70,7 +70,7 @@
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 110;
+ private static final int DATABASE_VERSION = 111;
private Context mContext;
private int mUserHandle;
@@ -1770,6 +1770,24 @@
upgradeVersion = 110;
}
+ if (upgradeVersion < 111) {
+ // reset ringer mode, so it doesn't force zen mode to follow
+ if (mUserHandle == UserHandle.USER_OWNER) {
+ db.beginTransaction();
+ SQLiteStatement stmt = null;
+ try {
+ stmt = db.compileStatement("INSERT OR REPLACE INTO global(name,value)"
+ + " VALUES(?,?);");
+ loadSetting(stmt, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ if (stmt != null) stmt.close();
+ }
+ }
+ upgradeVersion = 111;
+ }
+
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
diff --git a/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_bounce.xml b/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_bounce.xml
new file mode 100644
index 0000000..a571cbc
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_bounce.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="normal">
+
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.6"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/accelerate_cubic"
+ android:duration="133"/>
+
+ <translate android:fromYDelta="0" android:toYDelta="10%"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/accelerate_cubic"
+ android:duration="350"/>
+
+ <scale android:fromXScale="1.0" android:toXScale="0.9"
+ android:fromYScale="1.0" android:toYScale="0.9"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:pivotX="50%p" android:pivotY="50%p"
+ android:interpolator="@android:interpolator/fast_out_slow_in"
+ android:duration="350" />
+
+ <alpha android:fromAlpha="1.0" android:toAlpha="1.6666666666"
+ android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
+ android:interpolator="@android:interpolator/decelerate_cubic"
+ android:startOffset="350"
+ android:duration="133"/>
+
+ <translate android:fromYDelta="0%" android:toYDelta="-8.8888888888%"
+ android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
+ android:interpolator="@android:interpolator/decelerate_cubic"
+ android:startOffset="350"
+ android:duration="350"/>
+
+ <scale android:fromXScale="1.0" android:toXScale="1.1111111111"
+ android:fromYScale="1.0" android:toYScale="1.1111111111"
+ android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
+ android:pivotX="50%p" android:pivotY="50%p"
+ android:interpolator="@android:interpolator/decelerate_cubic"
+ android:startOffset="350"
+ android:duration="350" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_source.xml b/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_source.xml
new file mode 100644
index 0000000..f0fd684
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_source.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="normal">
+
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.6"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/accelerate_cubic"
+ android:duration="150"/>
+
+ <scale android:fromXScale="1.0" android:toXScale="0.9"
+ android:fromYScale="1.0" android:toYScale="0.9"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:pivotX="50%p" android:pivotY="50%p"
+ android:interpolator="@android:interpolator/fast_out_slow_in"
+ android:duration="300" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_target.xml b/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_target.xml
new file mode 100644
index 0000000..170ac82
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_target.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="top">
+
+ <translate android:fromYDelta="110%" android:toYDelta="0%"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/decelerate_quint"
+ android:startOffset="50"
+ android:duration="250" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_bounce.xml b/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_bounce.xml
new file mode 100644
index 0000000..46045ac
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_bounce.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="top">
+
+ <translate android:fromYDelta="0%" android:toYDelta="10%"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/decelerate_quint"
+ android:duration="300" />
+
+ <translate android:fromYDelta="10%" android:toYDelta="0%"
+ android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
+ android:interpolator="@android:interpolator/accelerate_quint"
+ android:startOffset="300"
+ android:duration="300" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_source.xml b/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_source.xml
new file mode 100644
index 0000000..ad5341b
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_source.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="top">
+
+ <translate android:fromYDelta="0%" android:toYDelta="110%"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/accelerate_quint"
+ android:duration="300" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_target.xml b/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_target.xml
new file mode 100644
index 0000000..7687f02
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_target.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="normal">
+
+ <alpha android:fromAlpha="0.6" android:toAlpha="1.0"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/decelerate_cubic"
+ android:startOffset="75"
+ android:duration="150"/>
+
+ <scale android:fromXScale="0.9" android:toXScale="1.0"
+ android:fromYScale="0.9" android:toYScale="1.0"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/linear_out_slow_in"
+ android:pivotX="50%p" android:pivotY="50%p"
+ android:startOffset="75"
+ android:duration="225" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/recents_button_bg.xml b/packages/SystemUI/res/drawable/recents_button_bg.xml
index a4cb088..7456365 100644
--- a/packages/SystemUI/res/drawable/recents_button_bg.xml
+++ b/packages/SystemUI/res/drawable/recents_button_bg.xml
@@ -15,4 +15,5 @@
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="?android:attr/colorControlHighlight" />
\ No newline at end of file
+ android:color="#40ffffff">
+</ripple>
diff --git a/packages/SystemUI/res/drawable/stat_sys_vpn_ic.xml b/packages/SystemUI/res/drawable/stat_sys_vpn_ic.xml
new file mode 100644
index 0000000..7ca8c40
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_vpn_ic.xml
@@ -0,0 +1,24 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="17.0dp"
+ android:height="17.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12.700000,10.000000c-0.800000,-2.300000 -3.000000,-4.000000 -5.700000,-4.000000c-3.300000,0.000000 -6.000000,2.700000 -6.000000,6.000000s2.700000,6.000000 6.000000,6.000000c2.600000,0.000000 4.800000,-1.700000 5.700000,-4.000000L17.000000,14.000000l0.000000,4.000000l4.000000,0.000000l0.000000,-4.000000l2.000000,0.000000l0.000000,-4.000000L12.700000,10.000000zM7.000000,14.000000c-1.100000,0.000000 -2.000000,-0.900000 -2.000000,-2.000000c0.000000,-1.100000 0.900000,-2.000000 2.000000,-2.000000s2.000000,0.900000 2.000000,2.000000C9.000000,13.100000 8.100000,14.000000 7.000000,14.000000z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/notification_public_default.xml b/packages/SystemUI/res/layout/notification_public_default.xml
new file mode 100644
index 0000000..acfc4bb
--- /dev/null
+++ b/packages/SystemUI/res/layout/notification_public_default.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+ android:id="@+id/status_bar_latest_event_content"
+ android:layout_width="match_parent"
+ android:layout_height="64dp"
+ internal:layout_minHeight="64dp"
+ internal:layout_maxHeight="64dp"
+ >
+ <ImageView android:id="@+id/icon"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_marginTop="12dp"
+ android:layout_marginStart="12dp"
+ android:layout_marginEnd="12dp"
+ android:scaleType="centerInside"
+ />
+ <DateTimeView android:id="@+id/time"
+ android:textAppearance="@android:style/TextAppearance.Material.Notification.Time"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:layout_alignParentEnd="true"
+ android:layout_alignBaseline="@id/title"
+ android:singleLine="true"
+ android:gravity="center"
+ android:paddingStart="8dp"
+ android:visibility="gone"
+ />
+ <TextView android:id="@+id/title"
+ android:textAppearance="@android:style/TextAppearance.Material.Notification.Title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_toEndOf="@id/icon"
+ android:layout_toStartOf="@id/time"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ />
+ <ImageView android:id="@+id/profile_badge_line3"
+ android:layout_width="@*android:dimen/notification_badge_size"
+ android:layout_height="@*android:dimen/notification_badge_size"
+ android:layout_below="@id/title"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="8dp"
+ android:layout_alignParentEnd="true"
+ android:scaleType="fitCenter"
+ android:visibility="gone"
+ />
+ <TextView android:id="@+id/text"
+ android:textAppearance="@android:style/TextAppearance.Material.Notification"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignStart="@id/title"
+ android:layout_below="@id/title"
+ android:layout_toStartOf="@id/profile_badge_line3"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ />
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index 5cdf819..2eb99ba 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -40,7 +40,6 @@
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:minWidth="132dp"
- android:text="@string/quick_settings_more_settings"
android:textAppearance="@style/TextAppearance.QS.DetailButton"
android:focusable="true" />
@@ -50,9 +49,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="88dp"
- android:text="@string/quick_settings_done"
android:textAppearance="@style/TextAppearance.QS.DetailButton"
android:focusable="true"/>
</LinearLayout>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index 1ef9cad..4b68e77 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -23,6 +23,6 @@
android:textSize="16sp"
android:textColor="#ffffffff"
android:text="@string/recents_empty_message"
- android:fontFamily="sans-serif-light"
+ android:fontFamily="sans-serif"
android:background="#80000000"
android:visibility="gone" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index 347c8a9..5889c55 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -25,6 +25,13 @@
android:gravity="center_vertical"
android:orientation="horizontal"
>
+ <ImageView
+ android:id="@+id/vpn"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:paddingEnd="6dp"
+ android:src="@drawable/stat_sys_vpn_ic"
+ />
<FrameLayout
android:id="@+id/wifi_combo"
android:layout_height="wrap_content"
@@ -36,6 +43,12 @@
android:layout_width="wrap_content"
/>
</FrameLayout>
+ <View
+ android:id="@+id/wifi_signal_spacer"
+ android:layout_width="4dp"
+ android:layout_height="4dp"
+ android:visibility="gone"
+ />
<FrameLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index 6b829e5..e9d86d6 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -52,9 +52,10 @@
android:paddingStart="8dp"
/>
- <include
- layout="@layout/notification_guts"
- android:id="@+id/notification_guts"
+ <ViewStub
+ android:layout="@layout/notification_guts"
+ android:id="@+id/notification_guts_stub"
+ android:inflatedId="@+id/notification_guts"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 215d0f1..a3a3f03 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Ligging deur GPS gestel"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Liggingversoeke aktief"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Verwyder alle kennisgewings."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Instellings"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Die skerm sal outomaties draai."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skerm is in landskapsoriëntasie gesluit."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skerm is in portretoriëntasie gesluit."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Alles"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Laai tans (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> tot vol)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Wissel gebruiker"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Wissel gebruiker, huidige gebruiker <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Wys profiel"</string>
<string name="user_add_user" msgid="5110251524486079492">"Voeg gebruiker by"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Nuwe gebruiker"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 23f9136..f3ea089 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"በ GPS የተዘጋጀ ሥፍራ"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"የአካባቢ ጥያቄዎች ነቅተዋል"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ሁሉንም ማሳወቂያዎች አጽዳ"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"ቅንብሮች"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ማያ ገጽ በራስ ሰር ይዞራል።"</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ማያ ገጽ በወርድ ገፅ አቀማመጥ ተቆልፏል።"</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ማያ ገጽ በቁም ገፅ አቀማመጥ ተቆልፏል።"</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"ሁሉም"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ሃይል በመሙላት ላይ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> እስከሚሞላ ድረስ)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ተጠቃሚ ቀይር"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"መገለጫ አሳይ"</string>
<string name="user_add_user" msgid="5110251524486079492">"ተጠቃሚ አክል"</string>
<string name="user_new_user_name" msgid="426540612051178753">"አዲስ ተጠቃሚ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 6416006..9bfb035 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"تم تعيين الموقع بواسطة GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"طلبات الموقع نشطة"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"محو جميع الإشعارات."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"الإعدادات"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"سيتم تدوير الشاشة تلقائيًا."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"تم تأمين الشاشة في الاتجاه الأفقي."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"تم تأمين الشاشة في الاتجاه العمودي."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"الكل"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"جارٍ الشحن (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> حتى الامتلاء)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"تبديل المستخدم"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"تبديل المستخدم، المستخدم الحالي <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"عرض الملف الشخصي"</string>
<string name="user_add_user" msgid="5110251524486079492">"إضافة مستخدم"</string>
<string name="user_new_user_name" msgid="426540612051178753">"مستخدم جديد"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index ee27bb2..e2f2905 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Местоположението е зададено от GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Активни заявки за местоположение"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Изчистване на всички известия."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Настройки"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екранът ще се завърта автоматично."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Екранът е заключен в хоризонтална ориентация."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Екранът е заключен във вертикална ориентация."</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Всички"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Зарежда се (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до пълно зареждане)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Превключване между потребителите"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Показване на потребителския профил"</string>
<string name="user_add_user" msgid="5110251524486079492">"Добавяне на потребител"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Нов потребител"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 812b19c..8e87c94 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS এর দ্বারা সেট করা অবস্থান"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"অবস্থান অনুরোধ সক্রিয় রয়েছে"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"সমস্ত বিজ্ঞপ্তি সাফ করুন৷"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"সেটিংস"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"স্ক্রীন স্বয়ংক্রিয়ভাবে ঘুরে যাবে৷"</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ভূদৃশ্য সজ্জাতে স্ক্রীন লক করা আছে৷"</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"প্রতিকৃতি সজ্জাতে স্ক্রীন লক করা আছে৷"</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"সমস্ত"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"চার্জ হচ্ছে (পূর্ণ হতে <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> সময় বাকি)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ব্যবহারকারী পাল্টে দিন"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ব্যবহারকারী পাল্টান, বর্তমান ব্যবহারকারী <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"প্রোফাইল দেখান"</string>
<string name="user_add_user" msgid="5110251524486079492">"ব্যবহারকারী জুড়ুন"</string>
<string name="user_new_user_name" msgid="426540612051178753">"নতুন ব্যবহারকারী"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index ee20ce9..1399cd7 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"S\'ha establert la ubicació per GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Sol·licituds d\'ubicació actives"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Esborra totes les notificacions."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Configuració"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girarà automàticament."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"La pantalla està bloquejada en orientació horitzontal."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"La pantalla està bloquejada en orientació vertical."</string>
@@ -306,6 +309,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Totes"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Carregant (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> per completar la càrrega)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Canvia d\'usuari"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Canvia l\'usuari. Usuari actual: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Mostra el perfil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Afegeix un usuari"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Usuari nou"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 89911ad..00ee3e1 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -44,7 +44,7 @@
<string name="battery_saver_start_action" msgid="5576697451677486320">"Zapnout úsporu baterie"</string>
<string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Nastavení"</string>
<string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
- <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Režim V letadle"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Režim Letadlo"</string>
<string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Autom. otočení obrazovky"</string>
<string name="status_bar_settings_mute_label" msgid="554682549917429396">"ZTLUM."</string>
<string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
@@ -144,8 +144,8 @@
<string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
<string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="8274017118472455155">"Žádná SIM karta."</string>
- <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Tethering přes Bluetooth."</string>
- <string name="accessibility_airplane_mode" msgid="834748999790763092">"Režim V letadle."</string>
+ <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Sdílené připojení přes Bluetooth."</string>
+ <string name="accessibility_airplane_mode" msgid="834748999790763092">"Režim Letadlo."</string>
<!-- String.format failed for translation -->
<!-- no translation found for accessibility_battery_level (7451474187113371965) -->
<skip />
@@ -174,10 +174,10 @@
<string name="accessibility_quick_settings_wifi_changed_on" msgid="6440117170789528622">"Připojení Wi-Fi je zapnuto."</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobil: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
<string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Baterie: <xliff:g id="STATE">%s</xliff:g>."</string>
- <string name="accessibility_quick_settings_airplane_off" msgid="7786329360056634412">"Režim V letadle je vypnutý."</string>
- <string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"Režim V letadle je zapnutý."</string>
- <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"Režim V letadle je vypnutý."</string>
- <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Režim V letadle je zapnutý."</string>
+ <string name="accessibility_quick_settings_airplane_off" msgid="7786329360056634412">"Režim Letadlo je vypnutý."</string>
+ <string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"Režim Letadlo je zapnutý."</string>
+ <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"Režim Letadlo je vypnutý."</string>
+ <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Režim Letadlo je zapnutý."</string>
<string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"Rozhraní Bluetooth je vypnuto."</string>
<string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"Rozhraní Bluetooth je zapnuto."</string>
<string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"Probíhá připojování rozhraní Bluetooth."</string>
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Poloha nastavena pomocí systému GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aktivní žádosti o polohu"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazat všechna oznámení."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Nastavení"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Obrazovka se automaticky otočí."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Obrazovka je uzamčena v orientaci na šířku."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Obrazovka je uzamčena v orientaci na výšku."</string>
@@ -224,7 +227,7 @@
<string name="dessert_case" msgid="1295161776223959221">"Pult se sladkostmi"</string>
<string name="start_dreams" msgid="7219575858348719790">"Spořič obrazovky"</string>
<string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
- <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Režim V letadle"</string>
+ <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Režim Letadlo"</string>
<string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Nabíjení, <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
<string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Nabito"</string>
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
@@ -306,6 +309,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Vše"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Nabíjení (plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Přepnout uživatele"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Přepnout uživatele, aktuální uživatel: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Zobrazit profil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Přidat uživatele"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Nový uživatel"</string>
@@ -324,7 +328,7 @@
<item quantity="other" msgid="6924190729213550991">"Na %d min"</item>
</plurals>
<plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Na jednu hodinu"</item>
+ <item quantity="one" msgid="3480040795582254384">"Na 1 h"</item>
<item quantity="other" msgid="5408537517529822157">"Na %d h"</item>
</plurals>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Režim Úspora baterie je zapnutý."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index a4b36ed..50866d7 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Placeringen er angivet ved hjælp af GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aktive placeringsanmodninger"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Ryd alle underretninger."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Indstillinger"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skærmen roterer automatisk."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skærmen er nu låst i liggende retning."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skærmen er nu låst i stående retning."</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Opladning (fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Skift bruger"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Vis profil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Tilføj bruger"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Ny bruger"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 4675c8f..b9e39e1 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Standort durch GPS festgelegt"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Standortanfragen aktiv"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Alle Benachrichtigungen löschen"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Einstellungen"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Bildschirm wird automatisch gedreht."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Bildschirm bleibt im Querformat."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Bildschirm bleibt im Hochformat."</string>
@@ -306,6 +309,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Wird aufgeladen (voll in <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Nutzer wechseln"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Nutzer wechseln. Aktueller Nutzer: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Profil öffnen"</string>
<string name="user_add_user" msgid="5110251524486079492">"Nutzer hinzufügen"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Neuer Nutzer"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 02f0ca0..56c41a2 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Ρύθμιση τοποθεσίας με GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Τα αιτήματα τοποθεσίας έχουν ενεργοποιηθεί"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Εκκαθάριση όλων των ειδοποιήσεων."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Ρυθμίσεις"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Θα γίνεται αυτόματη περιστροφή της οθόνης."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Η οθόνη έχει κλειδωθεί σε οριζόντιο προσανατολισμό."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Η οθόνη έχει κλειδωθεί σε κατακόρυφο προσανατολισμό."</string>
@@ -306,6 +309,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Όλα"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Φόρτιση (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> για πλήρη φόρτιση)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Εναλλαγή χρήστη"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Εναλλαγή χρήστη, τρέχων χρήστης <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Εμφάνιση προφίλ"</string>
<string name="user_add_user" msgid="5110251524486079492">"Προσθήκη χρήστη"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Νέος χρήστης"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index ffbdcb9..a4abdca 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -212,7 +212,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Location set by GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Location requests active"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Clear all notifications."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Settings"</string>
+ <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Notification settings"</string>
+ <string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> settings"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Screen will rotate automatically."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Screen is locked in landscape orientation."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Screen is locked in portrait orientation."</string>
@@ -304,6 +305,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"All"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Switch user"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Switch user, current user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Show profile"</string>
<string name="user_add_user" msgid="5110251524486079492">"Add user"</string>
<string name="user_new_user_name" msgid="426540612051178753">"New user"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index ffbdcb9..a4abdca 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -212,7 +212,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Location set by GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Location requests active"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Clear all notifications."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Settings"</string>
+ <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Notification settings"</string>
+ <string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> settings"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Screen will rotate automatically."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Screen is locked in landscape orientation."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Screen is locked in portrait orientation."</string>
@@ -304,6 +305,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"All"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Switch user"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Switch user, current user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Show profile"</string>
<string name="user_add_user" msgid="5110251524486079492">"Add user"</string>
<string name="user_new_user_name" msgid="426540612051178753">"New user"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 9b1f2af..8a71771 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"La ubicación se estableció por GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Solicitudes de ubicación activas"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Eliminar todas las notificaciones"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Configuración"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girará automáticamente."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"La pantalla está bloqueada en modo horizontal."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"La pantalla está bloqueada en modo vertical."</string>
@@ -306,6 +309,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Todo"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Cargando (faltan <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para completar)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Cambiar usuario"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Mostrar perfil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Agregar usuario"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Usuario nuevo"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 03fde10..c3feb3a 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Ubicación definida por GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Solicitudes de ubicación activas"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Borrar todas las notificaciones"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Ajustes"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girará automáticamente."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"La pantalla está bloqueada en modo horizontal."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"La pantalla está bloqueada en modo vertical."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Todo"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Cargando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hasta completar)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Cambiar de usuario"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Cambiar de usuario (usuario actual <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Mostrar perfil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Añadir usuario"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Nuevo usuario"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 951757a..94e67fad 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS-i määratud asukoht"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Asukoha taotlused on aktiivsed"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Kustuta kõik teatised."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Seaded"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekraani pööramine toimub automaatselt."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ekraan on lukustatud horisontaalsuunas."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ekraan on lukustatud vertikaalsuunas."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Kõik"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Laadimine (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>, kuni seade on täis)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Kasutaja vahetamine"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Kasutaja vahetamine, praegune kasutaja: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Kuva profiil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Kasutaja lisamine"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Uus kasutaja"</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 5226b9c..7ff9297 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Kokapena GPS bidez ezarri da"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aplikazioen kokapen-eskaerak aktibo daude"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Garbitu jakinarazpen guztiak."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Ezarpenak"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Pantaila automatikoki biratuko da."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Pantaila horizontalki blokeatuta dago."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Pantaila bertikalki blokeatuta dago."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Guztiak"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Kargatzen (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> guztiz kargatu arte)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Aldatu erabiltzailea"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Aldatu erabiltzailez. <xliff:g id="CURRENT_USER_NAME">%s</xliff:g> da saioa hasita duena."</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Erakutsi profila"</string>
<string name="user_add_user" msgid="5110251524486079492">"Gehitu erabiltzailea"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Erabiltzaile berria"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 9f63781..4cc5882 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"مکان تنظیم شده توسط GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"درخواستهای موقعیت مکانی فعال است"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"پاک کردن تمام اعلانها"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"تنظیمات"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"صفحه به صورت خودکار میچرخد."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"صفحه اکنون در جهت افقی قفل است."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"صفحه اکنون در جهت عمودی قفل است."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"همه"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"در حال شارژ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> تا شارژ کامل)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"تغییر کاربر"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"تعویض کاربر، کاربر کنونی <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"نمایش نمایه"</string>
<string name="user_add_user" msgid="5110251524486079492">"افزودن کاربر"</string>
<string name="user_new_user_name" msgid="426540612051178753">"کاربر جدید"</string>
@@ -328,7 +332,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"ذخیره کننده باتری روشن است."</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"عملکرد و اطلاعات پسزمینه را کاهش میدهد"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"خاموش کردن ذخیرهکننده باتری"</string>
- <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>٪٪"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
<string name="notification_hidden_text" msgid="1135169301897151909">"محتواها پنهان هستند"</string>
<string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> شروع به ضبط هر چیزی میکند که در صفحهنمایش شما نمایش داده میشود."</string>
<string name="media_projection_remember_text" msgid="3103510882172746752">"دوباره نشان داده نشود"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index e2dd843b..0b29e49 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Sijainti määritetty GPS:n avulla"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Sijaintipyynnöt aktiiviset"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Tyhjennä kaikki ilmoitukset."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Asetukset"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ruutu kääntyy automaattisesti."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ruutu on lukittu vaakasuuntaan."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ruutu on lukittu pystysuuntaan."</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Kaikki"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Ladataan (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kunnes täynnä)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Vaihda käyttäjää"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Näytä profiili"</string>
<string name="user_add_user" msgid="5110251524486079492">"Lisää käyttäjä"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Uusi käyttäjä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 71f042d..7147727 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Position définie par GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Demandes de localisation actives"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Supprimer toutes les notifications"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Paramètres"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"L\'écran pivote automatiquement."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"L\'écran est verrouillé en mode paysage."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"L\'écran est verrouillé en mode portrait."</string>
@@ -306,6 +309,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Tous"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charge en cours... (chargée à 100 % dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Changer d\'utilisateur"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Afficher le profil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Ajouter un utilisateur"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Nouvel utilisateur"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index a85b209..1020c27 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Position définie par GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Demandes de localisation actives"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Supprimer toutes les notifications"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Paramètres"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"L\'écran pivote automatiquement."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"L\'écran est verrouillé en mode paysage."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"L\'écran est verrouillé en mode portrait."</string>
@@ -306,6 +309,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Toutes"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charge en cours… (chargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Changer d\'utilisateur"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Changer d\'utilisateur (utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Afficher le profil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Ajouter un utilisateur"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Nouvel utilisateur"</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 3d7f2a1..ad48160 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Localización establecida polo GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Solicitudes de localización activas"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Eliminar todas as notificacións."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Configuración"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A pantalla xirará automaticamente."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"A pantalla está bloqueada en orientación horizontal."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"A pantalla está bloqueada en orientación vertical."</string>
@@ -306,6 +309,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Sempre"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Cargando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para finalizar a carga)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Cambiar usuario"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Mostrar perfil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Engadir usuario"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Novo usuario"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 99c5153..a1df1e0 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS द्वारा सेट किया गया स्थान"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"स्थान अनुरोध सक्रिय"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"सभी सूचनाएं साफ़ करें."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"सेटिंग"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"स्क्रीन स्वचालित रूप से घूमेगी."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"स्क्रीन लैंडस्केप अभिविन्यास में लॉक है."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"स्क्रीन पोर्ट्रेट अभिविन्यास में लॉक है."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"सभी"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"चार्ज हो रहा है (पूर्ण होने में <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> शेष)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"उपयोगकर्ता स्विच करें"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"उपयोगकर्ता स्विच करें, वर्तमान उपयोगकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"प्रोफ़ाइल दिखाएं"</string>
<string name="user_add_user" msgid="5110251524486079492">"उपयोगकर्ता जोड़ें"</string>
<string name="user_new_user_name" msgid="426540612051178753">"नया उपयोगकर्ता"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index a35fed5..247bcec 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokaciju utvrdio GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Zahtjevi za lokaciju aktivni su"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Brisanje svih obavijesti."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Postavke"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Zaslon će se automatski zakrenuti."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Zaslon je zaključan u pejzažnoj orijentaciji."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Zaslon je zaključan u portretnoj orijentaciji."</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Sve"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Punjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napunjenosti)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Promjena korisnika"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Prikaz profila"</string>
<string name="user_add_user" msgid="5110251524486079492">"Dodavanje korisnika"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Novi korisnik"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 4507754..42dc82d 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"A GPS beállította a helyet"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aktív helylekérések"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Minden értesítés törlése"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Beállítások"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A képernyő automatikusan forogni fog."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"A képernyő zárolva van fekvő tájolásban."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"A képernyő zárolva van álló tájolásban."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Összes"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Töltés (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> a teljes töltöttségig)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Felhasználóváltás"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Felhasználóváltás (a jelenlegi felhasználó: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Profil megjelenítése"</string>
<string name="user_add_user" msgid="5110251524486079492">"Felhasználó hozzáadása"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Új felhasználó"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index af20b98..1a96a43 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Տեղադրությունը կարգավորվել է GPS-ի կողմից"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Տեղադրության հարցումներն ակտիվ են"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Մաքրել բոլոր ծանուցումները:"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Կարգավորումներ"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Էկրանը ինքնուրույն կպտտվի:"</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Էկրանը կողպված է հորիզոնական դիրքավորման մեջ:"</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Էկրանը կողպված է ուղղաձիգ դիրքավորմամբ:"</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Բոլորը"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Լիցքավորում (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> մինչև լրիվ լիցքավորումը)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Անջատել օգտվողին"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Ցույց տալ դիտարկումը"</string>
<string name="user_add_user" msgid="5110251524486079492">"Ավելացնել օգտվող"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Նոր օգտվող"</string>
@@ -336,10 +341,10 @@
<string name="media_projection_action_text" msgid="8470872969457985954">"Մեկնարկել հիմա"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Ծանուցումներ չկան"</string>
<string name="device_owned_footer" msgid="3802752663326030053">"Սարքը կարող է վերահսկվել"</string>
- <string name="profile_owned_footer" msgid="8021888108553696069">"Պրոֆիլը կարող է մշտադիտարկվել"</string>
+ <string name="profile_owned_footer" msgid="8021888108553696069">"Պրոֆիլը կարող է վերահսկվել"</string>
<string name="vpn_footer" msgid="2388611096129106812">"Ցանցը կարող է վերահսկվել"</string>
<string name="monitoring_title_device_owned" msgid="7121079311903859610">"Սարքի մշտադիտարկում"</string>
- <string name="monitoring_title_profile_owned" msgid="6790109874733501487">"Պրոֆիլի մշտադիտարկում"</string>
+ <string name="monitoring_title_profile_owned" msgid="6790109874733501487">"Պրոֆիլի վերահսկում"</string>
<string name="monitoring_title" msgid="169206259253048106">"Ցանցի մշտադիտարկում"</string>
<string name="disable_vpn" msgid="4435534311510272506">"Անջատել VPN-ը"</string>
<string name="disconnect_vpn" msgid="1324915059568548655">"Անջատել VPN-ը"</string>
@@ -348,15 +353,15 @@
<string name="monitoring_description_legacy_vpn" msgid="4740349017929725435">"Դուք միացած եք VPN-ին («<xliff:g id="APPLICATION">%1$s</xliff:g>»):\n\nՁեզ VPN ծառայություն մատուցողը կարող է վերահսկել ձեր սարքի և ցանցի գործունեությունը, այդ թվում` նամակները, ծրագրերը և վստահելի կայքերը:"</string>
<string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Այս սարքը կառավարիչն է՝\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nՁեր ադմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը, այդ թվում՝ նամակները, ծրագրերը և վստահելի կայքերը: Լրացուցիչ տեղեկությունների համար դիմեք ձեր ադմինիստրատորին:\n\n Բացի այդ, դուք «<xliff:g id="APPLICATION">%2$s</xliff:g>» ծրագրին թույլատրել եք ստեղծել VPN կապ: Այդ ծրագիրը նույնպես կարող է վերահսկել ձեր ցանցային գործունեությունը:"</string>
<string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Այս սարքը կառավարիչն է՝\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nՁեր ադմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը, այդ թվում՝ նամակները, ծրագրերը և վստահելի կայքերը: Լրացուցիչ տեղեկությունների համար դիմեք ձեր ադմինիստրատորին:\n\nԲացի այդ, դուք միացած եք VPN-ին («<xliff:g id="APPLICATION">%2$s</xliff:g>»): Ձեզ VPN ծառայություն մատուցողը նույնպես կարող է վերահսկել ցանցային գործունեությունը:"</string>
- <string name="monitoring_description_profile_owned" msgid="2370062794285691713">"Այս պրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nՁեր ադմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը, այդ թվում՝ նամակները, ծրագրերը և վստահելի կայքերը:\n\nԼրացուցիչ տեղեկությունների համար դիմեք ձեր ադմինիստրատորին:"</string>
- <string name="monitoring_description_device_and_profile_owned" msgid="8685301493845456293">"Սարքի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nՊրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nՁեր ադմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը՝ նամակները, ծրագրերը և վստահելի կայքերը:\n\nՀավելյալ տեղեկությունների համար դիմեք ադմինիստրատորին:"</string>
- <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"Այս պրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nԱդմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը, այդ թվում՝ նամակները, ծրագրերը և վստահելի կայքերը: Լրացուցիչ տեղեկությունների համար դիմեք ադմինիստրատորին:\n\nԴուք նաև «<xliff:g id="APPLICATION">%2$s</xliff:g>» ծրագրին թույլատրել եք ստեղծել VPN: Այն նույնպես կարող է վերահսկել ցանցային գործունեությունը:"</string>
- <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"Այս պրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nԱդմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը՝ նամակները, ծրագրերը և վստահելի կայքերը: Լրացուցիչ տեղեկությունների համար դիմեք ձեր ադմինիստրատորին:\n\nԴուք նաև միացած եք VPN-ին («<xliff:g id="APPLICATION">%2$s</xliff:g>»): VPN ծառայություն մատուցողը նույնպես կարող է վերահսկել ցանցային գործունեությունը:"</string>
- <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Սարքի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nՊրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nԱդմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը՝ նամակները, ծրագրերը և վստահելի կայքերը: Լրացուցիչ տեղեկությունների համար դիմեք ադմինիստրատորին:\n\nԴուք նաև «<xliff:g id="APPLICATION">%3$s</xliff:g>»-ին թույլատրել եք ստեղծել VPN: Այն նույնպես կարող է վերահսկել ցանցային գործունեությունը:"</string>
- <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Սարքի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nՊրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nԱդմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը՝ նամակները, ծրագրերը և վստահելի կայքերը: Այլ տեղեկությունների համար դիմեք ադմինիստրատորին:\n\nԴուք նաև միացած եք VPN-ին («<xliff:g id="APPLICATION">%3$s</xliff:g>»): VPN ծառայություն մատուցողը նույնպես կարող է վերահսկել ցանցային գործունեությունը:"</string>
+ <string name="monitoring_description_profile_owned" msgid="2370062794285691713">"Այս պրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nԱդմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը, այդ թվում՝ նամակները, հավելվածները և վստահելի կայքերը:\n\nԼրացուցիչ տեղեկությունների համար դիմեք ձեր ադմինիստրատորին:"</string>
+ <string name="monitoring_description_device_and_profile_owned" msgid="8685301493845456293">"Սարքի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nՊրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nԱդմինիստրատորը կարող է վերահսկել ձեր սարքի և ցանցի գործունեությունը՝ նամակները, հավելվածները և վստահելի կայքերը:\n\nՀավելյալ տեղեկությունների համար դիմեք ադմինիստրատորին:"</string>
+ <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"Այս պրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nԱդմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը, այդ թվում՝ նամակները, հավելվածները և վստահելի կայքերը: Լրացուցիչ տեղեկությունների համար դիմեք ադմինիստրատորին:\n\nԴուք նաև «<xliff:g id="APPLICATION">%2$s</xliff:g>» հավելվածին թույլատրել եք ստեղծել VPN: Այն նույնպես կարող է վերահսկել ցանցային գործունեությունը:"</string>
+ <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"Այս պրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nԱդմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը՝ նամակները, հավելվածները և վստահելի կայքերը: Լրացուցիչ տեղեկությունների համար դիմեք ձեր ադմինիստրատորին:\n\nԴուք նաև միացած եք VPN-ին («<xliff:g id="APPLICATION">%2$s</xliff:g>»): VPN ծառայություն մատուցողը նույնպես կարող է վերահսկել ցանցային գործունեությունը:"</string>
+ <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Սարքի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nՊրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nԱդմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը՝ նամակները, հավելվածները և վստահելի կայքերը: Լրացուցիչ տեղեկությունների համար դիմեք ադմինիստրատորին:\n\nԴուք նաև «<xliff:g id="APPLICATION">%3$s</xliff:g>»-ին թույլատրել եք ստեղծել VPN: Այն նույնպես կարող է վերահսկել ցանցային գործունեությունը:"</string>
+ <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Սարքի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nՊրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nԱդմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը՝ նամակները, հավելվածները և վստահելի կայքերը: Այլ տեղեկությունների համար դիմեք ադմինիստրատորին:\n\nԴուք նաև միացած եք VPN-ին («<xliff:g id="APPLICATION">%3$s</xliff:g>»): VPN ծառայություն մատուցողը նույնպես կարող է վերահսկել ցանցային գործունեությունը:"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Սարքը կմնա արգելափակված՝ մինչև ձեռքով չբացեք"</string>
- <string name="hidden_notifications_title" msgid="7139628534207443290">"Ստանալ ծանուցումներն ավելի արագ"</string>
- <string name="hidden_notifications_text" msgid="2326409389088668981">"Տեսեք դրանք՝ մինչև ապակողպելը"</string>
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Ավելի արագ ստացեք ծանուցումները"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"Տեսեք դրանք մինչև ապակողպելը"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ոչ, շնորհակալություն"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Կարգավորել"</string>
<string name="muted_by" msgid="6147073845094180001">"Համրեցվել է <xliff:g id="THIRD_PARTY">%1$s</xliff:g>-ի կողմից"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 6c3502b..910b500 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasi yang disetel oleh GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Permintaan lokasi aktif"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Menghapus semua pemberitahuan."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Setelan"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Layar akan diputar secara otomatis."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Layar dikunci dalam orientasi lanskap."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Layar dikunci dalam orientasi potret."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Semua"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Mengisi daya (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hingga penuh)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Beralih pengguna"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Ganti pengguna, pengguna saat ini <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Tampilkan profil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Tambahkan pengguna"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Pengguna baru"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index f98be45..73931db 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Staðsetning valin með GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Staðsetningarbeiðnir virkar"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Hreinsa allar tilkynningar."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Stillingar"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skjárinn snýst sjálfkrafa."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skjárinn er læstur í langsniði."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skjárinn er læstur í skammsniði."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Allar"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Í hleðslu (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> fram að fullri hleðslu)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Skipta um notanda"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Skipta um notanda; núverandi notandi <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Sýna snið"</string>
<string name="user_add_user" msgid="5110251524486079492">"Bæta notanda við"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Nýr notandi"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 39dc3ee..f1f3c97 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Posizione stabilita dal GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Richieste di accesso alla posizione attive"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Cancella tutte le notifiche."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Impostazioni"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Lo schermo ruoterà automaticamente."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Lo schermo è bloccato in orientamento orizzontale."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Lo schermo è bloccato in orientamento verticale."</string>
@@ -268,7 +271,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifiche"</string>
- <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flashlight"</string>
+ <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Torcia"</string>
<string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Rete dati"</string>
<string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Utilizzo dati"</string>
<string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dati rimanenti"</string>
@@ -300,18 +303,19 @@
<string name="keyguard_unlock" msgid="8043466894212841998">"Scorri verso l\'alto per sbloccare"</string>
<string name="phone_hint" msgid="3101468054914424646">"Scorri verso destra per accedere al telefono"</string>
<string name="camera_hint" msgid="5241441720959174226">"Scorri verso sinistra per accedere alla fotocamera"</string>
- <string name="zen_mode_forever" msgid="4316804956488785559">"In modo indefinito"</string>
- <string name="interruption_level_none" msgid="3831278883136066646">"Nessuno"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Sempre"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Nessuna"</string>
<string name="interruption_level_priority" msgid="6517366750688942030">"Priorità"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Tutti"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Tutte"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"In carica (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> al termine)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Cambio utente"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Cambia utente, utente corrente <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Mostra profilo"</string>
<string name="user_add_user" msgid="5110251524486079492">"Aggiungi utente"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Nuovo utente"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Ospite"</string>
<string name="guest_new_guest" msgid="600537543078847803">"Aggiungi ospite"</string>
- <string name="guest_exit_guest" msgid="7187359342030096885">"Rimuovi invitato"</string>
+ <string name="guest_exit_guest" msgid="7187359342030096885">"Rimuovi ospite"</string>
<string name="guest_exit_guest_dialog_title" msgid="8480693520521766688">"Rimuovere l\'ospite?"</string>
<string name="guest_exit_guest_dialog_message" msgid="4155503224769676625">"Tutte le app e i dati di questa sessione verranno eliminati."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7402231963862520531">"Rimuovi"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 74d1bcf..5582418 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"מיקום מוגדר על ידי GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"בקשות מיקום פעילות"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"נקה את כל ההתראות."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"הגדרות"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"המסך יסתובב באופן אוטומטי."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"המסך נעול כעת לרוחב."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"המסך נעול כעת לאורך."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"הכל"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"טוען (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> עד לסיום)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"החלפת משתמש"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"החלף משתמש. המשתמש הנוכחי הוא <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"הצג פרופיל"</string>
<string name="user_add_user" msgid="5110251524486079492">"הוסף משתמש"</string>
<string name="user_new_user_name" msgid="426540612051178753">"משתמש חדש"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index f1aa72c..0493b28 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPSにより現在地が設定されました"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"現在地リクエストがアクティブ"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"通知をすべて消去。"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"設定"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"画面は自動的に回転します。"</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"画面は横向きにロックされています。"</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"画面は縦向きにロックされています。"</string>
@@ -306,6 +309,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"すべて"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"充電中(フル充電まで<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ユーザーを切り替える"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"プロフィールを表示"</string>
<string name="user_add_user" msgid="5110251524486079492">"ユーザーを追加"</string>
<string name="user_new_user_name" msgid="426540612051178753">"新しいユーザー"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index e7b272b..e73c13e 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS-ით დადგენილი მდებარეობა"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"მდებარეობის მოთხოვნები აქტიურია"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ყველა შეტყობინების წაშლა"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"პარამეტრები"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ეკრანი შეტრიალდება ავტომატურად."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ეკრანი დაბლოკილია თარაზულ ორიენტაციაში"</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ეკრანი დაბლოკილია პორტრეტის ორიენტაციაში."</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"ყველა"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>-ის შეცვლა დასრულებამდე)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"მომხმარებლის გადართვა"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"პროფილის ჩვენება"</string>
<string name="user_add_user" msgid="5110251524486079492">"მომხმარებლის დამატება"</string>
<string name="user_new_user_name" msgid="426540612051178753">"ახალი მომხმარებელი"</string>
@@ -350,10 +355,10 @@
<string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"ამ მოწყობილობის მმართველი არის:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტების, აპების და უსაფრთხო საიტების. დამატებითი ინფორმაციისათვის, დაუკავშირდით თქვენს ადმინისტრატორს.\n\nასევე, თქვენ დაკავშირებული ხართ VPN-თან („<xliff:g id="APPLICATION">%2$s</xliff:g>“). თქვენს VPN სერვისის პროვაიდერს ასევე შეუძლია თქვენი ქსელის აქტივობის მონიტორინგი."</string>
<string name="monitoring_description_profile_owned" msgid="2370062794285691713">"ამ პროფილის მმართველია:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი მოწყობილობისა და ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტის, აპების და უსაფრთხო საიტების.\n\nდამატებითი ინფორმაციისათვის, დაუკავშირდით ადმინისტრატორს."</string>
<string name="monitoring_description_device_and_profile_owned" msgid="8685301493845456293">"ამ მოწყობილობის მმართველია:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nთქვენი პროფილის მმართველია:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი მოწყობილობისა და ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტის, აპების და უსაფრთხო საიტების.\n\nდამატებითი ინფორმაციისათვის, დაუკავშირდით ადმინისტრატორს."</string>
- <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"ამ პროფილის მმართველია:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი მოწყობილობისა და ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტის, აპების და უსაფრთხო საიტების. დამატებითი ინფორმაციისათვის, დაუკავშირდით ადმინისტრატორს.\n\nასევე, თქვენ მიანიჭეთ „<xliff:g id="APPLICATION">%2$s</xliff:g>“-ს VPN კავშირის დაყენება. ამ აპს ასევე შეუძლია ქსელის მონიტორინგი."</string>
- <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"ამ პროფილის მმართველია:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტების, აპების და უსაფრთხო საიტების. დამატებითი ინფორმაციისათვის, დაუკავშირდით თქვენს ადმინისტრატორს.\n\nასევე, თქვენ დაკავშირებული ხართ VPN-თან („<xliff:g id="APPLICATION">%2$s</xliff:g>“). თქვენს VPN სერვისის მომწოდებელს ასევე შეუძლია თქვენი ქსელის აქტივობის მონიტორინგი."</string>
- <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"ამ მოწყობილობის მმართველია:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nთქვენი პროფილის მმართველია:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი მოწყობილობისა და ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტის, აპების და უსაფრთხო საიტების. დამატებითი ინფორმაციისათვის, დაუკავშირდით ადმინისტრატორს.\n\nასევე, თქვენ მიანიჭეთ „<xliff:g id="APPLICATION">%3$s</xliff:g>“-ს VPN კავშირის დაყენება. ამ აპს ასევე შეუძლია ქსელის მონიტორინგი."</string>
- <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"ამ მოწყობილობის მმართველია:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nთქვენი პროფილის მმართველია:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი მოწყობილობისა და ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტის, აპების და უსაფრთხო საიტების. დამატებითი ინფორმაციისათვის, დაუკავშირდით ადმინისტრატორს.\n\nასევე, თქვენ დაკავშირებული ხართ VPN-თან („<xliff:g id="APPLICATION">%3$s</xliff:g>“). თქვენს VPN სერვისის მომწოდებელს ასევე შეუძლია თქვენი ქსელის აქტივობის მონიტორინგი."</string>
+ <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"ამ პროფილის მმართველია:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი მოწყობილობისა და ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტის, აპების და უსაფრთხო საიტების. დამატებითი ინფორმაციისათვის, დაუკავშირდით ადმინისტრატორს.\n\nასევე, თქვენ მიანიჭეთ „<xliff:g id="APPLICATION">%2$s</xliff:g>“-ს VPN კავშირის დაყენება. ამ აპს ასევე შეუძლია ქსელის მონიტორ."</string>
+ <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"ამ პროფილის მმართველია:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nთქვენს ადმინ.-ს შეუძლია თქვენი ქსელის აქტივობის მონიტორ., მათ შორის ელფოსტების, აპების და უსაფრთხო საიტების. დამატ. ინფორმ.-თვის, დაუკავშირდით თქვენს ადმინ.-ს.\n\nასევე, თქვ. დაკავშ.-ლი ხართ VPN-თან („<xliff:g id="APPLICATION">%2$s</xliff:g>“). თქვენს VPN სერვისის მომწოდებელს ასევე შეუძლია თქვ. ქსელის აქტივობის მონიტორ."</string>
+ <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"ამ მოწყობილობის მმართველია:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nთქვ. პროფილის მმართველია:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nთქვენს ადმინ.-ს შეუძლია თქვ. მოწყ.-ისა და ქსელის აქტივობის მონიტ., მათ შორის ელფოსტის, აპების და უსაფრთხო საიტების. დამატებითი ინფორმ.-თვის, დაუკავშირდით ადმინ.-ს.\n\nასევე, თქვენ მიანიჭეთ „<xliff:g id="APPLICATION">%3$s</xliff:g>“-ს VPN კავშირის დაყენება. ამ აპს ასევე შეუძლია ქსელის მონიტ."</string>
+ <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"ამ მოწყ.-ის მმართ.-ია:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nთქვ. პროფ-ის მმართ-ია:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nთქვ. ადმინ.-ს შეუძლია თქვ. მოწყ.-ისა და ქსელის აქტივ.-ის მონიტ., მ. შ. ელფოსტის, აპების და უსაფრთხო საიტების. დამატებ. ინფორმ.-თვის, დაუკავშირდით ადმინ.-ს.\n\nასევე, თქვ. დაკავშირ. ხართ VPN-თან („<xliff:g id="APPLICATION">%3$s</xliff:g>“). თქვ. VPN სრვს-ის მომწ.-ს ასევე შეუძლია თქვ. ქსელის აქტ.-ის მონიტორ.."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"მოწყობილობის დარჩება ჩაკეტილი, სანამ ხელით არ გახსნით"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"შეტყობინებების უფრო სწრაფად მიღება"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"იხილეთ განბლოკვამდე"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index e7e7119..561596bf 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Аймақ GPS арқылы орнатылған"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Аймақ өтініштері қосылған"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Барлық хабарларды жойыңыз."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Параметрлер"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран автоматты түрде бұрылады."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Экран ландшафт бағытында бекітілген."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Экран портрет бағытында бекітілген."</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Барлығы"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Зарядталуда (толғанша <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Пайдаланушыны ауыстыру"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Профильді көрсету"</string>
<string name="user_add_user" msgid="5110251524486079492">"Пайдаланушы қосу"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Жаңа пайдаланушы"</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 61d4289..8555163 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"ទីតាំងកំណត់ដោយ GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"សំណើទីតាំងសកម្ម"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"សម្អាតការជូនដំណឹងទាំងអស់។"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"ការកំណត់"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"នឹងបង្វិលអេក្រង់ស្វ័យប្រវត្តិ។"</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"អេក្រង់ជាប់សោក្នុងទិសផ្ដេក។"</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"បានចាក់សោអេក្រង់ក្នុងទិសបញ្ឈរ។"</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"ទាំងអស់"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"កំពុងបញ្ចូលថ្ម (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ទើបពេញ)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ប្ដូរអ្នកប្រើ"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ប្ដូរអ្នកប្រើ អ្នកប្រើបច្ចុប្បន្ន <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"បង្ហាញប្រវត្តិរូប"</string>
<string name="user_add_user" msgid="5110251524486079492">"បន្ថែមអ្នកប្រើ"</string>
<string name="user_new_user_name" msgid="426540612051178753">"អ្នកប្រើថ្មី"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index f7b21c7..b2d7063 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"ಸ್ಥಾನವನ್ನು GPS ಮೂಲಕ ಹೊಂದಿಸಲಾಗಿದೆ"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"ಸ್ಥಾನ ವಿನಂತಿಗಳು ಸಕ್ರಿಯವಾಗಿವೆ"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೆರವುಗೊಳಿಸು."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ಪರದೆಯು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತಿರುಗುತ್ತದೆ."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ಪರದೆಯನ್ನು ಲ್ಯಾಂಡ್ಸ್ಕೇಪ್ ಓರಿಯಂಟೇಶನ್ನಲ್ಲಿ ಲಾಕ್ ಮಾಡಲಾಗಿದೆ."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ಪರದೆಯನ್ನು ಪೋಟ್ರೇಟ್ ಓರಿಯಂಟೇಶನ್ನಲ್ಲಿ ಲಾಕ್ ಮಾಡಲಾಗಿದೆ."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"ಎಲ್ಲ"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ ( ಪೂರ್ತಿ ಆಗುವವರೆಗೆ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ಬಳಕೆದಾರರನ್ನು ಬದಲಿಸಿ"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ಬಳಕೆದಾರರನ್ನು ಬದಲಿಸಿ, ಪ್ರಸ್ತುತ ಬಳಕೆದಾರ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"ಪ್ರೊಫೈಲ್ ತೋರಿಸು"</string>
<string name="user_add_user" msgid="5110251524486079492">"ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿ"</string>
<string name="user_new_user_name" msgid="426540612051178753">"ಹೊಸ ಬಳಕೆದಾರರು"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index e73cbde..aa8c465 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS에서 위치 설정"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"위치 요청 있음"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"모든 알림 지우기"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"설정"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"화면이 자동으로 회전됩니다."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"화면이 가로 방향으로 잠겨 있습니다."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"화면이 세로 방향으로 잠겨 있습니다."</string>
@@ -306,6 +309,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"모두 수신"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"충전 중(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> 후 충전 완료)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"사용자 전환"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"사용자 전환, 현재 사용자 <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"프로필 표시"</string>
<string name="user_add_user" msgid="5110251524486079492">"사용자 추가"</string>
<string name="user_new_user_name" msgid="426540612051178753">"새 사용자"</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index a96c88a..ccd706e 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -238,7 +238,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS боюнча аныкталган жайгашуу"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Жайгаштыруу талаптары иштелүүдө"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Бардык эскертмелерди тазалоо."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Жөндөөлөр"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран автоматтык түрдө бурулат."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Экран туурасынан турган бойдон бекитилген."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Экран тикесинен турган бойдон бекитилген."</string>
@@ -330,6 +333,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Бардыгы"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Кубатталууда (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> толгонго чейин)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Колдонуучуну которуу"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Профилди көрсөтүү"</string>
<string name="user_add_user" msgid="5110251524486079492">"Колдонуучу кошуу"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Жаңы колдонуучу"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 468f717..224b11f 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"ສະຖານທີ່ກຳນົດໂດຍ GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"ການຮ້ອງຂໍສະຖານທີ່ທີ່ເຮັດວຽກຢູ່"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ລຶບການແຈ້ງເຕືອນທັງໝົດ."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"ການຕັ້ງຄ່າ"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ໜ້າຈໍຈະໝຸນໂດຍອັດຕະໂນມັດ."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ໜ້າຈໍຖືກລັອກໃນລວງນອນ."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ໜ້າຈໍຖືກລັອກຢູ່ໃນໂໝດແນວຕັ້ງ."</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"ທັງໝົດ"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ກຳລັງສາກໄຟ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ກວ່າຈະເຕັມ)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ສະລັບຜູ່ໃຊ້"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"ສະແດງໂປຣໄຟລ໌"</string>
<string name="user_add_user" msgid="5110251524486079492">"ເພີ່ມຜູ່ໃຊ້"</string>
<string name="user_new_user_name" msgid="426540612051178753">"ຜູ່ໃຊ້ໃໝ່"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 866c8dd..f571a4c 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS nustatyta vieta"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Vietovės užklausos aktyvios"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Išvalyti visus pranešimus."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Nustatymai"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekranas bus sukamas automatiškai."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Užrakintas ekranas yra horizontalios orientacijos."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Užrakintas ekranas yra vertikalios orientacijos."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Visi"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Kraunama (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> iki visiško įkrovimo)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Perjungti naudotoją"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Perjungti naudotoją, dabartinis naudotojas <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Rodyti profilį"</string>
<string name="user_add_user" msgid="5110251524486079492">"Naudotojo pridėjimas"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Naujas naudotojas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 0e166b7..f309d24 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS iestatītā atrašanās vieta"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aktīvi atrašanās vietu pieprasījumi"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Notīrīt visus paziņojumus"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Iestatījumi"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekrāns tiks pagriezts automātiski."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ekrāns tagad ir bloķēts ainavas orientācijā."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ekrāns tagad ir bloķēts portreta orientācijā."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Visi"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Notiek uzlāde (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> līdz pilnīgai uzlādei)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Mainīt lietotāju"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Pārslēgt lietotāju; pašreizējais lietotājs: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Parādīt profilu"</string>
<string name="user_add_user" msgid="5110251524486079492">"Lietotāja pievienošana"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Jauns lietotājs"</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index b6b5396..90be4ad 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Локацијата е поставена со ГПС"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Активни барања за локација"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Исчисти ги сите известувања."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Поставки"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екранот ќе ротира автоматски."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Екранот е заклучен во ориентација на пејзаж."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Екранот е заклучен во ориентација на портрет."</string>
@@ -306,6 +309,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Сѐ"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Се полни (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> додека не се наполни)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Промени го корисникот"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Промени го корисникот, тековен корисник <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Прикажи го профилот"</string>
<string name="user_add_user" msgid="5110251524486079492">"Додај корисник"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Нов корисник"</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 293b028..742c943 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"ലൊക്കേഷൻ സജ്ജീകരിച്ചത് GPS ആണ്"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"ലൊക്കേഷൻ അഭ്യർത്ഥനകൾ സജീവമാണ്"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"എല്ലാ വിവരങ്ങളും മായ്ക്കുക."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"ക്രമീകരണങ്ങൾ"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"സ്ക്രീൻ യാന്ത്രികമായി തിരിയും."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"സ്ക്രീൻ ലാൻഡ്സ്കേപ്പ് ഓറിയന്റേഷനിൽ ലോക്കുചെയ്തു."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"സ്ക്രീൻ പോർട്രെയ്റ്റ് ഓറിയന്റേഷനിൽ ലോക്കുചെയ്തു."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"എല്ലാം"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ചാർജ്ജുചെയ്യുന്നു (പൂർണ്ണമാകുന്നതിന്, <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ഉപയോക്താവ് മാറുക"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ഉപയോക്താവിനെ മാറ്റുക, <xliff:g id="CURRENT_USER_NAME">%s</xliff:g> എന്നയാളാണ് നിലവിലുള്ള ഉപയോക്താവ്"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"പ്രൊഫൈൽ കാണിക്കുക"</string>
<string name="user_add_user" msgid="5110251524486079492">"ഉപയോക്താവിനെ ചേര്ക്കുക"</string>
<string name="user_new_user_name" msgid="426540612051178753">"പുതിയ ഉപയോക്താവ്"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index c5cf310..40e5dcd 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS байршил"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Байршлын хүсэлтүүд идэвхтэй"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Бүх мэдэгдлийг цэвэрлэх."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Тохиргоо"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Дэлгэц автоматаар эргэнэ."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Дэлгэц хэвтээ чиглэлд түгжигдсэн."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Дэлгэц босоо чиглэлээр түгжигдсэн."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Бүгд"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Цэнэглэж байна (дүүргэхэд <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Хэрэглэгчийг сэлгэх"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Хэрэглэгчийг сэлгэх, одоогийн хэрэглэгч <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Профайлыг харуулах"</string>
<string name="user_add_user" msgid="5110251524486079492">"Хэрэглэгч нэмэх"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Шинэ хэрэглэгч"</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index f6c6f8a..4e31db0 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS द्वारे स्थान सेट केले"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"स्थान विनंत्या सक्रिय"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"सर्व सूचना साफ करा."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"सेटिंग्ज"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"स्क्रीन स्वयंचलितपणे फिरेल."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"भूदृश्य अभिमुखतेमध्ये स्क्रीन लॉक केली आहे."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"पोर्ट्रेट अभिमुखतेमध्ये स्क्रीन लॉक केली आहे."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"सर्व"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> पूर्ण होईपर्यंत) चार्ज होत आहे"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"वापरकर्ता स्विच करा"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"वापरकर्ता स्विच करा, वर्तमान वापरकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"प्रोफाईल दर्शवा"</string>
<string name="user_add_user" msgid="5110251524486079492">"वापरकर्ता जोडा"</string>
<string name="user_new_user_name" msgid="426540612051178753">"नवीन वापरकर्ता"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 0c0efb3..fb6e04d 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasi ditetapkan oleh GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Permintaan lokasi aktif"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Padamkan semua pemberitahuan."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Tetapan"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skrin akan berputar secara automatik."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skrin dikunci dalam orientasi landskap."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skrin dikunci dalam orientasi potret."</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Semua"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Mengecas (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> sehingga penuh)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Tukar pengguna"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Tunjuk profil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Tambah pengguna"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Pengguna baharu"</string>
@@ -357,7 +362,7 @@
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Peranti akan kekal terkunci sehingga anda membuka kunci secara manual"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Dapatkan pemberitahuan lebih cepat"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Lihat sebelum anda membuka kunci"</string>
- <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Tidak, terima kasih"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Tidak"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Sediakan"</string>
<string name="muted_by" msgid="6147073845094180001">"Diredam oleh <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 5ac9d27..c22db95 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -210,7 +210,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPSမှတည်နေရာကိုအတည်ပြုသည်"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"တည်နေရာပြ တောင်းဆိုချက်များ အသက်ဝင်ရန်"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"သတိပေးချက်အားလုံးအား ဖယ်ရှားခြင်း။"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"ဆက်တင်များ"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ဖန်သားပြင်ပေါ်မှာ ပြသမှုက အလိုအလျောက် လှည့်သွားပါမည်"</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ဖန်သားပြင် အနေအထားက အလျားလိုက်အဖြစ် ပုံသေ လုပ်ထားပါသည်"</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ဖန်သားပြင် အနေအထားက ဒေါင်လိုက်အဖြစ် ပုံသေ လုပ်ထားပါသည်"</string>
@@ -302,6 +305,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"အားလုံး"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> အပြည့် အထိ) အားသွင်းနေ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"အသုံးပြုသူကို ပြောင်းလဲရန်"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"အသုံးပြုသူကို ပြောင်းရန်၊ လက်ရှိ အသုံးပြုသူ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"ပရိုဖိုင်ကို ပြရန်"</string>
<string name="user_add_user" msgid="5110251524486079492">"သုံးသူ ထပ်ထည့်ရန်"</string>
<string name="user_new_user_name" msgid="426540612051178753">"အသုံးပြုသူ အသစ်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 440fef3..dbbd216 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Posisjon angitt av GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aktive stedsforespørsler"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Fjern alle varslinger."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Innstillinger"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skjermen roterer automatisk."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skjermen er låst i liggende retning."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skjermen er låst i stående retning."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Lader (fulladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Bytt bruker"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Bytt bruker, gjeldende bruker er <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Vis profil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Legg til brukere"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Ny bruker"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index df555a6..248df04 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS द्वारा स्थान सेट गरिएको"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"स्थान अनुरोधहरू सक्रिय"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"सबै सूचनाहरू हटाउनुहोस्।"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"सेटिङ्हरू"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"स्क्रिन स्वतः घुम्ने छ।"</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"स्क्रिनलाई ल्यान्डस्केप अवस्थामा बन्द गरिएको छ।"</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"स्क्रिन पोर्टेट अभिमूखमा लक गरिएको छ।"</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"सबै"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"चार्ज हुँदै (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> पूर्ण भएसम्म)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"प्रयोगकर्ता फेर्नुहोस्"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"प्रयोगकर्ता, हालको प्रयोगकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g> मा स्विच गर्नुहोस्"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"प्रोफाइल देखाउनुहोस्"</string>
<string name="user_add_user" msgid="5110251524486079492">"प्रयोगकर्ता थप्नुहोस्"</string>
<string name="user_new_user_name" msgid="426540612051178753">"नयाँ प्रयोगकर्ता"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 4d5307c..6802420 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Locatie bepaald met GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Locatieverzoeken actief"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Alle meldingen wissen."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Instellingen"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Scherm wordt automatisch geroteerd."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Het scherm is nu vergrendeld in liggende stand."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Het scherm is nu vergrendeld in staande stand."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Opladen (vol over <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Gebruiker wijzigen"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Schakelen tussen gebruikers, huidige gebruiker <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Profiel weergeven"</string>
<string name="user_add_user" msgid="5110251524486079492">"Gebruiker toevoegen"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Nieuwe gebruiker"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 51fe321..0d482ab 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokalizacja z GPSa"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Prośby o lokalizację są aktywne"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Usuń wszystkie powiadomienia."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Ustawienia"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran zostanie obrócony automatycznie."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ekran jest zablokowany w orientacji poziomej."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ekran jest zablokowany w orientacji pionowej."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Wszystkie"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Ładuje się (pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Przełącz użytkownika"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Przełącz użytkownika. Bieżący użytkownik: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Pokaż profil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Dodaj użytkownika"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Nowy użytkownik"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 88ce23a..a37c832 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Localização definida por GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Pedidos de localização ativos"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Definições"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"O ecrã será rodado automaticamente."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"O ecrã está bloqueado na orientação horizontal."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"O ecrã está bloqueado na orientação vertical."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Tudo"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"A carregar (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até à carga máxima)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Mudar utilizador"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Mudar de utilizador; o utilizador atual é <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Mostrar perfil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Adicionar utilizador"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Novo utilizador"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 4180640..da43300 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Local definido por GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Solicitações de localização ativas"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Configurações"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A tela girará automaticamente."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"A tela está bloqueada na orientação paisagem."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"A tela está bloqueada na orientação retrato."</string>
@@ -306,6 +309,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Tudo"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Carregando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até concluir)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Trocar usuário"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Mostrar perfil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Adicionar usuário"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Novo usuário"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 8995c15..d4bebb3 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Locaţie setată prin GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Solicitări locație active"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Ștergeţi toate notificările."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Setări"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ecranul se va roti în mod automat."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ecranul este blocat în orientarea de tip peisaj."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ecranul este blocat în orientarea de tip portret."</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Toate"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Se încarcă (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> până la finalizare)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Comutați între utilizatori"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Afișați profilul"</string>
<string name="user_add_user" msgid="5110251524486079492">"Adăugați un utilizator"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Utilizator nou"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 84cfff4..337319a 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Координаты по GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Есть активные запросы на определение местоположения"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Удалить все уведомления"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Настройки"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран будет поворачиваться автоматически."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Выбрана только альбомная ориентация экрана."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Выбрана только книжная ориентация экрана."</string>
@@ -306,6 +309,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Все"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Зарядка батареи (осталось <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Сменить пользователя."</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Показать профиль."</string>
<string name="user_add_user" msgid="5110251524486079492">"Добавить пользователя"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Новый пользователь"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 321ecb9..6b41dbe 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS මඟින් ස්ථානය සකසා ඇත"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"පිහිටීම් ඉල්ලීම් සක්රියයි"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"සියලු දැනුම්දීම් හිස් කරන්න."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"සැකසීම්"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"තිරය ස්වයංක්රීයව කරකැවේ."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"තිරය තිරස් දිශානතියෙහි අගුළු දමා ඇත."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"තිරය සිරස් දිශානතිය තුළ අගුළු වැටී ඇත."</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"සියලු"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ආරෝපණය වෙමින් (සම්පුර්ණ වන තෙක් <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"පරිශීලක මාරුව"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"පැතිකඩ පෙන්වන්න"</string>
<string name="user_add_user" msgid="5110251524486079492">"පරිශීලකයෙක් එක් කරන්න"</string>
<string name="user_new_user_name" msgid="426540612051178753">"නව පරිශීලකයා"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index da1bb4c..2ebfe42 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Poloha nastavená pomocou GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Žiadosti o polohu sú aktívne"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazať všetky upozornenia."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Nastavenia"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Obrazovka sa automaticky otočí."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Obrazovka je uzamknutá v orientácii na šírku."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Obrazovka je uzamknutá v orientácii na výšku."</string>
@@ -306,6 +309,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Všetky"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Nabíja sa (úplné nabitie o <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Prepnutie používateľa"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Zobraziť profil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Pridať používateľa"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Nový používateľ"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 5b0442a..06a4b35 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokacija nastavljena z GPS-om"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aktivne zahteve za lokacijo"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Izbriši vsa obvestila."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Nastavitve"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Zaslon se bo samodejno zasukal."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Zaslon je zaklenjen v ležeči usmerjenosti."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Zaslon je zaklenjen v pokončni usmerjenosti."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Vse"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Polnjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napolnjenosti)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Preklop med uporabniki"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Preklop med uporabniki, trenutni uporabnik <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Prikaz profila"</string>
<string name="user_add_user" msgid="5110251524486079492">"Dodajanje uporabnika"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Nov uporabnik"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 4552926..4d509d5 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Локацију је подесио GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Има активних захтева за локацију"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Обриши сва обавештења."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Подешавања"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екран ће се аутоматски ротирати."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Екран је закључан у хоризонталном положају."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Екран је закључан у вертикалном положају."</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Све"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Пуњење (пун је за <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Замени корисника"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Прикажи профил"</string>
<string name="user_add_user" msgid="5110251524486079492">"Додај корисника"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Нови корисник"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index f99c4ef..48a84456 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Platsen har identifierats av GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Det finns aktiva platsbegäranden"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Ta bort alla meddelanden."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Inställningar"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skärmen roteras automatiskt."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Bildskärmens riktning är nu låst i liggande format."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Bildskärmens riktning är nu låst i stående format."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Alla"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Laddar (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> tills batteriet är fulladdat)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Byt användare"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Byt användare. Aktuell användare: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Visa profil"</string>
<string name="user_add_user" msgid="5110251524486079492">"Lägg till användare"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Ny användare"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index c0b1b12..a76edc1 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -210,7 +210,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Mahali pamewekwa na GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Maombi ya eneo yanatumika"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Futa arifa zote."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Mipangilio"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skrini itazunguka kiotomatiki."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skrini imefungwa sasa katika uelekezo wa mandhari."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skrini imefungwa katika uelekeo wa picha."</string>
@@ -302,6 +305,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Zote"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Inachaji (Imebakisha <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ijae)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Badili mtumiaji"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Onyesha wasifu"</string>
<string name="user_add_user" msgid="5110251524486079492">"Ongeza mtumiaji"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Mtumiaji mpya"</string>
@@ -355,7 +360,7 @@
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Kifaa kitaendelea kuwa katika hali ya kufungwa hadi utakapokifungua mwenyewe"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Pata arifa kwa haraka"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Zitazame kabla hujafungua"</string>
- <string name="hidden_notifications_cancel" msgid="3690709735122344913">"La, asante"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Hapana, asante"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Sanidi"</string>
<string name="muted_by" msgid="6147073845094180001">"Sauti imezimwa na <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index 5aafb66..83477c0 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -33,6 +33,8 @@
<!-- Set to true to enable the user switcher on the keyguard. -->
<bool name="config_keyguardUserSwitcher">true</bool>
- <!-- Transposes the recents layout in landscape. -->
- <bool name="recents_transpose_layout_with_orientation">false</bool>
+ <!-- Transposes the search bar layout in landscape. -->
+ <bool name="recents_has_transposed_search_bar">true</bool>
+ <!-- Transposes the nav bar in landscape (only used for purposes of layout). -->
+ <bool name="recents_has_transposed_nav_bar">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values-sw720dp/config.xml b/packages/SystemUI/res/values-sw720dp/config.xml
index d8bb8d7d..fbeadcd 100644
--- a/packages/SystemUI/res/values-sw720dp/config.xml
+++ b/packages/SystemUI/res/values-sw720dp/config.xml
@@ -39,5 +39,10 @@
<!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
card. -->
<integer name="keyguard_max_notification_count">5</integer>
+
+ <!-- Transposes the search bar layout in landscape. -->
+ <bool name="recents_has_transposed_search_bar">false</bool>
+ <!-- Transposes the nav bar in landscape (only used for purposes of layout). -->
+ <bool name="recents_has_transposed_nav_bar">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 52700cc..0d92c1b 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS அமைத்த இருப்பிடம்"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"இருப்பிடக் கோரிக்கைகள் இயக்கப்பட்டன"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"எல்லா அறிவிப்புகளையும் அழி."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"அமைப்பு"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"திரை தானாகச் சுழலும்."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"நிலத்தோற்ற திசையமைப்பில் திரைப் பூட்டப்பட்டுள்ளது."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"உருவப்பட திசையமைப்பில் திசை பூட்டப்பட்டுள்ளது."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"எல்லாம்"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"சார்ஜாகிறது (முழு சார்ஜிற்கு <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ஆகும்)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"பயனரை மாற்று"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"பயனரை மாற்று, தற்போதைய பயனர் <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"சுயவிவரத்தைக் காட்டு"</string>
<string name="user_add_user" msgid="5110251524486079492">"பயனரைச் சேர்"</string>
<string name="user_new_user_name" msgid="426540612051178753">"புதியவர்"</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 3740172..f498ba0 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"స్థానం GPS ద్వారా సెట్ చేయబడింది"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"స్థాన అభ్యర్థనలు సక్రియంగా ఉన్నాయి"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"అన్ని నోటిఫికేషన్లను క్లియర్ చేయండి."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"సెట్టింగ్లు"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"స్క్రీన్ స్వయంచాలకంగా తిప్పబడుతుంది."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"స్క్రీన్ ల్యాండ్స్కేప్ దృగ్విన్యాసంలో లాక్ చేయబడుతుంది."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"స్క్రీన్ పోర్ట్రెయిట్ దృగ్విన్యాసంలో లాక్ చేయబడుతుంది."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"అన్నిటికీ"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ఛార్జ్ అవుతోంది (పూర్తిగా నిండటానికి <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"వినియోగదారుని మార్చు"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"వినియోగదారుని మార్చు, ప్రస్తుత వినియోగదారు <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"ప్రొఫైల్ని చూపు"</string>
<string name="user_add_user" msgid="5110251524486079492">"వినియోగదారుని జోడించండి"</string>
<string name="user_new_user_name" msgid="426540612051178753">"కొత్త వినియోగదారు"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 59579bc..d1c2ecd 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"ตำแหน่งที่กำหนดโดย GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"คำขอตำแหน่งที่มีการใช้งาน"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ล้างการแจ้งเตือนทั้งหมด"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"การตั้งค่า"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"หน้าจอจะหมุนโดยอัตโนมัติ"</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ขณะนี้หน้าจอถูกล็อกให้วางในแนวนอน"</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ขณะนี้หน้าจอถูกล็อกให้วางในแนวตั้ง"</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"ทั้งหมด"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"กำลังชาร์จ (อีก <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> เต็ม)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"สลับผู้ใช้"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"แสดงโปรไฟล์"</string>
<string name="user_add_user" msgid="5110251524486079492">"เพิ่มผู้ใช้"</string>
<string name="user_new_user_name" msgid="426540612051178753">"ผู้ใช้ใหม่"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index a421a84..aa2992f 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasyong itinatakda ng GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aktibo ang mga kahilingan ng lokasyon"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"I-clear ang lahat ng notification."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Mga Setting"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Awtomatikong iikot ang screen."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Naka-lock ang screen sa pahigang oryentasyon."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Naka-lock ang screen sa patayong oryentasyon."</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Lahat"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Nagtsa-charge (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hanggang mapuno)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Magpalit ng user"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Ipakita ang profile"</string>
<string name="user_add_user" msgid="5110251524486079492">"Magdagdag ng user"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Bagong user"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 0c0149c..0dc8c61 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Konum GPS ile belirlendi"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Konum bilgisi istekleri etkin"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Tüm bildirimleri temizle"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Ayarlar"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran otomatik olarak dönecektir."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ekran yatay yönde kilitlendi."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ekran dikey yönde kilitlendi."</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Tümü"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Şarj oluyor (tamamen dolmasına <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kaldı)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Kullanıcı değiştirme"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Profili göster"</string>
<string name="user_add_user" msgid="5110251524486079492">"Kullanıcı ekle"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Yeni kullanıcı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 162a280..6e371a4 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Місцезнаходження встановлено за допомогою GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Запити про місцезнаходження активні"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Очистити всі сповіщення."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Налаштування"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екран обертатиметься автоматично."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Екран заблоковано в альбомній орієнтації."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Екран заблоковано в книжковій орієнтації."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Усі"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Заряджання (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до повного зарядження)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Змінити користувача"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Змінити користувача, поточний користувач – <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Показати профіль"</string>
<string name="user_add_user" msgid="5110251524486079492">"Додати користувача"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Новий користувач"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 708607c..ec3096b 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"مقام متعین کیا گیا بذریعہ GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"مقام کی درخواستیں فعال ہیں"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"سبھی اطلاعات صاف کریں۔"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"ترتیبات"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"اسکرین خود بخود گردش کرے گی۔"</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"اسکرین لینڈ اسکیپ سمت بندی میں مقفل ہے۔"</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"اسکرین پورٹریٹ سمت بندی میں مقفل ہے۔"</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"سبھی"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"چارج ہو رہا ہے (مکمل ہونے تک <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> باقی ہیں)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"صارف سوئچ کریں"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"صارف کو سوئچ کریں، موجودہ صارف <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"پروفائل دکھائیں"</string>
<string name="user_add_user" msgid="5110251524486079492">"صارف کو شامل کریں"</string>
<string name="user_new_user_name" msgid="426540612051178753">"نیا صارف"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 7776269..c0dd8b7 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS yordamida manzilni o‘rnatish"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Joylashuv so‘rovlari yoniq"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Barcha eslatmalarni tozalash."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Sozlamalar"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran avtomatik ravishda aylanadi."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ekran eniga holatida qulflandi."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ekran bo‘yiga holatida qulflandi."</string>
@@ -304,6 +307,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Barchasi"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Quvvat olmoqda (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>da to‘ladi)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Foydalanuvchini almashtirish"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Profilni ko‘rsatish"</string>
<string name="user_add_user" msgid="5110251524486079492">"Foydalanuvchi qo‘shish"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Yangi foydalanuvchi"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 80fdc46..2488556 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Vị trí đặt bởi GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Yêu cầu về thông tin vị trí đang hoạt động"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Xóa tất cả thông báo."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Cài đặt"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Màn hình sẽ xoay tự động."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Màn hình hiện bị khóa theo hướng ngang."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Màn hình hiện bị khóa theo hướng dọc."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Tất cả"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Đang sạc (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> cho đến khi đầy)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Chuyển đổi người dùng"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Chuyển người dùng, người dùng hiện tại <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Hiển thị hồ sơ"</string>
<string name="user_add_user" msgid="5110251524486079492">"Thêm người dùng"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Người dùng mới"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 06cebb3..4ca0e8f 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"已通过GPS确定位置"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"应用发出了有效位置信息请求"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"设置"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"屏幕会自动旋转。"</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"屏幕锁定为横向模式。"</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"屏幕锁定为纵向模式。"</string>
@@ -306,6 +309,8 @@
<string name="interruption_level_all" msgid="1330581184930945764">"全部"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"正在充电(还需<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>充满)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"切换用户"</string>
+ <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+ <skip />
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"显示个人资料"</string>
<string name="user_add_user" msgid="5110251524486079492">"添加用户"</string>
<string name="user_new_user_name" msgid="426540612051178753">"新用户"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 9b0bde1..3a53017 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS 已定位"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"位置要求啟動中"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"設定"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"螢幕會自動旋轉。"</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"螢幕已鎖定為橫向模式。"</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"螢幕已鎖定為垂直模式。"</string>
@@ -306,6 +309,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"全部"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"充電中 (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>後完成充電)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"切換使用者"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"切換使用者,目前使用者是<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"顯示個人檔案"</string>
<string name="user_add_user" msgid="5110251524486079492">"新增使用者"</string>
<string name="user_new_user_name" msgid="426540612051178753">"新使用者"</string>
@@ -357,7 +361,7 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"這部裝置的管理機構:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的個人檔案的管理機構:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理員可以監控您的網絡活動,包括電郵、應用程式及安全網站。如需瞭解詳情,請聯絡您的管理員。\n\n同時,由於您已授權「<xliff:g id="APPLICATION">%3$s</xliff:g>」設定 VPN 連線,因此這個應用程式也能監控您的網絡活動。"</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"這部裝置的管理機構:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的個人檔案的管理機構:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理員可以監控您的網絡活動,包括電郵、應用程式及安全網站。如需瞭解詳情,請聯絡您的管理員。\n\n同時,由於您的裝置已與 VPN (「<xliff:g id="APPLICATION">%3$s</xliff:g>」) 連線,因此您的 VPN 服務供應商也能監控您的網絡活動。"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"裝置將保持上鎖,直到您手動解鎖"</string>
- <string name="hidden_notifications_title" msgid="7139628534207443290">"快速取得通知"</string>
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"更快取得通知"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"解鎖前顯示"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"不用了,謝謝"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"設定"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index d57845b..8840b2c 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -214,7 +214,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS 已定位"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"有位置資訊要求"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"設定"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"螢幕會自動旋轉。"</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"螢幕已鎖定為橫向模式。"</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"螢幕已鎖定為垂直模式。"</string>
@@ -306,6 +309,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"全部"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"充電中 (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>後充飽)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"切換使用者"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"切換使用者,目前使用者是<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"顯示設定檔"</string>
<string name="user_add_user" msgid="5110251524486079492">"新增使用者"</string>
<string name="user_new_user_name" msgid="426540612051178753">"新使用者"</string>
@@ -350,12 +354,12 @@
<string name="monitoring_description_legacy_vpn" msgid="4740349017929725435">"您已連線至 VPN (「<xliff:g id="APPLICATION">%1$s</xliff:g>」)。\n\n您的 VPN 服務供應商可以監控您的裝置和網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。"</string>
<string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"這個裝置由下列網域管理:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>。\n\n您的管理員可以監控您的網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。如需詳細資訊,請與您的管理員聯絡。\n\n同時,由於您已授權「<xliff:g id="APPLICATION">%2$s</xliff:g>」設定 VPN 連線,因此這個應用程式也能監控您的網路活動。"</string>
<string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"這個裝置由下列網域管理:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>。\n\n您的管理員可以監控您的網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。如需詳細資訊,請與您的管理員聯絡。\n\n同時,由於您的裝置已連線至 VPN (「<xliff:g id="APPLICATION">%2$s</xliff:g>」),因此您的 VPN 服務供應商也能監控您的網路活動。"</string>
- <string name="monitoring_description_profile_owned" msgid="2370062794285691713">"這個設定檔由下列機構管理:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\n您的管理員可以監控您的裝置和網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。\n\n如需詳細資訊,請與您的管理員聯絡。"</string>
- <string name="monitoring_description_device_and_profile_owned" msgid="8685301493845456293">"這個裝置由下列機構管理:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的設定檔由下列機構管理:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理員可以監控您的網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。\n\n如需詳細資訊,請與您的管理員聯絡。"</string>
- <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"這個設定檔由下列機構管理:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\n您的管理員可以監控您的網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。如需詳細資訊,請與您的管理員聯絡。\n\n同時,由於您已授權「<xliff:g id="APPLICATION">%2$s</xliff:g>」設定 VPN 連線,因此這個應用程式也能監控您的網路活動。"</string>
- <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"這個設定檔由下列機構管理:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\n您的管理員可以監控您的網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。如需詳細資訊,請與您的管理員聯絡。\n\n同時,由於您的裝置已連線至 VPN (「<xliff:g id="APPLICATION">%2$s</xliff:g>」),因此您的 VPN 服務供應商也能監控您的網路活動。"</string>
- <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"這個裝置由下列機構管理:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的設定檔由下列機構管理:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理員可以監控您的網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。如需詳細資訊,請與您的管理員聯絡。\n\n同時,由於您已授權「<xliff:g id="APPLICATION">%3$s</xliff:g>」設定 VPN 連線,因此這個應用程式也能監控您的網路活動。"</string>
- <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"這個裝置由下列機構管理:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的設定檔由以下機構管理:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理員可以監控您的網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。如需詳細資訊,請與您的管理員聯絡。\n\n同時,由於您的裝置已連線至 VPN (「<xliff:g id="APPLICATION">%3$s</xliff:g>」),因此您的 VPN 服務供應商也能監控您的網路活動。"</string>
+ <string name="monitoring_description_profile_owned" msgid="2370062794285691713">"這個設定檔由下列機構管理:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\n您的管理員可以監控您的裝置和網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。\n\n如需詳細資訊,請洽您的管理員。"</string>
+ <string name="monitoring_description_device_and_profile_owned" msgid="8685301493845456293">"這個裝置由下列機構管理:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的設定檔由下列機構管理:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理員可以監控您的網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。\n\n如需詳細資訊,請洽您的管理員。"</string>
+ <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"這個設定檔由下列機構管理:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\n您的管理員可以監控您的網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。如需詳細資訊,請洽您的管理員。\n\n同時,由於您已授權「<xliff:g id="APPLICATION">%2$s</xliff:g>」設定 VPN 連線,因此這個應用程式也能監控您的網路活動。"</string>
+ <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"這個設定檔由下列機構管理:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\n您的管理員可以監控您的網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。如需詳細資訊,請洽您的管理員。\n\n同時,由於您的裝置已連線至 VPN (「<xliff:g id="APPLICATION">%2$s</xliff:g>」),因此您的 VPN 服務供應商也能監控您的網路活動。"</string>
+ <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"這個裝置由下列機構管理:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的設定檔由下列機構管理:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理員可以監控您的網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。如需詳細資訊,請洽您的管理員。\n\n同時,由於您已授權「<xliff:g id="APPLICATION">%3$s</xliff:g>」設定 VPN 連線,因此這個應用程式也能監控您的網路活動。"</string>
+ <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"這個裝置由下列機構管理:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的設定檔由以下機構管理:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理員可以監控您的網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。如需詳細資訊,請洽您的管理員。\n\n同時,由於您的裝置已連線至 VPN (「<xliff:g id="APPLICATION">%3$s</xliff:g>」),因此您的 VPN 服務供應商也能監控您的網路活動。"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"在您手動解鎖前,裝置將保持鎖定狀態"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"更快取得通知"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"解鎖前顯示"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index edf51a1..abb6841 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -212,7 +212,10 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Indawo ihlelwe i-GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Izicelo zendawo ziyasebenza"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Susa zonke izaziso."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="5386295743469882227">"Izilungiselelo"</string>
+ <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+ <skip />
+ <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+ <skip />
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Isikrini sizophenduka ngokuzenzakalela."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Isikrini sikhiyelwe ngomumo we-landscape."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Isikrini sikhiyelwe ngomumo we-portrait."</string>
@@ -304,6 +307,7 @@
<string name="interruption_level_all" msgid="1330581184930945764">"Konke"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Iyashaja (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ize igcwale)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Shintsha umsebenzisi"</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Shintsha umsebenzisi, umsebenzisi wamanje ngu-<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Bonisa iphrofayela"</string>
<string name="user_add_user" msgid="5110251524486079492">"Engeza umsebenzisi"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Umsebenzisi omusha"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 5399a39..f899572 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -134,10 +134,13 @@
<integer name="recents_animate_task_exit_to_home_duration">225</integer>
<!-- The min animation duration for animating the task bar out. -->
<integer name="recents_animate_task_bar_exit_duration">125</integer>
+ <!-- The animation delay for animating the first task in. This should roughly be the animation
+ duration of the transition in to recents from home. -->
+ <integer name="recents_animate_task_enter_from_home_delay">150</integer>
<!-- The min animation duration for animating the task in when transitioning from home. -->
<integer name="recents_animate_task_enter_from_home_duration">275</integer>
<!-- The animation stagger to apply to each task animation when transitioning from home. -->
- <integer name="recents_animate_task_enter_from_home_delay">150</integer>
+ <integer name="recents_animate_task_enter_from_home_stagger_delay">10</integer>
<!-- The short duration when animating in/out the lock to app button. -->
<integer name="recents_animate_lock_to_app_button_short_duration">150</integer>
<!-- The long duration when animating in/out the lock to app button. -->
@@ -152,8 +155,10 @@
<integer name="recents_max_task_stack_view_dim">96</integer>
<!-- The delay to enforce between each alt-tab key press. -->
<integer name="recents_alt_tab_key_delay">200</integer>
- <!-- Transposes the recents layout in landscape. -->
- <bool name="recents_transpose_layout_with_orientation">true</bool>
+ <!-- Transposes the search bar layout in landscape. -->
+ <bool name="recents_has_transposed_search_bar">true</bool>
+ <!-- Transposes the nav bar in landscape (only used for purposes of layout). -->
+ <bool name="recents_has_transposed_nav_bar">true</bool>
<!-- Whether to enable KeyguardService or not -->
<bool name="config_enableKeyguardService">true</bool>
@@ -186,11 +191,21 @@
<!-- Doze: maximum brightness to use when pulsing -->
<integer name="doze_pulse_brightness">40</integer>
- <!-- Doze: number of pulses when doing multiple pulses in quick succession -->
- <integer name="doze_multipulse_count">3</integer>
+ <!-- Doze: period of time between pulses (start of pulse) when following the notification light
+ Format: <under_ms>:<period_ms>,...,<default_ms> -->
+ <string name="doze_pulse_period_function">60000:10000,300000:30000,1800000:60000,0</string>
- <!-- Doze: interval between pulses when following the notification light -->
- <integer name="doze_notification_pulse_interval">30000</integer>
+ <!-- Doze: pulse parameter - how long does it take to fade in? -->
+ <integer name="doze_pulse_duration_in">1000</integer>
+
+ <!-- Doze: pulse parameter - once faded in, how long does it stay visible? -->
+ <integer name="doze_pulse_duration_visible">3000</integer>
+
+ <!-- Doze: pulse parameter - how long does it take to fade out? -->
+ <integer name="doze_pulse_duration_out">1000</integer>
+
+ <!-- Doze: pulse parameter - how long to wait before pulsing (if not starting immediately) -->
+ <integer name="doze_pulse_delay">1000</integer>
<!-- Doze: alpha to apply to small icons when dozing -->
<integer name="doze_small_icon_alpha">222</integer><!-- 87% of 0xff -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 8cd4ce6..4495318 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -476,4 +476,12 @@
<fraction name="battery_subpixel_smoothing_right">0%</fraction>
<dimen name="battery_margin_bottom">0dp</dimen>
+
+ <!-- Extra padding between the mobile data type icon and the strength indicator when the data
+ type icon is wide. -->
+ <dimen name="wide_type_icon_start_padding">2dp</dimen>
+
+ <!-- Extra padding between the mobile data type icon and the strength indicator when the data
+ type icon is wide for the tile in quick settings. -->
+ <dimen name="wide_type_icon_start_padding_qs">3dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 23d9748..0445fe8 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -736,9 +736,6 @@
<!-- Shows when people have clicked at the right edge of the screen to explain how to open the phone. In right-to-left languages, this is the opposite direction. [CHAR LIMIT=60] -->
<string name="camera_hint">Swipe left for camera</string>
- <!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
- <string name="zen_mode_forever">Indefinitely</string>
-
<!-- Interruption level: None. [CHAR LIMIT=20] -->
<string name="interruption_level_none">None</string>
@@ -798,18 +795,12 @@
<!-- Notification when resuming an existing guest session: Action that continues with the current session [CHAR LIMIT=35] -->
<string name="guest_wipe_session_dontwipe">Yes, continue</string>
+ <!-- Title for add user confirmation dialog [CHAR LIMIT=30] -->
+ <string name="user_add_user_title" msgid="2108112641783146007">Add new user?</string>
- <!-- Zen mode condition: time duration in minutes. [CHAR LIMIT=NONE] -->
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one">For one minute</item>
- <item quantity="other">For %d minutes</item>
- </plurals>
+ <!-- Message for add user confirmation dialog - short version. [CHAR LIMIT=none] -->
+ <string name="user_add_user_message_short" msgid="1511354412249044381">When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. </string>
- <!-- Zen mode condition: time duration in hours. [CHAR LIMIT=NONE] -->
- <plurals name="zen_mode_duration_hours">
- <item quantity="one">For one hour</item>
- <item quantity="other">For %d hours</item>
- </plurals>
<!-- Battery saver notification title. [CHAR LIMIT=60]-->
<string name="battery_saver_notification_title">Battery saver is on</string>
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index d17e263..1183582 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -42,6 +42,7 @@
import com.android.systemui.R;
import com.android.systemui.SystemUIApplication;
+import com.android.systemui.statusbar.phone.DozeParameters;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -54,11 +55,11 @@
private static final String ACTION_BASE = "com.android.systemui.doze";
private static final String PULSE_ACTION = ACTION_BASE + ".pulse";
private static final String NOTIFICATION_PULSE_ACTION = ACTION_BASE + ".notification_pulse";
- private static final String EXTRA_PULSES = "pulses";
private final String mTag = String.format(TAG + ".%08x", hashCode());
private final Context mContext = this;
private final Handler mHandler = new Handler();
+ private final DozeParameters mDozeParameters = new DozeParameters(mContext);
private Host mHost;
private SensorManager mSensors;
@@ -74,9 +75,8 @@
private int mDisplayStateWhenOn;
private boolean mNotificationLightOn;
private PendingIntent mNotificationPulseIntent;
- private int mMultipulseCount;
- private int mNotificationPulseInterval;
private boolean mPowerSaveActive;
+ private long mNotificationPulseTime;
public DozeService() {
if (DEBUG) Log.d(mTag, "new DozeService()");
@@ -94,9 +94,9 @@
pw.print(" mMaxBrightness: "); pw.println(mMaxBrightness);
pw.print(" mDisplayStateSupported: "); pw.println(mDisplayStateSupported);
pw.print(" mNotificationLightOn: "); pw.println(mNotificationLightOn);
- pw.print(" mMultipulseCount: "); pw.println(mMultipulseCount);
- pw.print(" mNotificationPulseInterval: "); pw.println(mNotificationPulseInterval);
pw.print(" mPowerSaveActive: "); pw.println(mPowerSaveActive);
+ pw.print(" mNotificationPulseTime: "); pw.println(mNotificationPulseTime);
+ mDozeParameters.dump(pw);
}
@Override
@@ -127,11 +127,7 @@
BRIGHTNESS_OFF, BRIGHTNESS_ON);
mNotificationPulseIntent = PendingIntent.getBroadcast(mContext, 0,
new Intent(NOTIFICATION_PULSE_ACTION).setPackage(getPackageName()),
- PendingIntent.FLAG_CANCEL_CURRENT);
- mMultipulseCount = SystemProperties.getInt("doze.multipulses",
- res.getInteger(R.integer.doze_multipulse_count));
- mNotificationPulseInterval = SystemProperties.getInt("doze.notification.pulse",
- res.getInteger(R.integer.doze_notification_pulse_interval));
+ PendingIntent.FLAG_UPDATE_CURRENT);
mDisplayStateWhenOn = mDisplayStateSupported ? Display.STATE_DOZE : Display.STATE_ON;
setDozeScreenState(mDisplayStateWhenOn);
}
@@ -159,6 +155,7 @@
public void stayAwake(long millis) {
if (mDreaming && millis > 0) {
+ if (DEBUG) Log.d(mTag, "stayAwake millis=" + millis);
mWakeLock.acquire(millis);
setDozeScreenState(mDisplayStateWhenOn);
setDozeScreenBrightness(mMaxBrightness);
@@ -218,21 +215,9 @@
}
}
- private void requestMultipulse() {
- requestPulse(mMultipulseCount);
- }
-
- private void requestPulse() {
- requestPulse(1);
- }
-
- private void requestPulse(int pulses) {
- requestPulse(pulses, true /*delayed*/);
- }
-
- private void requestPulse(int pulses, boolean delayed) {
+ private void requestPulse(boolean delayed) {
if (mHost != null) {
- mHost.requestPulse(pulses, delayed, this);
+ mHost.requestPulse(delayed, this);
}
}
@@ -281,9 +266,14 @@
private void rescheduleNotificationPulse() {
mAlarmManager.cancel(mNotificationPulseIntent);
if (mNotificationLightOn) {
- final long time = System.currentTimeMillis() + mNotificationPulseInterval;
- if (DEBUG) Log.d(TAG, "Scheduling pulse for " + new Date(time));
- mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, time, mNotificationPulseIntent);
+ final long now = System.currentTimeMillis();
+ final long age = now - mNotificationPulseTime;
+ final long period = mDozeParameters.getPulsePeriod(age);
+ final long time = now + period;
+ if (period > 0) {
+ if (DEBUG) Log.d(TAG, "Scheduling pulse in " + period + " for " + new Date(time));
+ mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, time, mNotificationPulseIntent);
+ }
}
}
@@ -314,11 +304,11 @@
public void onReceive(Context context, Intent intent) {
if (PULSE_ACTION.equals(intent.getAction())) {
if (DEBUG) Log.d(mTag, "Received pulse intent");
- requestPulse(intent.getIntExtra(EXTRA_PULSES, mMultipulseCount));
+ requestPulse(false /*delayed*/);
}
if (NOTIFICATION_PULSE_ACTION.equals(intent.getAction())) {
if (DEBUG) Log.d(mTag, "Received notification pulse intent");
- requestPulse();
+ requestPulse(true /*delayed*/);
rescheduleNotificationPulse();
}
}
@@ -334,7 +324,8 @@
@Override
public void onBuzzBeepBlinked() {
if (DEBUG) Log.d(mTag, "onBuzzBeepBlinked");
- requestMultipulse();
+ mNotificationPulseTime = System.currentTimeMillis();
+ requestPulse(true /*delayed*/);
}
@Override
@@ -342,6 +333,10 @@
if (DEBUG) Log.d(mTag, "onNotificationLight on=" + on);
if (mNotificationLightOn == on) return;
mNotificationLightOn = on;
+ if (mNotificationLightOn) {
+ mNotificationPulseTime = System.currentTimeMillis();
+ requestPulse(true /*delayed*/);
+ }
rescheduleNotificationPulse();
}
@@ -358,7 +353,7 @@
void addCallback(Callback callback);
void removeCallback(Callback callback);
void requestDoze(DozeService dozeService);
- void requestPulse(int pulses, boolean delayed, DozeService dozeService);
+ void requestPulse(boolean delayed, DozeService dozeService);
void dozingStopped(DozeService dozeService);
boolean isPowerSaveActive();
@@ -409,7 +404,7 @@
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION).build());
}
}
- requestPulse(1, false /*delayed*/);
+ requestPulse(false /*delayed*/);
setListening(true); // reregister, this sensor only fires once
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 8d35eb0..50ba68e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AlarmManager;
import android.app.PendingIntent;
@@ -487,7 +488,7 @@
mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
mLockPatternUtils = new LockPatternUtils(mContext);
- mLockPatternUtils.setCurrentUser(UserHandle.USER_OWNER);
+ mLockPatternUtils.setCurrentUser(ActivityManager.getCurrentUser());
// Assume keyguard is showing (unless it's disabled) until we know for sure...
mShowing = (mUpdateMonitor.isDeviceProvisioned() || mLockPatternUtils.isSecure())
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java b/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java
index 377fcc0..a9fdc86 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java
@@ -23,7 +23,6 @@
import android.text.TextUtils.TruncateAt;
import android.view.Gravity;
import android.view.View;
-import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -41,7 +40,7 @@
* truncate.
* Second line: ellipsis if necessary
*/
-public class QSDualTileLabel extends FrameLayout {
+public class QSDualTileLabel extends LinearLayout {
private final Context mContext;
private final TextView mFirstLine;
@@ -54,12 +53,13 @@
public QSDualTileLabel(Context context) {
super(context);
mContext = context;
+ setOrientation(LinearLayout.VERTICAL);
mHorizontalPaddingPx = mContext.getResources()
.getDimensionPixelSize(R.dimen.qs_dual_tile_padding_horizontal);
mFirstLine = initTextView();
- mFirstLine.setPadding(mHorizontalPaddingPx, 0, 0, 0);
+ mFirstLine.setPadding(mHorizontalPaddingPx, 0, mHorizontalPaddingPx, 0);
final LinearLayout firstLineLayout = new LinearLayout(mContext);
firstLineLayout.setPadding(0, 0, 0, 0);
firstLineLayout.setOrientation(LinearLayout.HORIZONTAL);
@@ -70,13 +70,13 @@
mFirstLineCaret.setScaleType(ImageView.ScaleType.MATRIX);
mFirstLineCaret.setClickable(false);
firstLineLayout.addView(mFirstLineCaret);
- addView(firstLineLayout, newFrameLayoutParams());
+ addView(firstLineLayout, newLinearLayoutParams());
mSecondLine = initTextView();
mSecondLine.setPadding(mHorizontalPaddingPx, 0, mHorizontalPaddingPx, 0);
mSecondLine.setEllipsize(TruncateAt.END);
mSecondLine.setVisibility(GONE);
- addView(mSecondLine, newFrameLayoutParams());
+ addView(mSecondLine, newLinearLayoutParams());
addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
@@ -89,7 +89,7 @@
});
}
- private static LayoutParams newFrameLayoutParams() {
+ private static LayoutParams newLinearLayoutParams() {
final LayoutParams lp =
new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.CENTER_HORIZONTAL;
@@ -104,6 +104,7 @@
lp.topMargin = h * 4 / 5;
mSecondLine.setLayoutParams(lp);
mFirstLine.setMinHeight(h);
+ mFirstLine.setPadding(mHorizontalPaddingPx, 0, 0, 0);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 6bfe0a4..2fafb2c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -89,6 +89,7 @@
mDetailContent = (ViewGroup) mDetail.findViewById(android.R.id.content);
mDetailSettingsButton = (TextView) mDetail.findViewById(android.R.id.button2);
mDetailDoneButton = (TextView) mDetail.findViewById(android.R.id.button1);
+ updateDetailText();
mDetail.setVisibility(GONE);
mDetail.setClickable(true);
mBrightnessView = LayoutInflater.from(context).inflate(
@@ -112,6 +113,11 @@
});
}
+ private void updateDetailText() {
+ mDetailDoneButton.setText(R.string.quick_settings_done);
+ mDetailSettingsButton.setText(R.string.quick_settings_more_settings);
+ }
+
public void setBrightnessMirror(BrightnessMirrorController c) {
super.onFinishInflate();
ToggleSlider brightnessSlider = (ToggleSlider) findViewById(R.id.brightness_slider);
@@ -150,6 +156,7 @@
if (mListening) {
refreshAllTiles();
}
+ updateDetailText();
}
@Override
@@ -525,6 +532,12 @@
};
private final AnimatorListenerAdapter mHideGridContentWhenDone = new AnimatorListenerAdapter() {
+ public void onAnimationCancel(Animator animation) {
+ // If we have been cancelled, remove the listener so that onAnimationEnd doesn't get
+ // called, this will avoid accidentally turning off the grid when we don't want to.
+ animation.removeListener(this);
+ };
+
@Override
public void onAnimationEnd(Animator animation) {
setGridContentVisibility(false);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 2b071cc..cb685fe 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -373,6 +373,7 @@
public boolean activityOut;
public int overlayIconId;
public boolean filter;
+ public boolean isOverlayIconWide;
@Override
public boolean copyTo(State other) {
@@ -380,13 +381,15 @@
final boolean changed = o.enabled != enabled
|| o.connected != connected || o.activityIn != activityIn
|| o.activityOut != activityOut
- || o.overlayIconId != overlayIconId;
+ || o.overlayIconId != overlayIconId
+ || o.isOverlayIconWide != isOverlayIconWide;
o.enabled = enabled;
o.connected = connected;
o.activityIn = activityIn;
o.activityOut = activityOut;
o.overlayIconId = overlayIconId;
o.filter = filter;
+ o.isOverlayIconWide = isOverlayIconWide;
return super.copyTo(other) || changed;
}
@@ -399,6 +402,7 @@
rt.insert(rt.length() - 1, ",activityOut=" + activityOut);
rt.insert(rt.length() - 1, ",overlayIconId=" + overlayIconId);
rt.insert(rt.length() - 1, ",filter=" + filter);
+ rt.insert(rt.length() - 1, ",wideOverlayIcon=" + isOverlayIconWide);
return rt;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index e6175d2..8d7edb9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -230,7 +230,7 @@
final int w = MeasureSpec.getSize(widthMeasureSpec);
final int h = MeasureSpec.getSize(heightMeasureSpec);
final int iconSpec = exactly(mIconSizePx);
- mIcon.measure(iconSpec, iconSpec);
+ mIcon.measure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.AT_MOST), iconSpec);
labelView().measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.AT_MOST));
if (mDual) {
mDivider.measure(widthMeasureSpec, exactly(mDivider.getLayoutParams().height));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
index 0ecdeaa..cfcd74e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
@@ -37,11 +37,16 @@
private ImageView mIn;
private ImageView mOut;
+ private int mWideOverlayIconStartPadding;
+
public SignalTileView(Context context) {
super(context);
mIn = addTrafficView(R.drawable.ic_qs_signal_in);
mOut = addTrafficView(R.drawable.ic_qs_signal_out);
+
+ mWideOverlayIconStartPadding = context.getResources().getDimensionPixelSize(
+ R.dimen.wide_type_icon_start_padding_qs);
}
private ImageView addTrafficView(int icon) {
@@ -106,6 +111,11 @@
} else {
mOverlay.setVisibility(GONE);
}
+ if (s.overlayIconId > 0 && s.isOverlayIconWide) {
+ mSignal.setPaddingRelative(mWideOverlayIconStartPadding, 0, 0, 0);
+ } else {
+ mSignal.setPaddingRelative(0, 0, 0, 0);
+ }
Drawable drawable = mSignal.getDrawable();
if (state.autoMirrorDrawable && drawable != null) {
drawable.setAutoMirrored(true);
@@ -122,10 +132,9 @@
view.animate()
.setDuration(visible ? SHORT_DURATION : DEFAULT_DURATION)
.alpha(newAlpha)
- .withLayer()
.start();
} else {
view.setAlpha(newAlpha);
}
}
-}
\ No newline at end of file
+}
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 8743207..359a259 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -23,10 +23,8 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.TextView;
import com.android.systemui.R;
-import com.android.systemui.qs.DataUsageGraph;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.QSTileView;
import com.android.systemui.qs.SignalTileView;
@@ -34,8 +32,6 @@
import com.android.systemui.statusbar.policy.NetworkController.DataUsageInfo;
import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
-import java.text.DecimalFormat;
-
/** Quick settings tile: Cellular **/
public class CellularTile extends QSTile<QSTile.SignalState> {
private static final Intent CELLULAR_SETTINGS = new Intent().setComponent(new ComponentName(
@@ -95,6 +91,7 @@
: !cb.enabled || cb.airplaneModeEnabled ? R.drawable.ic_qs_signal_disabled
: cb.mobileSignalIconId > 0 ? cb.mobileSignalIconId
: R.drawable.ic_qs_signal_no_signal;
+ state.isOverlayIconWide = cb.isDataTypeIconWide;
state.autoMirrorDrawable = !cb.noSim;
state.overlayIconId = cb.enabled && (cb.dataTypeIconId > 0) && !cb.wifiConnected
? cb.dataTypeIconId
@@ -142,6 +139,7 @@
boolean activityOut;
String enabledDesc;
boolean noSim;
+ boolean isDataTypeIconWide;
}
private final NetworkSignalChangedCallback mCallback = new NetworkSignalChangedCallback() {
@@ -162,7 +160,8 @@
int mobileSignalIconId,
String mobileSignalContentDescriptionId, int dataTypeIconId,
boolean activityIn, boolean activityOut,
- String dataTypeContentDescriptionId, String description, boolean noSim) {
+ String dataTypeContentDescriptionId, String description, boolean noSim,
+ boolean isDataTypeIconWide) {
final CallbackInfo info = new CallbackInfo(); // TODO pool?
info.enabled = enabled;
info.wifiEnabled = mWifiEnabled;
@@ -176,6 +175,7 @@
info.activityOut = activityOut;
info.enabledDesc = description;
info.noSim = noSim;
+ info.isDataTypeIconWide = isDataTypeIconWide;
refreshState(info);
}
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 4fc2ee4..0985812 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -206,7 +206,8 @@
int mobileSignalIconId,
String mobileSignalContentDescriptionId, int dataTypeIconId,
boolean activityIn, boolean activityOut,
- String dataTypeContentDescriptionId, String description, boolean noSim) {
+ String dataTypeContentDescriptionId, String description, boolean noSim,
+ boolean isDataTypeIconWide) {
// noop
}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index b7434fd..34430d9 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -203,8 +203,7 @@
Drawable icon = getFullResIcon(td.resolveInfo, pm);
if (td.userId != UserHandle.myUserId()) {
// Need to badge the icon
- icon = mContext.getPackageManager().getUserBadgedDrawableForDensity(icon,
- new UserHandle(td.userId), null, 0);
+ icon = mContext.getPackageManager().getUserBadgedIcon(icon, new UserHandle(td.userId));
}
if (DEBUG) Log.v(TAG, "Loaded bitmap for task "
+ td + ": " + thumbnail);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 2d114c0..787de4e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -16,10 +16,12 @@
package com.android.systemui.recents;
+import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ActivityNotFoundException;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -137,7 +139,8 @@
// Notify recents to hide itself
Intent intent = new Intent(ACTION_HIDE_RECENTS_ACTIVITY);
intent.setPackage(mContext.getPackageName());
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
+ Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, triggeredFromAltTab);
intent.putExtra(EXTRA_TRIGGERED_FROM_HOME_KEY, triggeredFromHomeKey);
mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
@@ -188,10 +191,14 @@
Task.TaskKey toTaskKey;
if (showNextTask) {
toTaskKey = group.getNextTaskInGroup(task);
- // XXX: We will actually set the appropriate launch animations here
+ launchOpts = ActivityOptions.makeCustomAnimation(mContext,
+ R.anim.recents_launch_next_affiliated_task_target,
+ R.anim.recents_launch_next_affiliated_task_source);
} else {
toTaskKey = group.getPrevTaskInGroup(task);
- // XXX: We will actually set the appropriate launch animations here
+ launchOpts = ActivityOptions.makeCustomAnimation(mContext,
+ R.anim.recents_launch_prev_affiliated_task_target,
+ R.anim.recents_launch_prev_affiliated_task_source);
}
if (toTaskKey != null) {
toTask = stack.findTaskWithId(toTaskKey.id);
@@ -202,7 +209,11 @@
// Return early if there is no next task
if (toTask == null) {
- // XXX: We will actually show a bounce animation here
+ if (showNextTask) {
+ // XXX: Show the next-task bounce animation
+ } else {
+ // XXX: Show the prev-task bounce animation
+ }
return;
}
@@ -241,8 +252,8 @@
mConfig = RecentsConfiguration.reinitialize(mContext, mSystemServicesProxy);
mConfig.updateOnConfigurationChange();
mConfig.getTaskStackBounds(mWindowRect.width(), mWindowRect.height(), mStatusBarHeight,
- mNavBarWidth, mTaskStackBounds);
- if (mConfig.isLandscape && mConfig.transposeRecentsLayoutWithOrientation) {
+ (mConfig.hasTransposedNavBar ? mNavBarWidth : 0), mTaskStackBounds);
+ if (mConfig.isLandscape && mConfig.hasTransposedNavBar) {
mSystemInsets.set(0, mStatusBarHeight, mNavBarWidth, 0);
} else {
mSystemInsets.set(0, mStatusBarHeight, 0, mNavBarHeight);
@@ -314,7 +325,8 @@
// Notify recents to toggle itself
Intent intent = new Intent(ACTION_TOGGLE_RECENTS_ACTIVITY);
intent.setPackage(mContext.getPackageName());
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
+ Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
mLastToggleTime = System.currentTimeMillis();
return;
@@ -385,9 +397,9 @@
toTask);
if (toTransform != null && toTask.key != null) {
Rect toTaskRect = toTransform.rect;
-
- // XXX: Reduce the memory usage the to the task bar height
- Bitmap thumbnail = Bitmap.createBitmap(toTaskRect.width(), toTaskRect.height(),
+ int toHeaderWidth = (int) (mHeaderBar.getMeasuredWidth() * toTransform.scale);
+ int toHeaderHeight = (int) (mHeaderBar.getMeasuredHeight() * toTransform.scale);
+ Bitmap thumbnail = Bitmap.createBitmap(toHeaderWidth, toHeaderHeight,
Bitmap.Config.ARGB_8888);
if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
thumbnail.eraseColor(0xFFff0000);
@@ -401,7 +413,8 @@
mStartAnimationTriggered = false;
return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mStatusBarView,
- thumbnail, toTaskRect.left, toTaskRect.top, this);
+ thumbnail, toTaskRect.left, toTaskRect.top, toTaskRect.width(),
+ toTaskRect.height(), this);
}
// If both the screenshot and thumbnail fails, then just fall back to the default transition
@@ -562,11 +575,35 @@
public void onAnimationStarted() {
// Notify recents to start the enter animation
if (!mStartAnimationTriggered) {
+ // There can be a race condition between the start animation callback and
+ // the start of the new activity (where we register the receiver that listens
+ // to this broadcast, so we add our own receiver and if that gets called, then
+ // we know the activity has not yet started and we can retry sending the broadcast.
+ BroadcastReceiver fallbackReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (getResultCode() == Activity.RESULT_OK) {
+ mStartAnimationTriggered = true;
+ return;
+ }
+
+ // Schedule for the broadcast to be sent again after some time
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ onAnimationStarted();
+ }
+ }, 75);
+ }
+ };
+
+ // Send the broadcast to notify Recents that the animation has started
Intent intent = new Intent(ACTION_START_ENTER_ANIMATION);
intent.setPackage(mContext.getPackageName());
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
- mStartAnimationTriggered = true;
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
+ Intent.FLAG_RECEIVER_FOREGROUND);
+ mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
+ fallbackReceiver, null, Activity.RESULT_CANCELED, null, null);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index ec7799a..8f92027 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -146,6 +146,9 @@
ReferenceCountedTrigger t = new ReferenceCountedTrigger(context, null, null, null);
mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
onEnterAnimationTriggered();
+ // Notify the fallback receiver that we have successfully got the broadcast
+ // See AlternateRecentsComponent.onAnimationStarted()
+ setResultCode(Activity.RESULT_OK);
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 5d8181c..ed5c126 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -57,7 +57,8 @@
/** Layout */
boolean isLandscape;
- boolean transposeRecentsLayoutWithOrientation;
+ boolean hasTransposedSearchBar;
+ boolean hasTransposedNavBar;
/** Loading */
public int maxNumTasksToLoad;
@@ -74,8 +75,9 @@
public float taskStackOverscrollPct;
/** Task view animation and styles */
- public int taskViewEnterFromHomeDuration;
public int taskViewEnterFromHomeDelay;
+ public int taskViewEnterFromHomeDuration;
+ public int taskViewEnterFromHomeStaggerDelay;
public int taskViewExitToHomeDuration;
public int taskViewRemoveAnimDuration;
public int taskViewRemoveAnimTranslationXPx;
@@ -173,8 +175,8 @@
// Layout
isLandscape = res.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
- transposeRecentsLayoutWithOrientation =
- res.getBoolean(R.bool.recents_transpose_layout_with_orientation);
+ hasTransposedSearchBar = res.getBoolean(R.bool.recents_has_transposed_search_bar);
+ hasTransposedNavBar = res.getBoolean(R.bool.recents_has_transposed_nav_bar);
// Insets
displayRect.set(0, 0, dm.widthPixels, dm.heightPixels);
@@ -209,10 +211,12 @@
taskStackTopPaddingPx = res.getDimensionPixelSize(R.dimen.recents_stack_top_padding);
// Task view animation and styles
- taskViewEnterFromHomeDuration =
- res.getInteger(R.integer.recents_animate_task_enter_from_home_duration);
taskViewEnterFromHomeDelay =
res.getInteger(R.integer.recents_animate_task_enter_from_home_delay);
+ taskViewEnterFromHomeDuration =
+ res.getInteger(R.integer.recents_animate_task_enter_from_home_duration);
+ taskViewEnterFromHomeStaggerDelay =
+ res.getInteger(R.integer.recents_animate_task_enter_from_home_stagger_delay);
taskViewExitToHomeDuration =
res.getInteger(R.integer.recents_animate_task_exit_to_home_duration);
taskViewRemoveAnimDuration =
@@ -326,13 +330,12 @@
/** Returns whether the nav bar scrim should be visible. */
public boolean hasNavBarScrim() {
// Only show the scrim if we have recent tasks, and if the nav bar is not transposed
- return !launchedWithNoRecentTasks &&
- (!transposeRecentsLayoutWithOrientation || !isLandscape);
+ return !launchedWithNoRecentTasks && (!hasTransposedNavBar || !isLandscape);
}
/** Returns whether the current layout is horizontal. */
public boolean hasHorizontalLayout() {
- return isLandscape && transposeRecentsLayoutWithOrientation;
+ return isLandscape && hasTransposedSearchBar;
}
/**
@@ -343,7 +346,7 @@
Rect taskStackBounds) {
Rect searchBarBounds = new Rect();
getSearchBarBounds(windowWidth, windowHeight, topInset, searchBarBounds);
- if (isLandscape && transposeRecentsLayoutWithOrientation) {
+ if (isLandscape && hasTransposedSearchBar) {
// In landscape, the search bar appears on the left
taskStackBounds.set(searchBarBounds.right, topInset, windowWidth - rightInset, windowHeight);
} else {
@@ -364,7 +367,7 @@
searchBarSize = 0;
}
- if (isLandscape && transposeRecentsLayoutWithOrientation) {
+ if (isLandscape && hasTransposedSearchBar) {
// In landscape, the search bar appears on the left
searchBarSpaceBounds.set(0, topInset, searchBarSize, windowHeight);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 07a42bd..bbd0a0d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -56,6 +56,7 @@
import android.view.DisplayInfo;
import android.view.SurfaceControl;
import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
import com.android.systemui.recents.Constants;
import java.io.IOException;
@@ -73,6 +74,7 @@
final static BitmapFactory.Options sBitmapOptions;
+ AccessibilityManager mAccm;
ActivityManager mAm;
IActivityManager mIam;
AppWidgetManager mAwm;
@@ -97,6 +99,7 @@
/** Private constructor */
public SystemServicesProxy(Context context) {
+ mAccm = AccessibilityManager.getInstance(context);
mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
mIam = ActivityManagerNative.getDefault();
mAwm = AppWidgetManager.getInstance(context);
@@ -356,7 +359,7 @@
*/
public Drawable getBadgedIcon(Drawable icon, int userId) {
if (userId != UserHandle.myUserId()) {
- icon = mPm.getUserBadgedDrawableForDensity(icon, new UserHandle(userId), null, 0);
+ icon = mPm.getUserBadgedIcon(icon, new UserHandle(userId));
}
return icon;
}
@@ -442,6 +445,15 @@
}
/**
+ * Returns whether touch exploration is currently enabled.
+ */
+ public boolean isTouchExplorationEnabled() {
+ if (mAccm == null) return false;
+
+ return mAccm.isEnabled() && mAccm.isTouchExplorationEnabled();
+ }
+
+ /**
* Returns a global setting.
*/
public int getGlobalSetting(Context context, String setting) {
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 0c6e7b6..1bfb41f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -413,10 +413,8 @@
final SystemServicesProxy ssp =
RecentsTaskLoader.getInstance().getSystemServicesProxy();
ActivityOptions opts = null;
- int thumbnailWidth = transform.rect.width();
- int thumbnailHeight = transform.rect.height();
- if (task.thumbnail != null && thumbnailWidth > 0 && thumbnailHeight > 0 &&
- task.thumbnail.getWidth() > 0 && task.thumbnail.getHeight() > 0) {
+ if (task.thumbnail != null && task.thumbnail.getWidth() > 0 &&
+ task.thumbnail.getHeight() > 0) {
Bitmap b;
if (tv != null) {
// Disable any focused state before we draw the header
@@ -424,7 +422,11 @@
tv.unsetFocusedTask();
}
- b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ARGB_8888);
+ float scale = tv.getScaleX();
+ int fromHeaderWidth = (int) (tv.mHeaderView.getMeasuredWidth() * scale);
+ int fromHeaderHeight = (int) (tv.mHeaderView.getMeasuredHeight() * scale);
+ b = Bitmap.createBitmap(fromHeaderWidth, fromHeaderHeight,
+ Bitmap.Config.ARGB_8888);
if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
b.eraseColor(0xFFff0000);
} else {
@@ -435,7 +437,7 @@
}
} else {
// Notify the system to skip the thumbnail layer by using an ALPHA_8 bitmap
- b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ALPHA_8);
+ b = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
}
ActivityOptions.OnAnimationStartedListener animStartedListener = null;
if (lockToTask) {
@@ -456,7 +458,8 @@
};
}
opts = ActivityOptions.makeThumbnailAspectScaleUpAnimation(sourceView,
- b, offsetX, offsetY, animStartedListener);
+ b, offsetX, offsetY, transform.rect.width(), transform.rect.height(),
+ animStartedListener);
}
final ActivityOptions launchOpts = opts;
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 dbed136..895b9d1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -22,11 +22,15 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.DozeTrigger;
+import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.RecentsPackageMonitor;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
@@ -67,6 +71,7 @@
DebugOverlayView mDebugOverlay;
Rect mTaskStackBounds = new Rect();
int mFocusedTaskIndex = -1;
+ int mPrevAccessibilityFocusedIndex = -1;
// Optimizations
int mStackViewsAnimationDuration;
@@ -244,6 +249,9 @@
/** Synchronizes the views with the model */
boolean synchronizeStackViewsWithModel() {
if (mStackViewsDirty) {
+ RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+ SystemServicesProxy ssp = loader.getSystemServicesProxy();
+
// Get all the task transforms
ArrayList<Task> tasks = mStack.getTasks();
float stackScroll = mStackScroller.getStackScroll();
@@ -293,6 +301,18 @@
// Animate the task into place
tv.updateViewPropertiesToTaskTransform(mCurrentTaskTransforms.get(taskIndex),
mStackViewsAnimationDuration);
+
+ // Request accessibility focus on the next view if we removed the task
+ // that previously held accessibility focus
+ childCount = getChildCount();
+ if (childCount > 0 && ssp.isTouchExplorationEnabled()) {
+ TaskView atv = (TaskView) getChildAt(childCount - 1);
+ int indexOfTask = mStack.indexOfTask(atv.getTask());
+ if (mPrevAccessibilityFocusedIndex != indexOfTask) {
+ tv.requestAccessibilityFocus();
+ mPrevAccessibilityFocusedIndex = indexOfTask;
+ }
+ }
}
// Reset the request-synchronize params
@@ -432,6 +452,22 @@
}
@Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ int childCount = getChildCount();
+ if (childCount > 0) {
+ TaskView backMostTask = (TaskView) getChildAt(0);
+ TaskView frontMostTask = (TaskView) getChildAt(childCount - 1);
+ event.setFromIndex(mStack.indexOfTask(backMostTask.getTask()));
+ event.setToIndex(mStack.indexOfTask(frontMostTask.getTask()));
+ event.setContentDescription(frontMostTask.getTask().activityLabel);
+ }
+ event.setItemCount(mStack.getTaskCount());
+ event.setScrollY(mStackScroller.mScroller.getCurrY());
+ event.setMaxScrollY(mStackScroller.progressToScrollRange(mLayoutAlgorithm.mMaxScrollP));
+ }
+
+ @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mTouchHandler.onInterceptTouchEvent(ev);
}
@@ -447,6 +483,8 @@
// Synchronize the views
synchronizeStackViewsWithModel();
clipTaskViews();
+ // Notify accessibility
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
}
/** Computes the stack and task rects */
@@ -623,6 +661,15 @@
mStartEnterAnimationCompleted = true;
// Start dozing
mUIDozeTrigger.startDozing();
+ // Focus the first view if accessibility is enabled
+ RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+ SystemServicesProxy ssp = loader.getSystemServicesProxy();
+ int childCount = getChildCount();
+ if (childCount > 0 && ssp.isTouchExplorationEnabled()) {
+ TaskView tv = ((TaskView) getChildAt(childCount - 1));
+ tv.requestAccessibilityFocus();
+ mPrevAccessibilityFocusedIndex = mStack.indexOfTask(tv.getTask());
+ }
}
});
}
@@ -812,6 +859,11 @@
public void prepareViewToEnterPool(TaskView tv) {
Task task = tv.getTask();
+ // Clear the accessibility focus for that view
+ if (tv.isAccessibilityFocused()) {
+ tv.clearAccessibilityFocus();
+ }
+
// Report that this tasks's data is no longer being used
RecentsTaskLoader.getInstance().unloadTaskData(task);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index eecc170..4563597 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -284,7 +284,7 @@
float scaledWindowInsetTop = (int) (taskScale * windowInsetTop);
float scaledTranslationY = taskRect.top + transform.translationY -
(scaledWindowInsetTop + scaledYOffset);
- startDelay = mConfig.taskViewEnterFromHomeDelay;
+ startDelay = mConfig.taskViewEnterFromHomeStaggerDelay;
// Animate the top clip
mViewBounds.animateClipTop(windowInsetTop, duration,
@@ -410,8 +410,8 @@
} else if (mConfig.launchedFromHome) {
// Animate the tasks up
int frontIndex = (ctx.currentStackViewCount - ctx.currentStackViewIndex - 1);
- int delay = mConfig.taskBarEnterAnimDelay +
- frontIndex * mConfig.taskViewEnterFromHomeDelay;
+ int delay = mConfig.taskViewEnterFromHomeDelay +
+ frontIndex * mConfig.taskViewEnterFromHomeStaggerDelay;
if (Constants.DebugFlags.App.EnableShadows) {
animate().translationZ(transform.translationZ);
}
@@ -839,25 +839,28 @@
@Override
public void onClick(final View v) {
- // We purposely post the handler delayed to allow for the touch feedback to draw
final TaskView tv = this;
- postDelayed(new Runnable() {
- @Override
- public void run() {
- if (Constants.DebugFlags.App.EnableTaskFiltering && v == mHeaderView.mApplicationIcon) {
- mCb.onTaskViewAppIconClicked(tv);
- } else if (v == mHeaderView.mDismissButton) {
- dismissTask();
- } else {
- if (v == mActionButtonView) {
- // Reset the translation of the action button before we animate it out
- mActionButtonView.setTranslationZ(0f);
+ final boolean delayViewClick = (v != this) && (v != mActionButtonView);
+ if (delayViewClick) {
+ // We purposely post the handler delayed to allow for the touch feedback to draw
+ postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (Constants.DebugFlags.App.EnableTaskFiltering && v == mHeaderView.mApplicationIcon) {
+ mCb.onTaskViewAppIconClicked(tv);
+ } else if (v == mHeaderView.mDismissButton) {
+ dismissTask();
}
- mCb.onTaskViewClicked(tv, tv.getTask(),
- (v == mFooterView || v == mActionButtonView));
}
+ }, 125);
+ } else {
+ if (v == mActionButtonView) {
+ // Reset the translation of the action button before we animate it out
+ mActionButtonView.setTranslationZ(0f);
}
- }, 125);
+ mCb.onTaskViewClicked(tv, tv.getTask(),
+ (v == mFooterView || v == mActionButtonView));
+ }
}
/**** View.OnLongClickListener Implementation ****/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 1c4556f..f7e0c83 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -39,6 +39,7 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
@@ -68,8 +69,10 @@
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
+import android.view.ViewStub;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
import android.view.animation.AnimationUtils;
import android.widget.DateTimeView;
import android.widget.ImageView;
@@ -91,6 +94,7 @@
import com.android.systemui.statusbar.phone.KeyguardTouchDelegate;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.HeadsUpNotificationView;
+import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import java.util.ArrayList;
@@ -159,6 +163,7 @@
final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();
protected int mLayoutDirection = -1; // invalid
+ protected AccessibilityManager mAccessibilityManager;
private Locale mLocale;
private float mFontScale;
@@ -260,10 +265,12 @@
final boolean isActivity = pendingIntent.isActivity();
if (isActivity) {
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
+ final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
+ mContext, pendingIntent.getIntent(), mCurrentUserId);
dismissKeyguardThenExecute(new OnDismissAction() {
@Override
public boolean onDismiss() {
- if (keyguardShowing) {
+ if (keyguardShowing && !afterKeyguardGone) {
try {
ActivityManagerNative.getDefault()
.keyguardWaitingForActivityDrawn();
@@ -277,7 +284,7 @@
}
boolean handled = superOnClickHandler(view, pendingIntent, fillInIntent);
- overrideActivityPendingAppTransition(keyguardShowing);
+ overrideActivityPendingAppTransition(keyguardShowing && !afterKeyguardGone);
// close the shade if it was open
if (handled) {
@@ -287,7 +294,7 @@
// Wait for activity start.
return handled;
}
- }, false /* afterKeyguardGone */);
+ }, afterKeyguardGone);
return true;
} else {
return super.onClickHandler(view, pendingIntent, fillInIntent);
@@ -438,6 +445,9 @@
mNotificationData = new NotificationData(this);
+ mAccessibilityManager = (AccessibilityManager)
+ mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+
mDreamManager = IDreamManager.Stub.asInterface(
ServiceManager.checkService(DreamService.DREAM_SERVICE));
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -678,19 +688,11 @@
protected void applyColorsAndBackgrounds(StatusBarNotification sbn,
NotificationData.Entry entry) {
- PackageManager pmUser = getPackageManagerForUser(
- entry.notification.getUser().getIdentifier());
- int version = 0;
- try {
- ApplicationInfo info = pmUser.getApplicationInfo(sbn.getPackageName(), 0);
- version = info.targetSdkVersion;
- } catch (NameNotFoundException ex) {
- Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
- }
if (entry.expanded.getId() != com.android.internal.R.id.status_bar_latest_event_content) {
// Using custom RemoteViews
- if (version >= Build.VERSION_CODES.GINGERBREAD && version < Build.VERSION_CODES.L) {
+ if (entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD
+ && entry.targetSdk < Build.VERSION_CODES.L) {
entry.row.setShowingLegacyBackground(true);
entry.legacy = true;
}
@@ -706,7 +708,7 @@
}
if (entry.icon != null) {
- if (version >= Build.VERSION_CODES.L) {
+ if (entry.targetSdk >= Build.VERSION_CODES.L) {
entry.icon.setColorFilter(mContext.getResources().getColor(android.R.color.white));
} else {
entry.icon.setColorFilter(null);
@@ -763,20 +765,102 @@
}, false /* afterKeyguardGone */);
}
+ private void inflateGuts(ExpandableNotificationRow row) {
+ ViewStub stub = (ViewStub) row.findViewById(R.id.notification_guts_stub);
+ if (stub != null) {
+ stub.inflate();
+ }
+ final StatusBarNotification sbn = row.getStatusBarNotification();
+ PackageManager pmUser = getPackageManagerForUser(
+ sbn.getUser().getIdentifier());
+ row.setTag(sbn.getPackageName());
+ final View guts = row.findViewById(R.id.notification_guts);
+ final String pkg = sbn.getPackageName();
+ String appname = pkg;
+ Drawable pkgicon = null;
+ int appUid = -1;
+ try {
+ final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
+ PackageManager.GET_UNINSTALLED_PACKAGES
+ | PackageManager.GET_DISABLED_COMPONENTS);
+ if (info != null) {
+ appname = String.valueOf(pmUser.getApplicationLabel(info));
+ pkgicon = pmUser.getApplicationIcon(info);
+ appUid = info.uid;
+ }
+ } catch (NameNotFoundException e) {
+ // app is gone, just show package name and generic icon
+ pkgicon = pmUser.getDefaultActivityIcon();
+ }
+ ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(pkgicon);
+ ((DateTimeView) row.findViewById(R.id.timestamp)).setTime(sbn.getPostTime());
+ ((TextView) row.findViewById(R.id.pkgname)).setText(appname);
+ final View settingsButton = guts.findViewById(R.id.notification_inspect_item);
+ final View appSettingsButton
+ = guts.findViewById(R.id.notification_inspect_app_provided_settings);
+ if (appUid >= 0) {
+ final int appUidF = appUid;
+ settingsButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ startAppNotificationSettingsActivity(pkg, appUidF);
+ }
+ });
+
+ final Intent appSettingsQueryIntent
+ = new Intent(Intent.ACTION_MAIN)
+ .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
+ .setPackage(pkg);
+ List<ResolveInfo> infos = pmUser.queryIntentActivities(appSettingsQueryIntent, 0);
+ if (infos.size() > 0) {
+ appSettingsButton.setVisibility(View.VISIBLE);
+ appSettingsButton.setContentDescription(
+ mContext.getResources().getString(
+ R.string.status_bar_notification_app_settings_title,
+ appname
+ ));
+ final Intent appSettingsLaunchIntent = new Intent(appSettingsQueryIntent)
+ .setClassName(pkg, infos.get(0).activityInfo.name);
+ appSettingsButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ startAppOwnNotificationSettingsActivity(appSettingsLaunchIntent,
+ sbn.getId(),
+ sbn.getTag(),
+ appUidF);
+ }
+ });
+ } else {
+ appSettingsButton.setVisibility(View.GONE);
+ }
+ } else {
+ settingsButton.setVisibility(View.GONE);
+ appSettingsButton.setVisibility(View.GONE);
+ }
+
+ }
+
protected SwipeHelper.LongPressListener getNotificationLongClicker() {
return new SwipeHelper.LongPressListener() {
@Override
public boolean onLongPress(View v, int x, int y) {
dismissPopups();
+ if (!(v instanceof ExpandableNotificationRow)) {
+ return false;
+ }
if (v.getWindowToken() == null) {
Log.e(TAG, "Trying to show notification guts, but not attached to window");
return false;
}
+ inflateGuts((ExpandableNotificationRow) v);
+
// Assume we are a status_bar_notification_row
final NotificationGuts guts = (NotificationGuts) v.findViewById(
R.id.notification_guts);
+ if (guts == null) {
+ // This view has no guts. Examples are the more card or the dismiss all view
+ return false;
+ }
// Already showing?
if (guts.getVisibility() == View.VISIBLE) {
@@ -1189,67 +1273,6 @@
row.setExpansionLogger(this, entry.notification.getKey());
}
- // the notification inspector (see SwipeHelper.setLongPressListener)
- row.setTag(sbn.getPackageName());
- final View guts = row.findViewById(R.id.notification_guts);
- final String pkg = entry.notification.getPackageName();
- String appname = pkg;
- Drawable pkgicon = null;
- int appUid = -1;
- try {
- final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
- PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS);
- if (info != null) {
- appname = String.valueOf(pmUser.getApplicationLabel(info));
- pkgicon = pmUser.getApplicationIcon(info);
- appUid = info.uid;
- }
- } catch (NameNotFoundException e) {
- // app is gone, just show package name and generic icon
- pkgicon = pmUser.getDefaultActivityIcon();
- }
- ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(pkgicon);
- ((DateTimeView) row.findViewById(R.id.timestamp)).setTime(entry.notification.getPostTime());
- ((TextView) row.findViewById(R.id.pkgname)).setText(appname);
- final View settingsButton = guts.findViewById(R.id.notification_inspect_item);
- final View appSettingsButton
- = guts.findViewById(R.id.notification_inspect_app_provided_settings);
- if (appUid >= 0) {
- final int appUidF = appUid;
- settingsButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- startAppNotificationSettingsActivity(pkg, appUidF);
- }
- });
-
- final Intent appSettingsQueryIntent
- = new Intent(Intent.ACTION_MAIN)
- .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
- .setPackage(pkg);
- List<ResolveInfo> infos = pmUser.queryIntentActivities(appSettingsQueryIntent, 0);
- if (infos.size() > 0) {
- appSettingsButton.setVisibility(View.VISIBLE);
- appSettingsButton.setContentDescription(
- mContext.getResources().getString(
- R.string.status_bar_notification_app_settings_title,
- appname
- ));
- final Intent appSettingsLaunchIntent = new Intent(appSettingsQueryIntent)
- .setClassName(pkg, infos.get(0).activityInfo.name);
- appSettingsButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- startAppOwnNotificationSettingsActivity(appSettingsLaunchIntent,
- sbn.getId(),
- sbn.getTag(),
- appUidF);
- }
- });
- }
- } else {
- settingsButton.setVisibility(View.GONE);
- appSettingsButton.setVisibility(View.GONE);
- }
-
workAroundBadLayerDrawableOpacity(row);
View vetoButton = updateNotificationVetoButton(row, sbn);
vetoButton.setContentDescription(mContext.getString(
@@ -1319,15 +1342,23 @@
}
}
+ // Extract target SDK version.
+ try {
+ ApplicationInfo info = pmUser.getApplicationInfo(sbn.getPackageName(), 0);
+ entry.targetSdk = info.targetSdkVersion;
+ } catch (NameNotFoundException ex) {
+ Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
+ }
+
if (publicViewLocal == null) {
// Add a basic notification template
publicViewLocal = LayoutInflater.from(mContext).inflate(
- com.android.internal.R.layout.notification_template_material_base,
+ R.layout.notification_public_default,
expandedPublic, false);
publicViewLocal.setIsRootNamespace(true);
expandedPublic.setContractedChild(publicViewLocal);
- final TextView title = (TextView) publicViewLocal.findViewById(com.android.internal.R.id.title);
+ final TextView title = (TextView) publicViewLocal.findViewById(R.id.title);
try {
title.setText(pmUser.getApplicationLabel(
pmUser.getApplicationInfo(entry.notification.getPackageName(), 0)));
@@ -1335,10 +1366,9 @@
title.setText(entry.notification.getPackageName());
}
- final ImageView icon = (ImageView) publicViewLocal.findViewById(
- com.android.internal.R.id.icon);
+ final ImageView icon = (ImageView) publicViewLocal.findViewById(R.id.icon);
final ImageView profileBadge = (ImageView) publicViewLocal.findViewById(
- com.android.internal.R.id.profile_badge_line3);
+ R.id.profile_badge_line3);
final StatusBarIcon ic = new StatusBarIcon(entry.notification.getPackageName(),
entry.notification.getUser(),
@@ -1349,12 +1379,17 @@
Drawable iconDrawable = StatusBarIconView.getIcon(mContext, ic);
icon.setImageDrawable(iconDrawable);
- if (mNotificationColorUtil.isGrayscaleIcon(iconDrawable)) {
+ if (entry.targetSdk >= Build.VERSION_CODES.L
+ || mNotificationColorUtil.isGrayscaleIcon(iconDrawable)) {
icon.setBackgroundResource(
com.android.internal.R.drawable.notification_icon_legacy_bg);
int padding = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_large_icon_circle_padding);
icon.setPadding(padding, padding, padding, padding);
+ if (sbn.getNotification().color != Notification.COLOR_DEFAULT) {
+ icon.getBackground().setColorFilter(
+ sbn.getNotification().color, PorterDuff.Mode.SRC_ATOP);
+ }
}
if (profileBadge != null) {
@@ -1369,16 +1404,13 @@
}
final View privateTime = contentViewLocal.findViewById(com.android.internal.R.id.time);
+ final DateTimeView time = (DateTimeView) publicViewLocal.findViewById(R.id.time);
if (privateTime != null && privateTime.getVisibility() == View.VISIBLE) {
- final View timeStub = publicViewLocal.findViewById(com.android.internal.R.id.time);
- timeStub.setVisibility(View.VISIBLE);
- final DateTimeView dateTimeView = (DateTimeView)
- publicViewLocal.findViewById(com.android.internal.R.id.time);
- dateTimeView.setTime(entry.notification.getNotification().when);
+ time.setVisibility(View.VISIBLE);
+ time.setTime(entry.notification.getNotification().when);
}
- final TextView text = (TextView) publicViewLocal.findViewById(
- com.android.internal.R.id.text);
+ final TextView text = (TextView) publicViewLocal.findViewById(R.id.text);
if (text != null) {
text.setText(R.string.notification_hidden_text);
text.setTextAppearance(mContext,
@@ -1418,7 +1450,7 @@
row.setUserExpanded(userExpanded);
}
row.setUserLocked(userLocked);
-
+ row.setStatusBarNotification(entry.notification);
return true;
}
@@ -1440,6 +1472,9 @@
public void onClick(final View v) {
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
+ final boolean afterKeyguardGone = mIntent.isActivity()
+ && PreviewInflater.wouldLaunchResolverActivity(mContext, mIntent.getIntent(),
+ mCurrentUserId);
dismissKeyguardThenExecute(new OnDismissAction() {
public boolean onDismiss() {
if (mIsHeadsUp) {
@@ -1448,7 +1483,7 @@
AsyncTask.execute(new Runnable() {
@Override
public void run() {
- if (keyguardShowing) {
+ if (keyguardShowing && !afterKeyguardGone) {
try {
ActivityManagerNative.getDefault()
.keyguardWaitingForActivityDrawn();
@@ -1472,7 +1507,8 @@
// TODO: Dismiss Keyguard.
}
if (mIntent.isActivity()) {
- overrideActivityPendingAppTransition(keyguardShowing);
+ overrideActivityPendingAppTransition(keyguardShowing
+ && !afterKeyguardGone);
}
}
@@ -1490,7 +1526,7 @@
return mIntent != null && mIntent.isActivity();
}
- }, false /* afterKeyguardGone */);
+ }, afterKeyguardGone);
}
}
@@ -1625,7 +1661,7 @@
}
}
boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
- if ((isLockscreenPublicMode() && !showOnKeyguard) ||
+ if ((isLockscreenPublicMode() && !mShowLockscreenNotifications) ||
(onKeyguard && (visibleNotifications >= maxKeyguardNotifications
|| !showOnKeyguard))) {
entry.row.setVisibility(View.GONE);
@@ -1776,7 +1812,7 @@
oldEntry.notification.getNotification().tickerText);
final boolean shouldInterrupt = shouldInterrupt(notification);
- final boolean alertAgain = alertAgain(oldEntry);
+ final boolean alertAgain = alertAgain(oldEntry, n);
boolean updateSuccessful = false;
if (contentsUnchanged && bigContentsUnchanged && headsUpContentsUnchanged
&& publicUnchanged) {
@@ -1911,9 +1947,6 @@
: null;
// Reapply the RemoteViews
- if (entry.row != null) {
- entry.row.resetHeight();
- }
contentView.reapply(mContext, entry.expanded, mOnClickHandler);
if (bigContentView != null && entry.getBigContentView() != null) {
bigContentView.reapply(mContext, entry.getBigContentView(),
@@ -1931,7 +1964,9 @@
} else {
entry.row.setOnClickListener(null);
}
+ entry.row.setStatusBarNotification(notification);
entry.row.notifyContentUpdated();
+ entry.row.resetHeight();
}
protected void notifyHeadsUpScreenOn(boolean screenOn) {
@@ -1940,10 +1975,9 @@
}
}
- private boolean alertAgain(Entry entry) {
- final StatusBarNotification sbn = entry.notification;
- return entry == null || !entry.hasInterrupted()
- || (sbn.getNotification().flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
+ private boolean alertAgain(Entry oldEntry, Notification newNotification) {
+ return oldEntry == null || !oldEntry.hasInterrupted()
+ || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
}
protected boolean shouldInterrupt(StatusBarNotification sbn) {
@@ -1965,10 +1999,13 @@
boolean hasTicker = mHeadsUpTicker && !TextUtils.isEmpty(notification.tickerText);
boolean isAllowed = notification.extras.getInt(Notification.EXTRA_AS_HEADS_UP,
Notification.HEADS_UP_ALLOWED) != Notification.HEADS_UP_NEVER;
+ boolean accessibilityForcesLaunch = isFullscreen
+ && mAccessibilityManager.isTouchExplorationEnabled();
final KeyguardTouchDelegate keyguard = KeyguardTouchDelegate.getInstance(mContext);
boolean interrupt = (isFullscreen || (isHighPriority && (isNoisy || hasTicker)))
&& isAllowed
+ && !accessibilityForcesLaunch
&& mPowerManager.isScreenOn()
&& !keyguard.isShowingAndNotOccluded()
&& !keyguard.isInputRestricted();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index c13593a..9196dc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -20,9 +20,11 @@
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
+import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewStub;
import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageView;
@@ -67,6 +69,8 @@
private boolean mWasReset;
private NotificationGuts mGuts;
+ private StatusBarNotification mStatusBarNotification;
+
public void setIconAnimationRunning(boolean running) {
setIconAnimationRunning(running, mPublicLayout);
setIconAnimationRunning(running, mPrivateLayout);
@@ -112,6 +116,14 @@
}
}
+ public void setStatusBarNotification(StatusBarNotification statusBarNotification) {
+ mStatusBarNotification = statusBarNotification;
+ }
+
+ public StatusBarNotification getStatusBarNotification() {
+ return mStatusBarNotification;
+ }
+
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
@@ -155,7 +167,15 @@
super.onFinishInflate();
mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
- mGuts = (NotificationGuts) findViewById(R.id.notification_guts);
+ ViewStub gutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
+ gutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
+ @Override
+ public void onInflate(ViewStub stub, View inflated) {
+ mGuts = (NotificationGuts) inflated;
+ mGuts.setClipTopAmount(getClipTopAmount());
+ mGuts.setActualHeight(getActualHeight());
+ }
+ });
mVetoButton = findViewById(R.id.veto);
}
@@ -386,7 +406,6 @@
target.animate().cancel();
source.animate()
.alpha(0f)
- .withLayer()
.setStartDelay(delay)
.setDuration(duration)
.withEndAction(new Runnable() {
@@ -397,7 +416,6 @@
});
target.animate()
.alpha(1f)
- .withLayer()
.setStartDelay(delay)
.setDuration(duration);
}
@@ -421,7 +439,9 @@
public void setActualHeight(int height, boolean notifyListeners) {
mPrivateLayout.setActualHeight(height);
mPublicLayout.setActualHeight(height);
- mGuts.setActualHeight(height);
+ if (mGuts != null) {
+ mGuts.setActualHeight(height);
+ }
invalidate();
super.setActualHeight(height, notifyListeners);
}
@@ -443,7 +463,9 @@
super.setClipTopAmount(clipTopAmount);
mPrivateLayout.setClipTopAmount(clipTopAmount);
mPublicLayout.setClipTopAmount(clipTopAmount);
- mGuts.setClipTopAmount(clipTopAmount);
+ if (mGuts != null) {
+ mGuts.setClipTopAmount(clipTopAmount);
+ }
}
public void notifyContentUpdated() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index e31eb7c..502490f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -243,6 +243,14 @@
}
}
+ @Override
+ public boolean hasOverlappingRendering() {
+
+ // This is not really true, but good enough when fading from the contracted to the expanded
+ // layout, and saves us some layers.
+ return false;
+ }
+
private static Paint createInvertPaint() {
final Paint p = new Paint();
final float[] invert = {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index ca1fbe0..34c458a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -48,6 +48,7 @@
private boolean interruption;
public boolean autoRedacted; // whether the redacted notification was generated by us
public boolean legacy; // whether the notification has a legacy, dark background
+ public int targetSdk;
public Entry(StatusBarNotification n, StatusBarIconView ic) {
this.key = n.getKey();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 5883c26..18ef024 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -27,17 +27,21 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
+import com.android.systemui.statusbar.policy.SecurityController;
// Intimately tied to the design of res/layout/signal_cluster_view.xml
public class SignalClusterView
extends LinearLayout
- implements NetworkControllerImpl.SignalCluster {
+ implements NetworkControllerImpl.SignalCluster,
+ SecurityController.SecurityControllerCallback {
static final String TAG = "SignalClusterView";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
NetworkControllerImpl mNC;
+ SecurityController mSC;
+ private boolean mVpnVisible = false;
private boolean mWifiVisible = false;
private int mWifiStrengthId = 0;
private boolean mMobileVisible = false;
@@ -46,10 +50,14 @@
private int mAirplaneIconId = 0;
private String mWifiDescription, mMobileDescription, mMobileTypeDescription;
private boolean mRoaming;
+ private boolean mIsMobileTypeIconWide;
ViewGroup mWifiGroup, mMobileGroup;
- ImageView mWifi, mMobile, mMobileType, mAirplane;
+ ImageView mVpn, mWifi, mMobile, mMobileType, mAirplane;
View mWifiAirplaneSpacer;
+ View mWifiSignalSpacer;
+
+ private int mWideTypeIconStartPadding;
public SignalClusterView(Context context) {
this(context, null);
@@ -68,10 +76,25 @@
mNC = nc;
}
+ public void setSecurityController(SecurityController sc) {
+ if (DEBUG) Log.d(TAG, "SecurityController=" + sc);
+ mSC = sc;
+ mSC.addCallback(this);
+ mVpnVisible = mSC.isVpnEnabled();
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mWideTypeIconStartPadding = getContext().getResources().getDimensionPixelSize(
+ R.dimen.wide_type_icon_start_padding);
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+ mVpn = (ImageView) findViewById(R.id.vpn);
mWifiGroup = (ViewGroup) findViewById(R.id.wifi_combo);
mWifi = (ImageView) findViewById(R.id.wifi_signal);
mMobileGroup = (ViewGroup) findViewById(R.id.mobile_combo);
@@ -79,12 +102,14 @@
mMobileType = (ImageView) findViewById(R.id.mobile_type);
mAirplane = (ImageView) findViewById(R.id.airplane);
mWifiAirplaneSpacer = findViewById(R.id.wifi_airplane_spacer);
+ mWifiSignalSpacer = findViewById(R.id.wifi_signal_spacer);
apply();
}
@Override
protected void onDetachedFromWindow() {
+ mVpn = null;
mWifiGroup = null;
mWifi = null;
mMobileGroup = null;
@@ -95,6 +120,18 @@
super.onDetachedFromWindow();
}
+ // From SecurityController.
+ @Override
+ public void onStateChanged() {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ mVpnVisible = mSC.isVpnEnabled();
+ apply();
+ }
+ });
+ }
+
@Override
public void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription) {
mWifiVisible = visible;
@@ -106,13 +143,15 @@
@Override
public void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon,
- String contentDescription, String typeContentDescription, boolean roaming) {
+ String contentDescription, String typeContentDescription, boolean roaming,
+ boolean isTypeIconWide) {
mMobileVisible = visible;
mMobileStrengthId = strengthIcon;
mMobileTypeId = typeIcon;
mMobileDescription = contentDescription;
mMobileTypeDescription = typeContentDescription;
mRoaming = roaming;
+ mIsMobileTypeIconWide = isTypeIconWide;
apply();
}
@@ -168,6 +207,8 @@
private void apply() {
if (mWifiGroup == null) return;
+ mVpn.setVisibility(mVpnVisible ? View.VISIBLE : View.GONE);
+ if (DEBUG) Log.d(TAG, String.format("vpn: %s", mVpnVisible ? "VISIBLE" : "GONE"));
if (mWifiVisible) {
mWifi.setImageResource(mWifiStrengthId);
mWifiGroup.setContentDescription(mWifiDescription);
@@ -203,6 +244,14 @@
mWifiAirplaneSpacer.setVisibility(View.GONE);
}
+ if (mRoaming && mMobileVisible && mWifiVisible) {
+ mWifiSignalSpacer.setVisibility(View.VISIBLE);
+ } else {
+ mWifiSignalSpacer.setVisibility(View.GONE);
+ }
+
+ mMobile.setPaddingRelative(mIsMobileTypeIconWide ? mWideTypeIconStartPadding : 0, 0, 0, 0);
+
if (DEBUG) Log.d(TAG,
String.format("mobile: %s sig=%d typ=%d",
(mMobileVisible ? "VISIBLE" : "GONE"),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
index c620046..64d80cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
@@ -90,7 +90,6 @@
.alpha(endValue)
.setInterpolator(interpolator)
.setDuration(260)
- .withLayer()
.withEndAction(new Runnable() {
@Override
public void run() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
index 9dfbb27..23810f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
@@ -24,5 +24,5 @@
* Keyguard.
*/
public interface ActivityStarter {
- public void startActivity(Intent intent, boolean dismissShade, boolean afterKeyguardGone);
+ public void startActivity(Intent intent, boolean dismissShade);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
new file mode 100644
index 0000000..e14ef12
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -0,0 +1,132 @@
+/*
+ * 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.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.MathUtils;
+
+import com.android.systemui.R;
+
+import java.io.PrintWriter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class DozeParameters {
+ private static final String TAG = "DozeParameters";
+
+ private static final int MAX_DURATION = 10 * 1000;
+
+ private final Context mContext;
+
+ private StepFunction mPulsePeriodFunction;
+
+ public DozeParameters(Context context) {
+ mContext = context;
+ }
+
+ public void dump(PrintWriter pw) {
+ pw.println(" DozeParameters:");
+ pw.print(" getPulseDuration(): "); pw.println(getPulseDuration());
+ pw.print(" getPulseInDuration(): "); pw.println(getPulseInDuration());
+ pw.print(" getPulseInVisibleDuration(): "); pw.println(getPulseVisibleDuration());
+ pw.print(" getPulseOutDuration(): "); pw.println(getPulseOutDuration());
+ pw.print(" getPulseStartDelay(): "); pw.println(getPulseStartDelay());
+ pw.print(" getPulsePeriodFunction(): "); pw.println(getPulsePeriodFunction());
+ }
+
+ public int getPulseDuration() {
+ return getPulseInDuration() + getPulseVisibleDuration() + getPulseOutDuration();
+ }
+
+ public int getPulseInDuration() {
+ return getInt("doze.pulse.duration.in", R.integer.doze_pulse_duration_in);
+ }
+
+ public int getPulseVisibleDuration() {
+ return getInt("doze.pulse.duration.visible", R.integer.doze_pulse_duration_visible);
+ }
+
+ public int getPulseOutDuration() {
+ return getInt("doze.pulse.duration.out", R.integer.doze_pulse_duration_out);
+ }
+
+ public int getPulseStartDelay() {
+ return getInt("doze.pulse.delay", R.integer.doze_pulse_delay);
+ }
+
+ public long getPulsePeriod(long age) {
+ final String spec = getPulsePeriodFunction();
+ if (mPulsePeriodFunction == null || !mPulsePeriodFunction.mSpec.equals(spec)) {
+ mPulsePeriodFunction = StepFunction.parse(spec);
+ }
+ return mPulsePeriodFunction != null ? mPulsePeriodFunction.evaluate(age) : 0;
+ }
+
+ private String getPulsePeriodFunction() {
+ return getString("doze.pulse.period.function", R.string.doze_pulse_period_function);
+ }
+
+ private int getInt(String propName, int resId) {
+ int value = SystemProperties.getInt(propName, mContext.getResources().getInteger(resId));
+ return MathUtils.constrain(value, 0, MAX_DURATION);
+ }
+
+ private String getString(String propName, int resId) {
+ return SystemProperties.get(propName, mContext.getString(resId));
+ }
+
+ private static class StepFunction {
+ private static final Pattern PATTERN = Pattern.compile("(\\d+?)(:(\\d+?))?", 0);
+
+ private String mSpec;
+ private long[] mSteps;
+ private long[] mValues;
+ private long mDefault;
+
+ public static StepFunction parse(String spec) {
+ if (TextUtils.isEmpty(spec)) return null;
+ try {
+ final StepFunction rt = new StepFunction();
+ rt.mSpec = spec;
+ final String[] tokens = spec.split(",");
+ rt.mSteps = new long[tokens.length - 1];
+ rt.mValues = new long[tokens.length - 1];
+ for (int i = 0; i < tokens.length - 1; i++) {
+ final Matcher m = PATTERN.matcher(tokens[i]);
+ if (!m.matches()) throw new IllegalArgumentException("Bad token: " + tokens[i]);
+ rt.mSteps[i] = Long.parseLong(m.group(1));
+ rt.mValues[i] = Long.parseLong(m.group(3));
+ }
+ rt.mDefault = Long.parseLong(tokens[tokens.length - 1]);
+ return rt;
+ } catch (RuntimeException e) {
+ Log.w(TAG, "Error parsing spec: " + spec, e);
+ return null;
+ }
+ }
+
+ public long evaluate(long x) {
+ for (int i = 0; i < mSteps.length; i++) {
+ if (x < mSteps[i]) return mValues[i];
+ }
+ return mDefault;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index f9da30f..e84ca52 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -315,15 +315,15 @@
public void launchCamera() {
mFlashlightController.killFlashlight();
Intent intent = getCameraIntent();
- boolean wouldLaunchResolverActivity = mPreviewInflater.wouldLaunchResolverActivity(intent);
+ boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
+ mContext, intent, mLockPatternUtils.getCurrentUser());
if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
} else {
// We need to delay starting the activity because ResolverActivity finishes itself if
// launched behind lockscreen.
- mActivityStarter.startActivity(intent, false /* dismissShade */,
- wouldLaunchResolverActivity /* afterKeyguardGone */);
+ mActivityStarter.startActivity(intent, false /* dismissShade */);
}
}
@@ -337,8 +337,7 @@
}
});
} else {
- mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */,
- mPreviewInflater.wouldLaunchResolverActivity(PHONE_INTENT));
+ mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index fc737bee..70b6952 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -17,14 +17,10 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
-import android.os.SystemClock;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardViewBase;
@@ -33,7 +29,7 @@
import com.android.systemui.keyguard.KeyguardViewMediator;
import static com.android.keyguard.KeyguardHostView.OnDismissAction;
-import static com.android.keyguard.KeyguardSecurityModel.*;
+import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
/**
* A class which manages the bouncer on the lockscreen.
@@ -62,6 +58,10 @@
public void show() {
ensureView();
if (mRoot.getVisibility() == View.VISIBLE) {
+
+ // show() updates the current security method. This is needed in case we are already
+ // showing and the current security method changed.
+ mKeyguardView.show();
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index dc49118..685c184 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -74,8 +74,10 @@
mKeyguardUserSwitcher.show(true /* animate */);
}
} else {
- mQsPanel.showDetailAdapter(true,
- mQsPanel.getHost().getUserSwitcherController().userDetailAdapter);
+ if (mQsPanel != null) {
+ mQsPanel.showDetailAdapter(true,
+ mQsPanel.getHost().getUserSwitcherController().userDetailAdapter);
+ }
}
} else {
Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
@@ -93,9 +95,12 @@
final UserManager um = UserManager.get(getContext());
String text;
if (um.isUserSwitcherEnabled()) {
- UserSwitcherController controller = mQsPanel.getHost()
- .getUserSwitcherController();
- String currentUser = controller.getCurrentUserName(mContext);
+ String currentUser = null;
+ if (mQsPanel != null) {
+ UserSwitcherController controller = mQsPanel.getHost()
+ .getUserSwitcherController();
+ currentUser = controller.getCurrentUserName(mContext);
+ }
if (TextUtils.isEmpty(currentUser)) {
text = mContext.getString(R.string.accessibility_multi_user_switch_switcher);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
index b633453..79bb1cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
@@ -31,7 +31,6 @@
private final GestureDetector mTaskSwitcherDetector;
private final int mScrollTouchSlop;
private final int mMinFlingVelocity;
- private boolean mInterceptTouches;
private int mTouchDownX;
private int mTouchDownY;
@@ -56,11 +55,11 @@
// task switcher detector
mTaskSwitcherDetector.onTouchEvent(event);
int action = event.getAction();
+ boolean interceptTouches = false;
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
mTouchDownX = (int) event.getX();
mTouchDownY = (int) event.getY();
- mInterceptTouches = false;
break;
}
case MotionEvent.ACTION_MOVE: {
@@ -72,21 +71,19 @@
? xDiff > mScrollTouchSlop && xDiff > yDiff
: yDiff > mScrollTouchSlop && yDiff > xDiff;
if (exceededTouchSlop) {
- mInterceptTouches = true;
+ interceptTouches = true;
return true;
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
- mInterceptTouches = false;
break;
}
- return mInterceptTouches;
+ return interceptTouches;
}
public boolean onTouchEvent(MotionEvent event) {
- if (!mInterceptTouches) return false;
return mTaskSwitcherDetector.onTouchEvent(event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index cf5aebc..c04ca83 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -23,6 +23,8 @@
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.util.MathUtils;
import android.view.MotionEvent;
@@ -60,6 +62,10 @@
private static final float HEADER_RUBBERBAND_FACTOR = 2.05f;
private static final float LOCK_ICON_ACTIVE_SCALE = 1.2f;
+ private static final int DOZE_BACKGROUND_COLOR = 0xff000000;
+ private static final int TAG_KEY_ANIM = R.id.scrim;
+ private static final long DOZE_BACKGROUND_ANIM_DURATION = ScrimController.ANIMATION_DURATION;
+
private KeyguardAffordanceHelper mAfforanceHelper;
private StatusBarHeaderView mHeader;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
@@ -270,6 +276,7 @@
// Calculate quick setting heights.
mQsMinExpansionHeight = mKeyguardShowing ? 0 : mHeader.getCollapsedHeight() + mQsPeekHeight;
mQsMaxExpansionHeight = mHeader.getExpandedHeight() + mQsContainer.getHeight();
+ positionClockAndNotifications();
if (mQsExpanded) {
if (mQsFullyExpanded) {
mQsExpansionHeight = mQsMaxExpansionHeight;
@@ -277,7 +284,6 @@
}
} else {
setQsExpansion(mQsMinExpansionHeight + mLastOverscroll);
- positionClockAndNotifications();
mNotificationStackScroller.setStackHeight(getExpandedHeight());
updateHeader();
}
@@ -559,7 +565,7 @@
}
private boolean isBelowFalsingThreshold() {
- return !mQsTouchAboveFalsingThreshold && mStatusBar.isFalsingThresholdNeeded();
+ return !mQsTouchAboveFalsingThreshold && mStatusBarState == StatusBarState.KEYGUARD;
}
private float getQsExpansionFraction() {
@@ -625,9 +631,10 @@
}
private boolean isInQsArea(float x, float y) {
- return mStatusBarState != StatusBarState.SHADE
- || y <= mNotificationStackScroller.getBottomMostNotificationBottom()
- || y <= mQsContainer.getY() + mQsContainer.getHeight();
+ return mStatusBarState != StatusBarState.SHADE ||
+ (x >= mScrollView.getLeft() && x <= mScrollView.getRight()) &&
+ (y <= mNotificationStackScroller.getBottomMostNotificationBottom()
+ || y <= mQsContainer.getY() + mQsContainer.getHeight());
}
private void handleQsDown(MotionEvent event) {
@@ -1724,13 +1731,58 @@
if (dozing == mDozing) return;
mDozing = dozing;
if (mDozing) {
- setBackgroundColor(0xff000000);
+ setBackgroundColorAlpha(this, DOZE_BACKGROUND_COLOR, 0xff, false /*animate*/);
} else {
- setBackground(null);
+ setBackgroundColorAlpha(this, DOZE_BACKGROUND_COLOR, 0, true /*animate*/);
}
updateKeyguardStatusBarVisibility();
}
+ private static void setBackgroundColorAlpha(final View target, int rgb, int targetAlpha,
+ boolean animate) {
+ int currentAlpha = getBackgroundAlpha(target);
+ if (currentAlpha == targetAlpha) {
+ return;
+ }
+ final int r = Color.red(rgb);
+ final int g = Color.green(rgb);
+ final int b = Color.blue(rgb);
+ Object runningAnim = target.getTag(TAG_KEY_ANIM);
+ if (runningAnim instanceof ValueAnimator) {
+ ((ValueAnimator) runningAnim).cancel();
+ }
+ if (!animate) {
+ target.setBackgroundColor(Color.argb(targetAlpha, r, g, b));
+ return;
+ }
+ ValueAnimator anim = ValueAnimator.ofInt(currentAlpha, targetAlpha);
+ anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ int value = (int) animation.getAnimatedValue();
+ target.setBackgroundColor(Color.argb(value, r, g, b));
+ }
+ });
+ anim.setDuration(DOZE_BACKGROUND_ANIM_DURATION);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ target.setTag(TAG_KEY_ANIM, null);
+ }
+ });
+ anim.start();
+ target.setTag(TAG_KEY_ANIM, anim);
+ }
+
+ private static int getBackgroundAlpha(View view) {
+ if (view.getBackground() instanceof ColorDrawable) {
+ ColorDrawable drawable = (ColorDrawable) view.getBackground();
+ return Color.alpha(drawable.getColor());
+ } else {
+ return 0;
+ }
+ }
+
public void setShadeEmpty(boolean shadeEmpty) {
mShadeEmpty = shadeEmpty;
updateEmptyShadeView();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 7261ea1..006e480 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -684,25 +684,27 @@
removeCallbacks(mPeekRunnable);
mPeekRunnable.run();
}
- } else if (!isFullyCollapsed() && !mTracking) {
+ } else if (!isFullyCollapsed() && !mTracking && !mClosing) {
if (mHeightAnimator != null) {
mHeightAnimator.cancel();
}
mClosing = true;
notifyExpandingStarted();
if (delayed) {
- postDelayed(new Runnable() {
- @Override
- public void run() {
- fling(0, false /* expand */);
- }
- }, 120);
+ postDelayed(mFlingCollapseRunnable, 120);
} else {
fling(0, false /* expand */);
}
}
}
+ private final Runnable mFlingCollapseRunnable = new Runnable() {
+ @Override
+ public void run() {
+ fling(0, false /* expand */);
+ }
+ };
+
public void expand() {
if (DEBUG) logf("expand: " + this);
if (isFullyCollapsed()) {
@@ -728,7 +730,9 @@
public void instantExpand() {
mInstantExpanding = true;
+ mUpdateFlingOnLayout = false;
abortAnimations();
+ cancelPeek();
if (mTracking) {
onTrackingStopped(true /* expands */); // The panel is expanded after this call.
}
@@ -761,6 +765,8 @@
if (mHeightAnimator != null) {
mHeightAnimator.cancel();
}
+ removeCallbacks(mPostCollapseRunnable);
+ removeCallbacks(mFlingCollapseRunnable);
}
protected void startUnlockHintAnimation() {
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 861bf4a..271383f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -149,6 +149,7 @@
import com.android.systemui.statusbar.policy.LocationControllerImpl;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
import com.android.systemui.statusbar.policy.SecurityControllerImpl;
import com.android.systemui.statusbar.policy.UserInfoController;
@@ -786,8 +787,11 @@
mNetworkController.addSignalCluster(signalCluster);
mNetworkController.addSignalCluster(signalClusterKeyguard);
mNetworkController.addSignalCluster(signalClusterQs);
+ signalCluster.setSecurityController(mSecurityController);
signalCluster.setNetworkController(mNetworkController);
+ signalClusterKeyguard.setSecurityController(mSecurityController);
signalClusterKeyguard.setNetworkController(mNetworkController);
+ signalClusterQs.setSecurityController(mSecurityController);
signalClusterQs.setNetworkController(mNetworkController);
final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
if (isAPhone) {
@@ -1078,7 +1082,6 @@
};
private long mLastLockToAppLongPress;
- private AccessibilityManager mAccessibilityManager;
private View.OnLongClickListener mLongPressBackRecentsListener =
new View.OnLongClickListener() {
@Override
@@ -2067,8 +2070,8 @@
}
@Override
- public void startActivity(Intent intent, boolean dismissShade, boolean afterKeyguardGone) {
- startActivityDismissingKeyguard(intent, false, dismissShade, afterKeyguardGone);
+ public void startActivity(Intent intent, boolean dismissShade) {
+ startActivityDismissingKeyguard(intent, false, dismissShade);
}
public ScrimController getScrimController() {
@@ -2957,9 +2960,11 @@
}
public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
- final boolean dismissShade, final boolean afterKeyguardGone) {
+ final boolean dismissShade) {
if (onlyProvisioned && !isDeviceProvisioned()) return;
+ final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
+ mContext, intent, mCurrentUserId);
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
dismissKeyguardThenExecute(new OnDismissAction() {
@Override
@@ -3308,8 +3313,7 @@
}
private void handleStartSettingsActivity(Intent intent, boolean onlyProvisioned) {
- startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */,
- false /* afterKeyguardGone */);
+ startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */);
}
private static class FastColorDrawable extends Drawable {
@@ -3869,10 +3873,6 @@
try {
boolean sendBackLongPress = false;
IActivityManager activityManager = ActivityManagerNative.getDefault();
- if (mAccessibilityManager == null) {
- mAccessibilityManager = (AccessibilityManager)
- mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
- }
boolean isAccessiblityEnabled = mAccessibilityManager.isEnabled();
if (activityManager.isInLockTaskMode() && !isAccessiblityEnabled) {
long time = System.currentTimeMillis();
@@ -3948,6 +3948,14 @@
return !mNotificationData.getActiveNotifications().isEmpty();
}
+ public void wakeUpIfDozing(long time) {
+ if (mDozeServiceHost != null && mDozeServiceHost.isDozing()
+ && mScrimController.isPulsing()) {
+ PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ pm.wakeUp(time);
+ }
+ }
+
private final class ShadeUpdates {
private final ArraySet<String> mVisibleNotifications = new ArraySet<String>();
private final ArraySet<String> mNewVisibleNotifications = new ArraySet<String>();
@@ -3992,6 +4000,10 @@
+ mCurrentDozeService + "]";
}
+ public boolean isDozing() {
+ return mCurrentDozeService != null;
+ }
+
public void firePowerSaveChanged(boolean active) {
for (Callback callback : mCallbacks) {
callback.onPowerSaveChanged(active);
@@ -4034,10 +4046,10 @@
}
@Override
- public void requestPulse(int pulses, boolean delayed, DozeService dozeService) {
+ public void requestPulse(boolean delayed, DozeService dozeService) {
if (dozeService == null) return;
dozeService.stayAwake(PROCESSING_TIME);
- mHandler.obtainMessage(H.REQUEST_PULSE, pulses, delayed ? 1 : 0, dozeService)
+ mHandler.obtainMessage(H.REQUEST_PULSE, delayed ? 1 : 0, 0, dozeService)
.sendToTarget();
}
@@ -4062,9 +4074,9 @@
mCurrentDozeService.startDozing();
}
- private void handleRequestPulse(int pulses, boolean delayed, DozeService dozeService) {
+ private void handleRequestPulse(boolean delayed, DozeService dozeService) {
if (!dozeService.equals(mCurrentDozeService)) return;
- final long stayAwake = mScrimController.pulse(pulses, delayed);
+ final long stayAwake = mScrimController.pulse(delayed);
mCurrentDozeService.stayAwake(stayAwake);
}
@@ -4088,7 +4100,7 @@
if (msg.what == REQUEST_DOZE) {
handleRequestDoze((DozeService) msg.obj);
} else if (msg.what == REQUEST_PULSE) {
- handleRequestPulse(msg.arg1, msg.arg2 != 0, (DozeService) msg.obj);
+ handleRequestPulse(msg.arg1 != 0, (DozeService) msg.obj);
} else if (msg.what == DOZING_STOPPED) {
handleDozingStopped((DozeService) msg.obj);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 455c336..57e5755 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -19,6 +19,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.util.Log;
@@ -36,26 +37,20 @@
*/
public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
private static final String TAG = "ScrimController";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ public static final long ANIMATION_DURATION = 220;
private static final float SCRIM_BEHIND_ALPHA = 0.62f;
private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.55f;
private static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f;
private static final float SCRIM_IN_FRONT_ALPHA = 0.75f;
- private static final long ANIMATION_DURATION = 220;
private static final int TAG_KEY_ANIM = R.id.scrim;
- private static final long PULSE_IN_ANIMATION_DURATION = 1000;
- private static final long PULSE_VISIBLE_DURATION = 3000;
- private static final long PULSE_OUT_ANIMATION_DURATION = 1000;
- private static final long PULSE_INVISIBLE_DURATION = 1000;
- private static final long PULSE_DURATION = PULSE_IN_ANIMATION_DURATION
- + PULSE_VISIBLE_DURATION + PULSE_OUT_ANIMATION_DURATION + PULSE_INVISIBLE_DURATION;
- private static final long PRE_PULSE_DELAY = 1000;
-
private final View mScrimBehind;
private final View mScrimInFront;
private final UnlockMethodCache mUnlockMethodCache;
+ private final DozeParameters mDozeParameters;
private boolean mKeyguardShowing;
private float mFraction;
@@ -71,16 +66,18 @@
private Runnable mOnAnimationFinished;
private boolean mAnimationStarted;
private boolean mDozing;
- private int mPulsesRemaining;
+ private long mPulseEndTime;
private final Interpolator mInterpolator = new DecelerateInterpolator();
private final Interpolator mLinearOutSlowInInterpolator;
public ScrimController(View scrimBehind, View scrimInFront) {
mScrimBehind = scrimBehind;
mScrimInFront = scrimInFront;
- mUnlockMethodCache = UnlockMethodCache.getInstance(scrimBehind.getContext());
- mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(scrimBehind.getContext(),
+ final Context context = scrimBehind.getContext();
+ mUnlockMethodCache = UnlockMethodCache.getInstance(context);
+ mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
android.R.interpolator.linear_out_slow_in);
+ mDozeParameters = new DozeParameters(context);
}
public void setKeyguardShowing(boolean showing) {
@@ -131,23 +128,33 @@
mDozing = dozing;
if (!mDozing) {
cancelPulsing();
+ mAnimateChange = true;
}
scheduleUpdate();
}
- /** When dozing, fade screen contents in and out a few times using the front scrim. */
- public long pulse(int pulses, boolean delayed) {
+ /** When dozing, fade screen contents in and out using the front scrim. */
+ public long pulse(boolean delayed) {
if (!mDozing) return 0;
- mPulsesRemaining = Math.max(pulses, mPulsesRemaining);
- final long delay = delayed ? PRE_PULSE_DELAY : 0;
+ final long now = System.currentTimeMillis();
+ if (DEBUG) Log.d(TAG, "pulse delayed=" + delayed + " mPulseEndTime=" + mPulseEndTime
+ + " now=" + now);
+ if (mPulseEndTime != 0 && mPulseEndTime > now) return mPulseEndTime - now;
+ final long delay = delayed ? mDozeParameters.getPulseStartDelay() : 0;
mScrimInFront.postDelayed(mPulseIn, delay);
- return delay + mPulsesRemaining * PULSE_DURATION;
+ mPulseEndTime = now + delay + mDozeParameters.getPulseDuration();
+ return mPulseEndTime - now;
+ }
+
+ public boolean isPulsing() {
+ return mDozing && mPulseEndTime != 0;
}
private void cancelPulsing() {
- mPulsesRemaining = 0;
+ if (DEBUG) Log.d(TAG, "Cancel pulsing");
mScrimInFront.removeCallbacks(mPulseIn);
mScrimInFront.removeCallbacks(mPulseOut);
+ mPulseEndTime = 0;
}
private void scheduleUpdate() {
@@ -163,7 +170,7 @@
if (mAnimateKeyguardFadingOut) {
setScrimInFrontColor(0f);
setScrimBehindColor(0f);
- }else if (!mKeyguardShowing && !mBouncerShowing) {
+ } else if (!mKeyguardShowing && !mBouncerShowing) {
updateScrimNormal();
setScrimInFrontColor(0);
} else {
@@ -217,8 +224,8 @@
mScrimInFront.setClickable(false);
} else {
- // Eat touch events.
- mScrimInFront.setClickable(true);
+ // Eat touch events (unless dozing).
+ mScrimInFront.setClickable(!mDozing);
}
}
@@ -300,11 +307,9 @@
private final Runnable mPulseIn = new Runnable() {
@Override
public void run() {
- if (DEBUG) Log.d(TAG, "Pulse in, mDozing=" + mDozing
- + " mPulsesRemaining=" + mPulsesRemaining);
- if (!mDozing || mPulsesRemaining == 0) return;
- mPulsesRemaining--;
- mDurationOverride = PULSE_IN_ANIMATION_DURATION;
+ if (DEBUG) Log.d(TAG, "Pulse in, mDozing=" + mDozing);
+ if (!mDozing) return;
+ mDurationOverride = mDozeParameters.getPulseInDuration();
mAnimationDelay = 0;
mAnimateChange = true;
mOnAnimationFinished = mPulseInFinished;
@@ -317,7 +322,7 @@
public void run() {
if (DEBUG) Log.d(TAG, "Pulse in finished, mDozing=" + mDozing);
if (!mDozing) return;
- mScrimInFront.postDelayed(mPulseOut, PULSE_VISIBLE_DURATION);
+ mScrimInFront.postDelayed(mPulseOut, mDozeParameters.getPulseVisibleDuration());
}
};
@@ -326,7 +331,7 @@
public void run() {
if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing);
if (!mDozing) return;
- mDurationOverride = PULSE_OUT_ANIMATION_DURATION;
+ mDurationOverride = mDozeParameters.getPulseOutDuration();
mAnimationDelay = 0;
mAnimateChange = true;
mOnAnimationFinished = mPulseOutFinished;
@@ -337,10 +342,8 @@
private final Runnable mPulseOutFinished = new Runnable() {
@Override
public void run() {
- if (DEBUG) Log.d(TAG, "Pulse out finished, mPulsesRemaining=" + mPulsesRemaining);
- if (mPulsesRemaining > 0) {
- mScrimInFront.postDelayed(mPulseIn, PULSE_INVISIBLE_DURATION);
- }
+ if (DEBUG) Log.d(TAG, "Pulse out finished");
+ mPulseEndTime = 0;
}
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index eeb97e3..15a7229 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -497,20 +497,19 @@
} else if (v == mAlarmStatus && mNextAlarm != null) {
PendingIntent showIntent = mNextAlarm.getShowIntent();
if (showIntent != null && showIntent.isActivity()) {
- mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */,
- false /* afterKeyguardGone */);
+ mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */);
}
}
}
private void startSettingsActivity() {
mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
- true /* dismissShade */, false /* afterKeyguardGone */);
+ true /* dismissShade */);
}
private void startBatteryActivity() {
mActivityStarter.startActivity(new Intent(Intent.ACTION_POWER_USAGE_SUMMARY),
- true /* dismissShade */, false /* afterKeyguardGone */);
+ true /* dismissShade */);
}
public void setQSPanel(QSPanel qsp) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 1811d8d..42cfd39 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -100,6 +100,11 @@
if (!down) {
return mService.onSpacePressed();
}
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ if (down) {
+ mService.wakeUpIfDozing(event.getEventTime());
+ }
}
if (mService.interceptMediaKey(event)) {
return true;
@@ -128,6 +133,10 @@
&& mService.getBarState() == StatusBarState.KEYGUARD
&& !mService.isBouncerShowing()) {
intercept = mDragDownHelper.onInterceptTouchEvent(ev);
+ // wake up on a touch down event, if dozing
+ if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mService.wakeUpIfDozing(ev.getEventTime());
+ }
}
if (!intercept) {
super.onInterceptTouchEvent(ev);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
index b2009c3..7f155a1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -28,6 +28,7 @@
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
+import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
import com.android.systemui.ExpandHelper;
@@ -111,6 +112,7 @@
mContentHolder.setVisibility(View.VISIBLE);
mContentHolder.setAlpha(mMaxAlpha);
mContentHolder.addView(mHeadsUp.row);
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
mSwipeHelper.snapChild(mContentHolder, 1f);
mStartTouchTime = System.currentTimeMillis() + mTouchSensitivityDelay;
@@ -126,6 +128,14 @@
return true;
}
+ @Override
+ protected void onVisibilityChanged(View changedView, int visibility) {
+ super.onVisibilityChanged(changedView, visibility);
+ if (changedView.getVisibility() == VISIBLE) {
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+ }
+ }
+
public boolean isShowing(String key) {
return mHeadsUp != null && mHeadsUp.key.equals(key);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index d9a3e14..16c0e66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -18,10 +18,12 @@
import android.animation.Animator;
import android.animation.ObjectAnimator;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.hardware.input.InputManager;
+import android.media.AudioManager;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.AttributeSet;
@@ -57,6 +59,7 @@
private boolean mSupportsLongpress = true;
private Animator mAnimateToQuiescent = new ObjectAnimator();
private Drawable mBackground;
+ private AudioManager mAudioManager;
private final Runnable mCheckLongPress = new Runnable() {
public void run() {
@@ -99,6 +102,7 @@
setClickable(true);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+ mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
@Override
@@ -251,6 +255,10 @@
return true;
}
+ public void playSoundEffect(int soundConstant) {
+ mAudioManager.playSoundEffect(soundConstant, ActivityManager.getCurrentUser());
+ };
+
public void sendEvent(int action, int flags) {
sendEvent(action, flags, SystemClock.uptimeMillis());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index b64dcbe..2ed9366 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -30,7 +30,8 @@
void onMobileDataSignalChanged(boolean enabled, int mobileSignalIconId,
String mobileSignalContentDescriptionId, int dataTypeIconId,
boolean activityIn, boolean activityOut,
- String dataTypeContentDescriptionId, String description, boolean noSim);
+ String dataTypeContentDescriptionId, String description, boolean noSim,
+ boolean isDataTypeIconWide);
void onAirplaneModeChanged(boolean enabled);
void onMobileDataEnabled(boolean enabled);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 4a6f1a8..4d248c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -63,9 +63,6 @@
static final boolean DEBUG = false;
static final boolean CHATTY = false; // additional diagnostics, but not logspew
- private static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
- private static final int ROAMING_ICON = R.drawable.stat_sys_data_fully_connected_roam;
-
// telephony
boolean mHspaDataDistinguishable;
final TelephonyManager mPhone;
@@ -165,7 +162,8 @@
public interface SignalCluster {
void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription);
void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon,
- String contentDescription, String typeContentDescription, boolean roaming);
+ String contentDescription, String typeContentDescription, boolean roaming,
+ boolean isTypeIconWide);
void setIsAirplaneMode(boolean is, int airplaneIcon);
}
@@ -339,7 +337,9 @@
@Override
public DataUsageInfo getDataUsageInfo() {
final DataUsageInfo info = mMobileDataController.getDataUsageInfo();
- info.carrier = mNetworkName;
+ if (info != null) {
+ info.carrier = mNetworkName;
+ }
return info;
}
@@ -358,6 +358,16 @@
mMobileDataController.setMobileDataEnabled(enabled);
}
+ private boolean isTypeIconWide(int iconId) {
+ return TelephonyIcons.ICON_LTE == iconId || TelephonyIcons.ICON_1X == iconId
+ || TelephonyIcons.ICON_3G == iconId || TelephonyIcons.ICON_4G == iconId;
+ }
+
+ private boolean isQsTypeIconWide(int iconId) {
+ return TelephonyIcons.QS_ICON_LTE == iconId || TelephonyIcons.QS_ICON_1X == iconId
+ || TelephonyIcons.QS_ICON_3G == iconId || TelephonyIcons.QS_ICON_4G == iconId;
+ }
+
public void refreshSignalCluster(SignalCluster cluster) {
if (mDemoMode) return;
cluster.setWifiIndicators(
@@ -374,7 +384,8 @@
mDataTypeIconId,
mContentDescriptionWimax,
mContentDescriptionDataType,
- mDataTypeIconId == ROAMING_ICON);
+ mDataTypeIconId == TelephonyIcons.ROAMING_ICON,
+ false /* isTypeIconWide */ );
} else {
// normal mobile data
cluster.setMobileDataIndicators(
@@ -383,7 +394,8 @@
mDataTypeIconId,
mContentDescriptionPhoneSignal,
mContentDescriptionDataType,
- mDataTypeIconId == ROAMING_ICON);
+ mDataTypeIconId == TelephonyIcons.ROAMING_ICON,
+ isTypeIconWide(mDataTypeIconId));
}
cluster.setIsAirplaneMode(mAirplaneMode, mAirplaneIconId);
}
@@ -409,18 +421,20 @@
if (isEmergencyOnly()) {
cb.onMobileDataSignalChanged(false, mQSPhoneSignalIconId,
mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut,
- mContentDescriptionDataType, null, mNoSim);
+ mContentDescriptionDataType, null, mNoSim, isQsTypeIconWide(mQSDataTypeIconId));
} else {
if (mIsWimaxEnabled && mWimaxConnected) {
// Wimax is special
cb.onMobileDataSignalChanged(true, mQSPhoneSignalIconId,
mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut,
- mContentDescriptionDataType, mNetworkName, mNoSim);
+ mContentDescriptionDataType, mNetworkName, mNoSim,
+ isQsTypeIconWide(mQSDataTypeIconId));
} else {
// Normal mobile data
cb.onMobileDataSignalChanged(mHasMobileDataFeature, mQSPhoneSignalIconId,
mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut,
- mContentDescriptionDataType, mNetworkName, mNoSim);
+ mContentDescriptionDataType, mNetworkName, mNoSim,
+ isQsTypeIconWide(mQSDataTypeIconId));
}
}
cb.onAirplaneModeChanged(mAirplaneMode);
@@ -754,7 +768,7 @@
R.string.accessibility_data_connection_4g);
} else {
mDataIconList = TelephonyIcons.DATA_LTE[mInetCondition];
- mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_lte;
+ mDataTypeIconId = TelephonyIcons.ICON_LTE;
mQSDataTypeIconId = TelephonyIcons.QS_DATA_LTE[mInetCondition];
mContentDescriptionDataType = mContext.getString(
R.string.accessibility_data_connection_lte);
@@ -780,11 +794,11 @@
if (isCdma()) {
if (isCdmaEri()) {
- mDataTypeIconId = ROAMING_ICON;
+ mDataTypeIconId = TelephonyIcons.ROAMING_ICON;
mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
}
} else if (mPhone.isNetworkRoaming()) {
- mDataTypeIconId = ROAMING_ICON;
+ mDataTypeIconId = TelephonyIcons.ROAMING_ICON;
mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
}
}
@@ -928,8 +942,8 @@
intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
boolean wasConnected = mWifiConnected;
mWifiConnected = networkInfo != null && networkInfo.isConnected();
- // If we just connected, grab the inintial signal strength and ssid
- if (mWifiConnected && !wasConnected) {
+ // If Connected grab the signal strength and ssid
+ if (mWifiConnected) {
// try getting it out of the intent first
WifiInfo info = (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
if (info == null) {
@@ -1164,7 +1178,7 @@
// look again; your radios are now airplanes
mContentDescriptionPhoneSignal = mContext.getString(
R.string.accessibility_airplane_mode);
- mAirplaneIconId = FLIGHT_MODE_ICON;
+ mAirplaneIconId = TelephonyIcons.FLIGHT_MODE_ICON;
mPhoneSignalIconId = mDataSignalIconId = mDataTypeIconId = mQSDataTypeIconId = 0;
mQSPhoneSignalIconId = 0;
@@ -1198,11 +1212,11 @@
mQSDataTypeIconId = 0;
if (isCdma()) {
if (isCdmaEri()) {
- mDataTypeIconId = ROAMING_ICON;
+ mDataTypeIconId = TelephonyIcons.ROAMING_ICON;
mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
}
} else if (mPhone.isNetworkRoaming()) {
- mDataTypeIconId = ROAMING_ICON;
+ mDataTypeIconId = TelephonyIcons.ROAMING_ICON;
mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
}
}
@@ -1509,7 +1523,7 @@
if (airplane != null) {
boolean show = airplane.equals("show");
for (SignalCluster cluster : mSignalClusters) {
- cluster.setIsAirplaneMode(show, FLIGHT_MODE_ICON);
+ cluster.setIsAirplaneMode(show, TelephonyIcons.FLIGHT_MODE_ICON);
}
}
String fully = args.getString("fully");
@@ -1540,23 +1554,23 @@
String datatype = args.getString("datatype");
if (datatype != null) {
mDemoDataTypeIconId =
- datatype.equals("1x") ? R.drawable.stat_sys_data_fully_connected_1x :
- datatype.equals("3g") ? R.drawable.stat_sys_data_fully_connected_3g :
- datatype.equals("4g") ? R.drawable.stat_sys_data_fully_connected_4g :
+ datatype.equals("1x") ? TelephonyIcons.ICON_1X :
+ datatype.equals("3g") ? TelephonyIcons.ICON_3G :
+ datatype.equals("4g") ? TelephonyIcons.ICON_4G :
datatype.equals("e") ? R.drawable.stat_sys_data_fully_connected_e :
datatype.equals("g") ? R.drawable.stat_sys_data_fully_connected_g :
datatype.equals("h") ? R.drawable.stat_sys_data_fully_connected_h :
- datatype.equals("lte") ? R.drawable.stat_sys_data_fully_connected_lte :
- datatype.equals("roam") ? ROAMING_ICON :
+ datatype.equals("lte") ? TelephonyIcons.ICON_LTE :
+ datatype.equals("roam") ? TelephonyIcons.ROAMING_ICON :
0;
mDemoQSDataTypeIconId =
- datatype.equals("1x") ? R.drawable.ic_qs_signal_1x :
- datatype.equals("3g") ? R.drawable.ic_qs_signal_3g :
- datatype.equals("4g") ? R.drawable.ic_qs_signal_4g :
+ datatype.equals("1x") ? TelephonyIcons.QS_ICON_1X :
+ datatype.equals("3g") ? TelephonyIcons.QS_ICON_3G :
+ datatype.equals("4g") ? TelephonyIcons.QS_ICON_4G :
datatype.equals("e") ? R.drawable.ic_qs_signal_e :
datatype.equals("g") ? R.drawable.ic_qs_signal_g :
datatype.equals("h") ? R.drawable.ic_qs_signal_h :
- datatype.equals("lte") ? R.drawable.ic_qs_signal_lte :
+ datatype.equals("lte") ? TelephonyIcons.QS_ICON_LTE :
datatype.equals("roam") ? R.drawable.ic_qs_signal_r :
0;
}
@@ -1575,7 +1589,8 @@
mDemoDataTypeIconId,
"Demo",
"Demo",
- mDemoDataTypeIconId == ROAMING_ICON);
+ mDemoDataTypeIconId == TelephonyIcons.ROAMING_ICON,
+ isTypeIconWide(mDemoDataTypeIconId));
}
refreshViews();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
index cdbe494..030cd6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
@@ -20,14 +20,12 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardActivityLauncher;
import com.android.systemui.statusbar.phone.KeyguardPreviewContainer;
import java.util.List;
@@ -107,20 +105,21 @@
return info;
}
- public boolean wouldLaunchResolverActivity(Intent intent) {
- PackageManager packageManager = mContext.getPackageManager();
+ public static boolean wouldLaunchResolverActivity(Context ctx, Intent intent,
+ int currentUserId) {
+ PackageManager packageManager = ctx.getPackageManager();
final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
- intent, PackageManager.MATCH_DEFAULT_ONLY, mLockPatternUtils.getCurrentUser());
+ intent, PackageManager.MATCH_DEFAULT_ONLY, currentUserId);
if (appList.size() == 0) {
return false;
}
ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
- PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
- mLockPatternUtils.getCurrentUser());
+ PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, currentUserId);
return wouldLaunchResolverActivity(resolved, appList);
}
- private boolean wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList) {
+ private static boolean wouldLaunchResolverActivity(
+ ResolveInfo resolved, List<ResolveInfo> appList) {
// If the list contains the above resolved activity, then it can't be
// ResolverActivity itself.
for (int i = 0; i < appList.size(); i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index a15ddaf..2fbb812 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -139,14 +139,14 @@
}
@Override
- public void addCallback(SecurityControllerCallback callback) {
+ public void removeCallback(SecurityControllerCallback callback) {
if (callback == null) return;
if (DEBUG) Log.d(TAG, "removeCallback " + callback);
mCallbacks.remove(callback);
}
@Override
- public void removeCallback(SecurityControllerCallback callback) {
+ public void addCallback(SecurityControllerCallback callback) {
if (callback == null || mCallbacks.contains(callback)) return;
if (DEBUG) Log.d(TAG, "addCallback " + callback);
mCallbacks.add(callback);
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 84c53ce..1f2b918 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -188,5 +188,16 @@
R.drawable.ic_qs_signal_lte
};
+ static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
+ static final int ROAMING_ICON = R.drawable.stat_sys_data_fully_connected_roam;
+ static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte;
+ static final int ICON_3G = R.drawable.stat_sys_data_fully_connected_3g;
+ static final int ICON_4G = R.drawable.stat_sys_data_fully_connected_4g;
+ static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x;
+
+ 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;
+ static final int QS_ICON_1X = R.drawable.ic_qs_signal_1x;
}
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 52fa621..d02826f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -73,6 +73,7 @@
private ArrayList<UserRecord> mUsers = new ArrayList<>();
private Dialog mExitGuestDialog;
+ private Dialog mAddUserDialog;
private int mLastNonGuestUser = UserHandle.USER_OWNER;
private boolean mSimpleUserSwitcher;
private boolean mAddUsersWhenLocked;
@@ -228,8 +229,8 @@
// No guest user. Create one.
id = mUserManager.createGuest(mContext, mContext.getString(R.string.guest_nickname)).id;
} else if (record.isAddUser) {
- id = mUserManager.createUser(
- mContext.getString(R.string.user_new_user_name), 0 /* flags */).id;
+ showAddUserDialog();
+ return;
} else {
id = record.info.id;
}
@@ -260,6 +261,14 @@
mExitGuestDialog.show();
}
+ private void showAddUserDialog() {
+ if (mAddUserDialog != null && mAddUserDialog.isShowing()) {
+ mAddUserDialog.cancel();
+ }
+ mAddUserDialog = new AddUserDialog(mContext);
+ mAddUserDialog.show();
+ }
+
private void exitGuest(int id) {
int newId = UserHandle.USER_OWNER;
if (mLastNonGuestUser != UserHandle.USER_OWNER) {
@@ -534,4 +543,30 @@
}
}
}
+
+ private final class AddUserDialog extends SystemUIDialog implements
+ DialogInterface.OnClickListener {
+
+ public AddUserDialog(Context context) {
+ super(context);
+ setTitle(R.string.user_add_user_title);
+ setMessage(context.getString(R.string.user_add_user_message_short));
+ setButton(DialogInterface.BUTTON_NEGATIVE,
+ context.getString(android.R.string.cancel), this);
+ setButton(DialogInterface.BUTTON_POSITIVE,
+ context.getString(android.R.string.ok), this);
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == BUTTON_NEGATIVE) {
+ cancel();
+ } else {
+ dismiss();
+ int id = mUserManager.createUser(
+ mContext.getString(R.string.user_new_user_name), 0 /* flags */).id;
+ switchToUserId(id);
+ }
+ }
+ }
}
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 6f477ef..67ba8d20 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -40,6 +40,7 @@
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.SpeedBumpView;
+import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.policy.ScrollAdapter;
import com.android.systemui.statusbar.stack.StackScrollState.ViewState;
@@ -645,7 +646,7 @@
@Override
public boolean isAntiFalsingNeeded() {
- return mPhoneStatusBar.isFalsingThresholdNeeded();
+ return mPhoneStatusBar.getBarState() == StatusBarState.KEYGUARD;
}
private void setSwipingInProgress(boolean isSwiped) {
@@ -1546,7 +1547,7 @@
mStackScrollAlgorithm.notifyChildrenChanged(this);
((ExpandableView) child).setOnHeightChangedListener(this);
generateAddAnimation(child, false /* fromMoreCard */);
- updateAnimationState(mAnimationsEnabled && mIsExpanded, child);
+ updateAnimationState(child);
}
public void setAnimationsEnabled(boolean animationsEnabled) {
@@ -1563,6 +1564,11 @@
}
}
+ private void updateAnimationState(View child) {
+ updateAnimationState(mAnimationsEnabled && mIsExpanded, child);
+ }
+
+
private void updateAnimationState(boolean running, View child) {
if (child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
@@ -1960,6 +1966,7 @@
mRequestViewResizeAnimationOnLayout = true;
}
mStackScrollAlgorithm.onReset(view);
+ updateAnimationState(view);
}
private void updateScrollPositionOnExpandInBottom(ExpandableView view) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 7c4c0e8..e4a1c27 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -40,8 +40,6 @@
private static final int MAX_ITEMS_IN_BOTTOM_STACK = 3;
private static final int MAX_ITEMS_IN_TOP_STACK = 3;
- /** When a child is activated, the other cards' alpha fade to this value. */
- private static final float ACTIVATED_INVERSE_ALPHA = 0.9f;
public static final float DIMMED_SCALE = 0.95f;
private int mPaddingBetweenElements;
@@ -270,12 +268,8 @@
childViewState.scale = !mScaleDimmed || !dimmed || isActivatedChild
? 1.0f
: DIMMED_SCALE;
- if (dimmed && activatedChild != null) {
- if (!isActivatedChild) {
- childViewState.alpha *= ACTIVATED_INVERSE_ALPHA;
- } else {
- childViewState.zTranslation += 2.0f * mZDistanceBetweenElements;
- }
+ if (dimmed && isActivatedChild) {
+ childViewState.zTranslation += 2.0f * mZDistanceBetweenElements;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index ece82a1..a69390e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -166,7 +166,7 @@
boolean hasDelays = mAnimationFilter.hasDelays;
boolean isDelayRelevant = yTranslationChanging || zTranslationChanging || scaleChanging ||
alphaChanging || heightChanging || topInsetChanging;
- boolean noAnimation = wasAdded && !mAnimationFilter.hasGoToFullShadeEvent;
+ boolean noAnimation = wasAdded;
long delay = 0;
long duration = mCurrentLength;
if (hasDelays && isDelayRelevant || wasAdded) {
@@ -184,7 +184,7 @@
// start translationY animation
if (yTranslationChanging) {
- if (noAnimation) {
+ if (noAnimation && !mAnimationFilter.hasGoToFullShadeEvent) {
child.setTranslationY(viewState.yTranslation);
} else {
startYTranslationAnimation(child, viewState, duration, delay);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index ffc10a9..fa43f32 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -56,6 +56,7 @@
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.widget.ImageView;
import android.widget.SeekBar;
@@ -430,6 +431,9 @@
public void onConfigurationChanged(Configuration newConfig) {
updateWidth();
+ if (mZenPanel != null) {
+ mZenPanel.updateLocale();
+ }
}
private void updateWidth() {
@@ -1078,6 +1082,7 @@
if (mCallback != null) {
mCallback.onVisible(true);
}
+ announceDialogShown();
}
// Do a little vibrate if applicable (only when going into vibrate mode)
@@ -1094,6 +1099,10 @@
}
}
+ private void announceDialogShown() {
+ mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ }
+
private boolean isShowing() {
return mDialog.isShowing();
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index acb4827..0586a83 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -140,8 +140,7 @@
@Override
public void run() {
getComponent(PhoneStatusBar.class).startActivityDismissingKeyguard(
- ZenModePanel.ZEN_SETTINGS, true /* onlyProvisioned */, true /* dismissShade */,
- false /* afterKeyguardGone */);
+ ZenModePanel.ZEN_SETTINGS, true /* onlyProvisioned */, true /* dismissShade */);
mPanel.postDismiss(mDismissDelay);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index ac7fc25..f829994 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -60,7 +60,7 @@
private static final int[] MINUTE_BUCKETS = DEBUG
? new int[] { 0, 1, 2, 5, 15, 30, 45, 60, 120, 180, 240, 480 }
- : new int[] { 15, 30, 45, 60, 120, 180, 240, 480 };
+ : ZenModeConfig.MINUTE_BUCKETS;
private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
@@ -68,7 +68,6 @@
private static final int TIME_CONDITION_INDEX = 1;
private static final int FIRST_CONDITION_INDEX = 2;
private static final float SILENT_HINT_PULSE_SCALE = 1.1f;
- private static final int ZERO_VALUE_MS = 20 * SECONDS_MS;
public static final Intent ZEN_SETTINGS = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
@@ -121,10 +120,7 @@
super.onFinishInflate();
mZenButtons = (SegmentedButtons) findViewById(R.id.zen_buttons);
- mZenButtons.addButton(R.string.interruption_level_none, Global.ZEN_MODE_NO_INTERRUPTIONS);
- mZenButtons.addButton(R.string.interruption_level_priority,
- Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- mZenButtons.addButton(R.string.interruption_level_all, Global.ZEN_MODE_OFF);
+ addZenButtons();
mZenButtons.setCallback(mZenButtonsCallback);
mZenSubhead = findViewById(R.id.zen_subhead);
@@ -174,6 +170,13 @@
setExpanded(false);
}
+ private void addZenButtons() {
+ mZenButtons.addButton(R.string.interruption_level_none, Global.ZEN_MODE_NO_INTERRUPTIONS);
+ mZenButtons.addButton(R.string.interruption_level_priority,
+ Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+ mZenButtons.addButton(R.string.interruption_level_all, Global.ZEN_MODE_OFF);
+ }
+
public void setHidden(boolean hidden) {
if (mHidden == hidden) return;
mHidden = hidden;
@@ -213,7 +216,7 @@
mBucketIndex = -1;
} else {
mBucketIndex = DEFAULT_BUCKET_INDEX;
- mTimeCondition = newTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
+ mTimeCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
}
if (DEBUG) Log.d(mTag, "Initial bucket index: " + mBucketIndex);
mConditions = null; // reset conditions
@@ -234,6 +237,11 @@
mController.addCallback(mZenCallback);
}
+ public void updateLocale() {
+ mZenButtons.removeAllViews();
+ addZenButtons();
+ }
+
private void setExitCondition(Condition exitCondition) {
if (sameConditionId(mExitCondition, exitCondition)) return;
mExitCondition = exitCondition;
@@ -254,7 +262,7 @@
}
private void refreshExitConditionText() {
- final String forever = mContext.getString(R.string.zen_mode_forever);
+ final String forever = mContext.getString(com.android.internal.R.string.zen_mode_forever);
if (mExitCondition == null) {
mExitConditionText = forever;
} else if (ZenModeConfig.isValidCountdownConditionId(mExitCondition.id)) {
@@ -330,24 +338,7 @@
if (time == 0) return null;
final long span = time - System.currentTimeMillis();
if (span <= 0 || span > MAX_BUCKET_MINUTES * MINUTES_MS) return null;
- return timeCondition(time, Math.round(span / (float)MINUTES_MS));
- }
-
- private Condition newTimeCondition(int minutesFromNow) {
- final long now = System.currentTimeMillis();
- final long millis = minutesFromNow == 0 ? ZERO_VALUE_MS : minutesFromNow * MINUTES_MS;
- return timeCondition(now + millis, minutesFromNow);
- }
-
- private Condition timeCondition(long time, int minutes) {
- final int num = minutes < 60 ? minutes : Math.round(minutes / 60f);
- final int resId = minutes < 60
- ? R.plurals.zen_mode_duration_minutes
- : R.plurals.zen_mode_duration_hours;
- final String caption = mContext.getResources().getQuantityString(resId, num, num);
- final Uri id = ZenModeConfig.toCountdownConditionId(time);
- return new Condition(id, caption, "", "", 0, Condition.STATE_TRUE,
- Condition.FLAG_RELEVANT_NOW);
+ return ZenModeConfig.toTimeCondition(time, Math.round(span / (float) MINUTES_MS));
}
private void handleUpdateConditions(Condition[] conditions) {
@@ -401,7 +392,7 @@
if (favoriteIndex == -1) {
getConditionTagAt(FOREVER_CONDITION_INDEX).rb.setChecked(true);
} else {
- mTimeCondition = newTimeCondition(MINUTE_BUCKETS[favoriteIndex]);
+ mTimeCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[favoriteIndex]);
mBucketIndex = favoriteIndex;
bind(mTimeCondition, mZenConditions.getChildAt(TIME_CONDITION_INDEX));
getConditionTagAt(TIME_CONDITION_INDEX).rb.setChecked(true);
@@ -457,7 +448,7 @@
});
final TextView title = (TextView) row.findViewById(android.R.id.title);
if (condition == null) {
- title.setText(R.string.zen_mode_forever);
+ title.setText(mContext.getString(com.android.internal.R.string.zen_mode_forever));
} else {
title.setText(condition.summary);
}
@@ -494,7 +485,7 @@
} else {
final long span = time - System.currentTimeMillis();
button1.setEnabled(span > MIN_BUCKET_MINUTES * MINUTES_MS);
- final Condition maxCondition = newTimeCondition(MAX_BUCKET_MINUTES);
+ final Condition maxCondition = ZenModeConfig.toTimeCondition(MAX_BUCKET_MINUTES);
button2.setEnabled(!Objects.equals(condition.summary, maxCondition.summary));
}
@@ -520,18 +511,18 @@
final long bucketTime = now + bucketMinutes * MINUTES_MS;
if (up && bucketTime > time || !up && bucketTime < time) {
mBucketIndex = j;
- newCondition = timeCondition(bucketTime, bucketMinutes);
+ newCondition = ZenModeConfig.toTimeCondition(bucketTime, bucketMinutes);
break;
}
}
if (newCondition == null) {
mBucketIndex = DEFAULT_BUCKET_INDEX;
- newCondition = newTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
+ newCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
}
} else {
// on a known index, simply increment or decrement
mBucketIndex = Math.max(0, Math.min(N - 1, mBucketIndex + (up ? 1 : -1)));
- newCondition = newTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
+ newCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
}
mTimeCondition = newCondition;
bind(mTimeCondition, row);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index f39727a..cce30c7 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -2755,12 +2755,14 @@
SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
mStatusBarColor, mLastTopInset, Gravity.TOP,
STATUS_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.statusBarBackground);
+ com.android.internal.R.id.statusBarBackground,
+ (getAttributes().flags & FLAG_FULLSCREEN) != 0);
mNavigationColorView = updateColorViewInt(mNavigationColorView,
SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
mNavigationBarColor, mLastBottomInset, Gravity.BOTTOM,
NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.navigationBarBackground);
+ com.android.internal.R.id.navigationBarBackground,
+ false /* hiddenByWindowFlag */);
}
if (insets != null) {
insets = insets.consumeStableInsets();
@@ -2769,8 +2771,10 @@
}
private View updateColorViewInt(View view, int systemUiHideFlag, int translucentFlag,
- int color, int height, int verticalGravity, String transitionName, int id) {
+ int color, int height, int verticalGravity, String transitionName, int id,
+ boolean hiddenByWindowFlag) {
boolean show = height > 0 && (mLastSystemUiVisibility & systemUiHideFlag) == 0
+ && !hiddenByWindowFlag
&& (getAttributes().flags & translucentFlag) == 0
&& (color & Color.BLACK) != 0
&& (getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index cd3eab5..9daa190 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1826,8 +1826,6 @@
params.packageName = packageName;
params.windowAnimations = win.getWindowStyle().getResourceId(
com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
- params.privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
if (!compatInfo.supportsScreen()) {
@@ -3533,13 +3531,16 @@
pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
+ mOverscanScreenHeight;
} else if (attrs.type == TYPE_WALLPAPER) {
- // The wallpaper also has Real Ultimate Power.
- pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
- pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
- pf.right = df.right = of.right = cf.right
- = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
- pf.bottom = df.bottom = of.bottom = cf.bottom
- = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
+ // The wallpaper also has Real Ultimate Power, but we want to tell
+ // it about the overscan area.
+ pf.left = df.left = mOverscanScreenLeft;
+ pf.top = df.top = mOverscanScreenTop;
+ pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
+ pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
+ of.left = cf.left = mUnrestrictedScreenLeft;
+ of.top = cf.top = mUnrestrictedScreenTop;
+ of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
+ of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
} else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
&& attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
&& attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
@@ -3653,9 +3654,12 @@
// TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR) {
- df.left = df.top = of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
- df.right = df.bottom = of.right = of.bottom = cf.right = cf.bottom
- = vf.right = vf.bottom = 10000;
+ df.left = df.top = -10000;
+ df.right = df.bottom = 10000;
+ if (attrs.type != TYPE_WALLPAPER) {
+ of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
+ of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
+ }
}
if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
@@ -4240,14 +4244,17 @@
int result;
boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
|| event.isWakeKey();
- if (interactive
- || (isInjected && !isWakeKey)
- || (!interactive && shouldDispatchInputWhenNonInteractive())) {
- // When the device is interactive, the key is injected, or we're currently dozing in a
- // non-interactive state with the screen on and the keyguard showing, pass the key to
- // the application.
+ if (interactive || (isInjected && !isWakeKey)) {
+ // When the device is interactive or the key is injected pass the key to the
+ // application.
result = ACTION_PASS_TO_USER;
isWakeKey = false;
+ } else if (!interactive && shouldDispatchInputWhenNonInteractive()) {
+ // If we're currently dozing with the screen on and the keyguard showing, pass the key
+ // to the application but preserve its wake key status to make sure we still move
+ // from dozing to fully interactive if we would normally go from off to fully
+ // interactive.
+ result = ACTION_PASS_TO_USER;
} else {
// When the screen is off and the key is not injected, determine whether
// to wake the device but don't pass the key to the application.
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index a43a2a6..ebe21ff 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -746,14 +746,16 @@
}
/**
- * Gets the bounds of the accessibility focus in the active window.
+ * Gets a point within the accessibility focused node where we can send down
+ * and up events to perform a click.
*
- * @param outBounds The output to which to write the focus bounds.
- * @return Whether accessibility focus was found and the bounds are populated.
+ * @param outPoint The click point to populate.
+ * @return Whether accessibility a click point was found and set.
*/
// TODO: (multi-display) Make sure this works for multiple displays.
- boolean getAccessibilityFocusBounds(Rect outBounds) {
- return getInteractionBridgeLocked().getAccessibilityFocusBoundsNotLocked(outBounds);
+ boolean getAccessibilityFocusClickPointInScreen(Point outPoint) {
+ return getInteractionBridgeLocked()
+ .getAccessibilityFocusClickPointInScreenNotLocked(outPoint);
}
/**
@@ -2196,8 +2198,8 @@
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName,
- partialInteractiveRegion, interactionId, callback, mFetchFlags, interrogatingPid,
- interrogatingTid, spec);
+ partialInteractiveRegion, interactionId, callback, mFetchFlags,
+ interrogatingPid, interrogatingTid, spec);
return true;
} catch (RemoteException re) {
if (DEBUG) {
@@ -2248,8 +2250,8 @@
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
- partialInteractiveRegion, interactionId, callback, mFetchFlags, interrogatingPid,
- interrogatingTid, spec);
+ partialInteractiveRegion, interactionId, callback, mFetchFlags,
+ interrogatingPid, interrogatingTid, spec);
return true;
} catch (RemoteException re) {
if (DEBUG) {
@@ -2352,8 +2354,9 @@
final long identityToken = Binder.clearCallingIdentity();
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
- connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion, interactionId,
- callback, mFetchFlags, interrogatingPid, interrogatingTid, spec);
+ connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion,
+ interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
+ spec);
return true;
} catch (RemoteException re) {
if (DEBUG) {
@@ -2403,8 +2406,9 @@
final long identityToken = Binder.clearCallingIdentity();
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
- connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion, interactionId,
- callback, mFetchFlags, interrogatingPid, interrogatingTid, spec);
+ connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion,
+ interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
+ spec);
return true;
} catch (RemoteException re) {
if (DEBUG) {
@@ -2460,6 +2464,7 @@
return true;
}
+ @Override
public boolean performGlobalAction(int action) {
synchronized (mLock) {
// We treat calls from a profile as if made by its parent as profiles
@@ -2501,6 +2506,57 @@
}
@Override
+ public boolean computeClickPointInScreen(int accessibilityWindowId,
+ long accessibilityNodeId, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
+ throws RemoteException {
+ final int resolvedWindowId;
+ IAccessibilityInteractionConnection connection = null;
+ Region partialInteractiveRegion = mTempRegion;
+ synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(
+ UserHandle.getCallingUserId());
+ if (resolvedUserId != mCurrentUserId) {
+ return false;
+ }
+ resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
+ final boolean permissionGranted =
+ mSecurityPolicy.canRetrieveWindowContentLocked(this);
+ if (!permissionGranted) {
+ return false;
+ } else {
+ connection = getConnectionLocked(resolvedWindowId);
+ if (connection == null) {
+ return false;
+ }
+ }
+ if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
+ resolvedWindowId, partialInteractiveRegion)) {
+ partialInteractiveRegion = null;
+ }
+ }
+ final int interrogatingPid = Binder.getCallingPid();
+ final long identityToken = Binder.clearCallingIdentity();
+ MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
+ try {
+ connection.computeClickPointInScreen(accessibilityNodeId, partialInteractiveRegion,
+ interactionId, callback, interrogatingPid, interrogatingTid, spec);
+ return true;
+ } catch (RemoteException re) {
+ if (DEBUG) {
+ Slog.e(LOG_TAG, "Error computeClickPointInScreen().");
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identityToken);
+ }
+ return false;
+ }
+
+ @Override
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
synchronized (mLock) {
@@ -3119,30 +3175,43 @@
}
}
- public boolean getAccessibilityFocusBoundsNotLocked(Rect outBounds) {
+ public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) {
AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
if (focus == null) {
return false;
}
synchronized (mLock) {
- focus.getBoundsInScreen(outBounds);
+ Point point = mClient.computeClickPointInScreen(mConnectionId,
+ focus.getWindowId(), focus.getSourceNodeId());
+
+ if (point == null) {
+ return false;
+ }
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId());
if (spec != null && !spec.isNop()) {
- outBounds.offset((int) -spec.offsetX, (int) -spec.offsetY);
- outBounds.scale(1 / spec.scale);
+ point.offset((int) -spec.offsetX, (int) -spec.offsetY);
+ point.x = (int) (point.x * (1 / spec.scale));
+ point.y = (int) (point.y * (1 / spec.scale));
}
- // Clip to the window rectangle.
+ // Make sure the point is within the window.
Rect windowBounds = mTempRect;
getActiveWindowBounds(windowBounds);
- outBounds.intersect(windowBounds);
+ if (!windowBounds.contains(point.x, point.y)) {
+ return false;
+ }
- // Clip to the screen rectangle.
- mDefaultDisplay.getRealSize(mTempPoint);
- outBounds.intersect(0, 0, mTempPoint.x, mTempPoint.y);
+ // Make sure the point is within the screen.
+ Point screenSize = mTempPoint;
+ mDefaultDisplay.getRealSize(screenSize);
+ if (point.x < 0 || point.x > screenSize.x
+ || point.y < 0 || point.y > screenSize.y) {
+ return false;
+ }
+ outPoint.set(point.x, point.y);
return true;
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index ac0ca0a..9e63433 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -24,6 +24,7 @@
import android.gesture.GestureStore;
import android.gesture.GestureStroke;
import android.gesture.Prediction;
+import android.graphics.Point;
import android.graphics.Rect;
import android.os.Handler;
import android.os.SystemClock;
@@ -171,6 +172,9 @@
// Temporary rectangle to avoid instantiation.
private final Rect mTempRect = new Rect();
+ // Temporary point to avoid instantiation.
+ private final Point mTempPoint = new Point();
+
// Context in which this explorer operates.
private final Context mContext;
@@ -1157,18 +1161,18 @@
mInjectedPointerTracker.getLastInjectedHoverEventForClick();
if (lastExploreEvent == null) {
// No last touch explored event but there is accessibility focus in
- // the active window. We click in the middle of the focus bounds.
- Rect focusBounds = mTempRect;
- if (mAms.getAccessibilityFocusBounds(focusBounds)) {
- clickLocationX = focusBounds.centerX();
- clickLocationY = focusBounds.centerY();
+ // the active window. We click in the focus bounds.
+ Point point = mTempPoint;
+ if (mAms.getAccessibilityFocusClickPointInScreen(point)) {
+ clickLocationX = point.x;
+ clickLocationY = point.y;
} else {
// Out of luck - do nothing.
return;
}
} else {
// If the click is within the active window but not within the
- // accessibility focus bounds we click in the focus center.
+ // accessibility focus bounds we click in the focus bounds.
final int lastExplorePointerIndex = lastExploreEvent.getActionIndex();
clickLocationX = (int) lastExploreEvent.getX(lastExplorePointerIndex);
clickLocationY = (int) lastExploreEvent.getY(lastExplorePointerIndex);
@@ -1176,12 +1180,10 @@
if (mLastTouchedWindowId == mAms.getActiveWindowId()) {
mAms.getActiveWindowBounds(activeWindowBounds);
if (activeWindowBounds.contains(clickLocationX, clickLocationY)) {
- Rect focusBounds = mTempRect;
- if (mAms.getAccessibilityFocusBounds(focusBounds)) {
- if (!focusBounds.contains(clickLocationX, clickLocationY)) {
- clickLocationX = focusBounds.centerX();
- clickLocationY = focusBounds.centerY();
- }
+ Point point = mTempPoint;
+ if (mAms.getAccessibilityFocusClickPointInScreen(point)) {
+ clickLocationX = point.x;
+ clickLocationY = point.y;
}
}
}
@@ -1330,18 +1332,18 @@
mInjectedPointerTracker.getLastInjectedHoverEventForClick();
if (lastExploreEvent == null) {
// No last touch explored event but there is accessibility focus in
- // the active window. We click in the middle of the focus bounds.
- Rect focusBounds = mTempRect;
- if (mAms.getAccessibilityFocusBounds(focusBounds)) {
- clickLocationX = focusBounds.centerX();
- clickLocationY = focusBounds.centerY();
+ // the active window. We click in the focus bounds.
+ Point point = mTempPoint;
+ if (mAms.getAccessibilityFocusClickPointInScreen(point)) {
+ clickLocationX = point.x;
+ clickLocationY = point.y;
} else {
// Out of luck - do nothing.
return;
}
} else {
// If the click is within the active window but not within the
- // accessibility focus bounds we click in the focus center.
+ // accessibility focus bounds we click in the focus bounds.
final int lastExplorePointerIndex = lastExploreEvent.getActionIndex();
clickLocationX = (int) lastExploreEvent.getX(lastExplorePointerIndex);
clickLocationY = (int) lastExploreEvent.getY(lastExplorePointerIndex);
@@ -1349,12 +1351,10 @@
if (mLastTouchedWindowId == mAms.getActiveWindowId()) {
mAms.getActiveWindowBounds(activeWindowBounds);
if (activeWindowBounds.contains(clickLocationX, clickLocationY)) {
- Rect focusBounds = mTempRect;
- if (mAms.getAccessibilityFocusBounds(focusBounds)) {
- if (!focusBounds.contains(clickLocationX, clickLocationY)) {
- clickLocationX = focusBounds.centerX();
- clickLocationY = focusBounds.centerY();
- }
+ Point point = mTempPoint;
+ if (mAms.getAccessibilityFocusClickPointInScreen(point)) {
+ clickLocationX = point.x;
+ clickLocationY = point.y;
}
}
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index e9419ad..b04cc19 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1535,7 +1535,7 @@
for (int i=0; i<triggerList.size(); i++) {
Alarm alarm = triggerList.get(i);
try {
- if (localLOGV) Slog.v(TAG, "sending alarm " + alarm);
+ Slog.v(TAG, "sending alarm " + alarm);
alarm.operation.send(getContext(), 0,
mBackgroundIntent.putExtra(
Intent.EXTRA_ALARM_COUNT, alarm.count),
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 3bab1bf..75090db 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -425,8 +425,8 @@
TelephonyManager mTelephonyManager;
- // sequence number for Networks
- private final static int MIN_NET_ID = 10; // some reserved marks
+ // sequence number for Networks; keep in sync with system/netd/NetworkController.cpp
+ private final static int MIN_NET_ID = 100; // some reserved marks
private final static int MAX_NET_ID = 65535;
private int mNextNetId = MIN_NET_ID;
@@ -793,14 +793,28 @@
}
/**
- * Check if UID should be blocked from using the network represented by the
- * given {@link NetworkStateTracker}.
+ * Check if UID should be blocked from using the network represented by the given networkType.
+ * @deprecated Uses mLegacyTypeTracker; cannot deal with multiple Networks of the same type.
*/
private boolean isNetworkBlocked(int networkType, int uid) {
+ return isNetworkWithLinkPropertiesBlocked(getLinkPropertiesForType(networkType), uid);
+ }
+
+ /**
+ * Check if UID should be blocked from using the network represented by the given
+ * NetworkAgentInfo.
+ */
+ private boolean isNetworkBlocked(NetworkAgentInfo nai, int uid) {
+ return isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid);
+ }
+
+ /**
+ * Check if UID should be blocked from using the network with the given LinkProperties.
+ */
+ private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid) {
final boolean networkCostly;
final int uidRules;
- LinkProperties lp = getLinkPropertiesForType(networkType);
final String iface = (lp == null ? "" : lp.getInterfaceName());
synchronized (mRulesLock) {
networkCostly = mMeteredIfaces.contains(iface);
@@ -819,17 +833,36 @@
* Return a filtered {@link NetworkInfo}, potentially marked
* {@link DetailedState#BLOCKED} based on
* {@link #isNetworkBlocked}.
+ * @deprecated Uses mLegacyTypeTracker; cannot deal with multiple Networks of the same type.
*/
private NetworkInfo getFilteredNetworkInfo(int networkType, int uid) {
NetworkInfo info = getNetworkInfoForType(networkType);
return getFilteredNetworkInfo(info, networkType, uid);
}
+ /*
+ * @deprecated Uses mLegacyTypeTracker; cannot deal with multiple Networks of the same type.
+ */
private NetworkInfo getFilteredNetworkInfo(NetworkInfo info, int networkType, int uid) {
if (isNetworkBlocked(networkType, uid)) {
// network is blocked; clone and override state
info = new NetworkInfo(info);
info.setDetailedState(DetailedState.BLOCKED, null, null);
+ if (VDBG) log("returning Blocked NetworkInfo");
+ }
+ if (mLockdownTracker != null) {
+ info = mLockdownTracker.augmentNetworkInfo(info);
+ if (VDBG) log("returning Locked NetworkInfo");
+ }
+ return info;
+ }
+
+ private NetworkInfo getFilteredNetworkInfo(NetworkAgentInfo nai, int uid) {
+ NetworkInfo info = nai.networkInfo;
+ if (isNetworkBlocked(nai, uid)) {
+ // network is blocked; clone and override state
+ info = new NetworkInfo(info);
+ info.setDetailedState(DetailedState.BLOCKED, null, null);
if (DBG) log("returning Blocked NetworkInfo");
}
if (mLockdownTracker != null) {
@@ -946,7 +979,7 @@
synchronized (nai) {
if (nai.networkInfo == null) return null;
- return getFilteredNetworkInfo(nai.networkInfo, nai.networkInfo.getType(), uid);
+ return getFilteredNetworkInfo(nai, uid);
}
}
@@ -1315,6 +1348,12 @@
// }
}
+ private void enforceInternetPermission() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERNET,
+ "ConnectivityService");
+ }
+
private void enforceAccessPermission() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE,
@@ -2468,7 +2507,22 @@
}
public void reportBadNetwork(Network network) {
- //TODO
+ enforceAccessPermission();
+ enforceInternetPermission();
+
+ if (network == null) return;
+
+ final int uid = Binder.getCallingUid();
+ NetworkAgentInfo nai = null;
+ synchronized (mNetworkForNetId) {
+ nai = mNetworkForNetId.get(network.netId);
+ }
+ if (nai == null) return;
+ synchronized (nai) {
+ if (isNetworkBlocked(nai, uid)) return;
+
+ nai.networkMonitor.sendMessage(NetworkMonitor.CMD_FORCE_REEVALUATION, uid);
+ }
}
public ProxyInfo getProxy() {
@@ -4436,10 +4490,14 @@
loge("Unknown NetworkAgentInfo in handleLingerComplete");
return;
}
- if (DBG) log("handleLingerComplete for " + oldNetwork.name());
if (DBG) {
- if (oldNetwork.networkRequests.size() != 0) {
- loge("Dead network still had " + oldNetwork.networkRequests.size() + " requests");
+ log("handleLingerComplete for " + oldNetwork.name());
+ for (int i = 0; i < oldNetwork.networkRequests.size(); i++) {
+ NetworkRequest nr = oldNetwork.networkRequests.valueAt(i);
+ // Ignore listening requests.
+ if (mNetworkRequests.get(nr).isRequest == false) continue;
+ loge("Dead network still had at least " + nr);
+ break;
}
}
oldNetwork.asyncChannel.disconnect();
@@ -4463,6 +4521,8 @@
loge("Unknown NetworkAgentInfo in handleConnectionValidated");
return;
}
+ if (newNetwork.validated) return;
+ newNetwork.validated = true;
boolean keep = newNetwork.isVPN();
boolean isNewDefault = false;
if (DBG) log("handleConnectionValidated for "+newNetwork.name());
@@ -4686,6 +4746,11 @@
private void updateNetworkScore(NetworkAgentInfo nai, int score) {
if (DBG) log("updateNetworkScore for " + nai.name() + " to " + score);
+ if (score < 0) {
+ loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score +
+ "). Bumping score to min of 0");
+ score = 0;
+ }
nai.currentScore = score;
@@ -4706,6 +4771,8 @@
// code will fire.
for (int i = 0; i < nai.networkRequests.size(); i++) {
NetworkRequest nr = nai.networkRequests.valueAt(i);
+ // Don't send listening requests to factories. b/17393458
+ if (mNetworkRequests.get(nr).isRequest == false) continue;
sendUpdatedScoreToFactories(nr, score);
}
}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index c8718e3e..060c8e3 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -106,6 +106,7 @@
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
+import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
@@ -3455,9 +3456,14 @@
parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE);
final boolean isAuxiliary = "1".equals(String.valueOf(
parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
- final InputMethodSubtype subtype =
- new InputMethodSubtype(label, icon, imeSubtypeLocale,
- imeSubtypeMode, imeSubtypeExtraValue, isAuxiliary);
+ final InputMethodSubtype subtype = new InputMethodSubtypeBuilder()
+ .setSubtypeNameResId(label)
+ .setSubtypeIconResId(icon)
+ .setSubtypeLocale(imeSubtypeLocale)
+ .setSubtypeMode(imeSubtypeMode)
+ .setSubtypeExtraValue(imeSubtypeExtraValue)
+ .setIsAuxiliary(isAuxiliary)
+ .build();
tempSubtypesArray.add(subtype);
}
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 7624314..37c23bb 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -196,7 +196,7 @@
if (VDBG) log("MSG_USER_SWITCHED userId=" + msg.arg1);
int numPhones = TelephonyManager.getDefault().getPhoneCount();
for (int sub = 0; sub < numPhones; sub++) {
- TelephonyRegistry.this.notifyCellLocationUsingSubId(sub,
+ TelephonyRegistry.this.notifyCellLocationForSubscriber(sub,
mCellLocation[sub]);
}
break;
@@ -326,7 +326,7 @@
}
@Override
- public void listenUsingSubId(long subId, String pkgForDebug, IPhoneStateListener callback,
+ public void listenForSubscriber(long subId, String pkgForDebug, IPhoneStateListener callback,
int events, boolean notifyNow) {
listen(pkgForDebug, callback, events, notifyNow, subId, false);
}
@@ -542,12 +542,12 @@
broadcastCallStateChanged(state, incomingNumber, mDefaultSubId);
}
- public void notifyCallStateUsingSubId(long subId, int state, String incomingNumber) {
+ public void notifyCallStateForSubscriber(long subId, int state, String incomingNumber) {
if (!checkNotifyPermission("notifyCallState()")) {
return;
}
if (VDBG) {
- log("notifyCallStateUsingSubId: subId=" + subId
+ log("notifyCallStateForSubscriber: subId=" + subId
+ " state=" + state + " incomingNumber=" + incomingNumber);
}
synchronized (mRecords) {
@@ -573,38 +573,38 @@
}
public void notifyServiceState(ServiceState state) {
- notifyServiceStateUsingSubId(mDefaultSubId, state);
+ notifyServiceStateForSubscriber(mDefaultSubId, state);
}
- public void notifyServiceStateUsingSubId(long subId, ServiceState state) {
+ public void notifyServiceStateForSubscriber(long subId, ServiceState state) {
if (!checkNotifyPermission("notifyServiceState()")){
return;
}
if (subId == SubscriptionManager.DEFAULT_SUB_ID) {
subId = mDefaultSubId;
- if (VDBG) log("notifyServiceStateUsingSubId: using mDefaultSubId=" + mDefaultSubId);
+ if (VDBG) log("notifyServiceStateForSubscriber: using mDefaultSubId=" + mDefaultSubId);
}
synchronized (mRecords) {
int phoneId = SubscriptionManager.getPhoneId(subId);
if (VDBG) {
- log("notifyServiceStateUsingSubId: subId=" + subId + " phoneId=" + phoneId
+ log("notifyServiceStateForSubscriber: subId=" + subId + " phoneId=" + phoneId
+ " state=" + state);
}
if (validatePhoneId(phoneId)) {
mServiceState[phoneId] = state;
- logServiceStateChanged("notifyServiceStateUsingSubId", subId, phoneId, state);
- if (VDBG) toStringLogSSC("notifyServiceStateUsingSubId");
+ logServiceStateChanged("notifyServiceStateForSubscriber", subId, phoneId, state);
+ if (VDBG) toStringLogSSC("notifyServiceStateForSubscriber");
for (Record r : mRecords) {
if (VDBG) {
- log("notifyServiceStateUsingSubId: r=" + r + " subId=" + subId
+ log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId
+ " phoneId=" + phoneId + " state=" + state);
}
if (((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) &&
(r.phoneId == phoneId)) {
try {
if (DBG) {
- log("notifyServiceStateUsingSubId: callback.onSSC r=" + r
+ log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
+ " subId=" + subId + " phoneId=" + phoneId
+ " state=" + state);
}
@@ -615,7 +615,7 @@
}
}
} else {
- log("notifyServiceStateUsingSubId: INVALID phoneId=" + phoneId);
+ log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId);
}
handleRemoveListLocked();
}
@@ -623,33 +623,33 @@
}
public void notifySignalStrength(SignalStrength signalStrength) {
- notifySignalStrengthUsingSubId(mDefaultSubId, signalStrength);
+ notifySignalStrengthForSubscriber(mDefaultSubId, signalStrength);
}
- public void notifySignalStrengthUsingSubId(long subId, SignalStrength signalStrength) {
+ public void notifySignalStrengthForSubscriber(long subId, SignalStrength signalStrength) {
if (!checkNotifyPermission("notifySignalStrength()")) {
return;
}
if (VDBG) {
- log("notifySignalStrengthUsingSubId: subId=" + subId
+ log("notifySignalStrengthForSubscriber: subId=" + subId
+ " signalStrength=" + signalStrength);
- toStringLogSSC("notifySignalStrengthUsingSubId");
+ toStringLogSSC("notifySignalStrengthForSubscriber");
}
synchronized (mRecords) {
int phoneId = SubscriptionManager.getPhoneId(subId);
if (validatePhoneId(phoneId)) {
- if (VDBG) log("notifySignalStrengthUsingSubId: valid phoneId=" + phoneId);
+ if (VDBG) log("notifySignalStrengthForSubscriber: valid phoneId=" + phoneId);
mSignalStrength[phoneId] = signalStrength;
for (Record r : mRecords) {
if (VDBG) {
- log("notifySignalStrengthUsingSubId: r=" + r + " subId=" + subId
+ log("notifySignalStrengthForSubscriber: r=" + r + " subId=" + subId
+ " phoneId=" + phoneId + " ss=" + signalStrength);
}
if (((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) &&
(r.phoneId == phoneId)) {
try {
if (DBG) {
- log("notifySignalStrengthUsingSubId: callback.onSsS r=" + r
+ log("notifySignalStrengthForSubscriber: callback.onSsS r=" + r
+ " subId=" + subId + " phoneId=" + phoneId
+ " ss=" + signalStrength);
}
@@ -664,7 +664,7 @@
int gsmSignalStrength = signalStrength.getGsmSignalStrength();
int ss = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
if (DBG) {
- log("notifySignalStrengthUsingSubId: callback.onSS r=" + r
+ log("notifySignalStrengthForSubscriber: callback.onSS r=" + r
+ " subId=" + subId + " phoneId=" + phoneId
+ " gsmSS=" + gsmSignalStrength + " ss=" + ss);
}
@@ -675,7 +675,7 @@
}
}
} else {
- log("notifySignalStrengthUsingSubId: invalid phoneId=" + phoneId);
+ log("notifySignalStrengthForSubscriber: invalid phoneId=" + phoneId);
}
handleRemoveListLocked();
}
@@ -683,15 +683,15 @@
}
public void notifyCellInfo(List<CellInfo> cellInfo) {
- notifyCellInfoUsingSubId(mDefaultSubId, cellInfo);
+ notifyCellInfoForSubscriber(mDefaultSubId, cellInfo);
}
- public void notifyCellInfoUsingSubId(long subId, List<CellInfo> cellInfo) {
+ public void notifyCellInfoForSubscriber(long subId, List<CellInfo> cellInfo) {
if (!checkNotifyPermission("notifyCellInfo()")) {
return;
}
if (VDBG) {
- log("notifyCellInfoUsingSubId: subId=" + subId
+ log("notifyCellInfoForSubscriber: subId=" + subId
+ " cellInfo=" + cellInfo);
}
@@ -743,15 +743,15 @@
}
public void notifyMessageWaitingChanged(boolean mwi) {
- notifyMessageWaitingChangedUsingSubId(mDefaultSubId, mwi);
+ notifyMessageWaitingChangedForSubscriber(mDefaultSubId, mwi);
}
- public void notifyMessageWaitingChangedUsingSubId(long subId, boolean mwi) {
+ public void notifyMessageWaitingChangedForSubscriber(long subId, boolean mwi) {
if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
return;
}
if (VDBG) {
- log("notifyMessageWaitingChangedUsingSubId: subId=" + subId
+ log("notifyMessageWaitingChangedForSubscriber: subId=" + subId
+ " mwi=" + mwi);
}
synchronized (mRecords) {
@@ -774,15 +774,15 @@
}
public void notifyCallForwardingChanged(boolean cfi) {
- notifyCallForwardingChangedUsingSubId(mDefaultSubId, cfi);
+ notifyCallForwardingChangedForSubscriber(mDefaultSubId, cfi);
}
- public void notifyCallForwardingChangedUsingSubId(long subId, boolean cfi) {
+ public void notifyCallForwardingChangedForSubscriber(long subId, boolean cfi) {
if (!checkNotifyPermission("notifyCallForwardingChanged()")) {
return;
}
if (VDBG) {
- log("notifyCallForwardingChangedUsingSubId: subId=" + subId
+ log("notifyCallForwardingChangedForSubscriber: subId=" + subId
+ " cfi=" + cfi);
}
synchronized (mRecords) {
@@ -805,10 +805,10 @@
}
public void notifyDataActivity(int state) {
- notifyDataActivityUsingSubId(mDefaultSubId, state);
+ notifyDataActivityForSubscriber(mDefaultSubId, state);
}
- public void notifyDataActivityUsingSubId(long subId, int state) {
+ public void notifyDataActivityForSubscriber(long subId, int state) {
if (!checkNotifyPermission("notifyDataActivity()" )) {
return;
}
@@ -831,12 +831,12 @@
public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
String reason, String apn, String apnType, LinkProperties linkProperties,
NetworkCapabilities networkCapabilities, int networkType, boolean roaming) {
- notifyDataConnectionUsingSubId(mDefaultSubId, state, isDataConnectivityPossible,
+ notifyDataConnectionForSubscriber(mDefaultSubId, state, isDataConnectivityPossible,
reason, apn, apnType, linkProperties,
networkCapabilities, networkType, roaming);
}
- public void notifyDataConnectionUsingSubId(long subId, int state,
+ public void notifyDataConnectionForSubscriber(long subId, int state,
boolean isDataConnectivityPossible, String reason, String apn, String apnType,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int networkType, boolean roaming) {
@@ -844,7 +844,7 @@
return;
}
if (VDBG) {
- log("notifyDataConnectionUsingSubId: subId=" + subId
+ log("notifyDataConnectionForSubscriber: subId=" + subId
+ " state=" + state + " isDataConnectivityPossible=" + isDataConnectivityPossible
+ " reason='" + reason
+ "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType
@@ -921,16 +921,16 @@
}
public void notifyDataConnectionFailed(String reason, String apnType) {
- notifyDataConnectionFailedUsingSubId(mDefaultSubId, reason, apnType);
+ notifyDataConnectionFailedForSubscriber(mDefaultSubId, reason, apnType);
}
- public void notifyDataConnectionFailedUsingSubId(long subId,
+ public void notifyDataConnectionFailedForSubscriber(long subId,
String reason, String apnType) {
if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
return;
}
if (VDBG) {
- log("notifyDataConnectionFailedUsingSubId: subId=" + subId
+ log("notifyDataConnectionFailedForSubscriber: subId=" + subId
+ " reason=" + reason + " apnType=" + apnType);
}
synchronized (mRecords) {
@@ -954,17 +954,17 @@
}
public void notifyCellLocation(Bundle cellLocation) {
- notifyCellLocationUsingSubId(mDefaultSubId, cellLocation);
+ notifyCellLocationForSubscriber(mDefaultSubId, cellLocation);
}
- public void notifyCellLocationUsingSubId(long subId, Bundle cellLocation) {
- log("notifyCellLocationUsingSubId: subId=" + subId
+ public void notifyCellLocationForSubscriber(long subId, Bundle cellLocation) {
+ log("notifyCellLocationForSubscriber: subId=" + subId
+ " cellLocation=" + cellLocation);
if (!checkNotifyPermission("notifyCellLocation()")) {
return;
}
if (VDBG) {
- log("notifyCellLocationUsingSubId: subId=" + subId
+ log("notifyCellLocationForSubscriber: subId=" + subId
+ " cellLocation=" + cellLocation);
}
synchronized (mRecords) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 0bdb964..599c3b9 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -308,7 +308,14 @@
return new ComponentName("!", res.permission != null
? res.permission : "private to package");
}
+
ServiceRecord r = res.record;
+
+ if (!mAm.getUserManagerLocked().exists(r.userId)) {
+ Slog.d(TAG, "Trying to start service with non-existent user! " + r.userId);
+ return null;
+ }
+
NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
callingUid, r.packageName, service, service.getFlags(), null, r.userId);
if (unscheduleServiceRestartLocked(r, callingUid, false)) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1397ea4..a490ac6 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -180,6 +180,7 @@
import android.os.SystemProperties;
import android.os.UpdateLock;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.text.format.DateUtils;
import android.text.format.Time;
@@ -196,6 +197,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
+import dalvik.system.VMRuntime;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -887,6 +889,8 @@
boolean mProcessesReady = false;
boolean mSystemReady = false;
boolean mBooting = false;
+ boolean mCallFinishBooting = false;
+ boolean mBootAnimationComplete = false;
boolean mWaitingUpdate = false;
boolean mDidUpdate = false;
boolean mOnBattery = false;
@@ -1074,13 +1078,16 @@
/**
* Runtime CPU use collection thread. This object's lock is used to
- * protect all related state.
+ * perform synchronization with the thread (notifying it to run).
*/
final Thread mProcessCpuThread;
/**
- * Used to collect process stats when showing not responding dialog.
- * Protected by mProcessCpuThread.
+ * Used to collect per-process CPU use for ANRs, battery stats, etc.
+ * Must acquire this object's lock when accessing it.
+ * NOTE: this lock will be held while doing long operations (trawling
+ * through all processes in /proc), so it should never be acquired by
+ * any critical paths such as when holding the main activity manager lock.
*/
final ProcessCpuTracker mProcessCpuTracker = new ProcessCpuTracker(
MONITOR_THREAD_CPU_USAGE);
@@ -1594,7 +1601,7 @@
infoMap.put(mi.pid, mi);
}
updateCpuStatsNow();
- synchronized (mProcessCpuThread) {
+ synchronized (mProcessCpuTracker) {
final int N = mProcessCpuTracker.countStats();
for (int i=0; i<N; i++) {
ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
@@ -1893,7 +1900,7 @@
if (memInfo != null) {
updateCpuStatsNow();
long nativeTotalPss = 0;
- synchronized (mProcessCpuThread) {
+ synchronized (mProcessCpuTracker) {
final int N = mProcessCpuTracker.countStats();
for (int j=0; j<N; j++) {
ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(j);
@@ -1911,7 +1918,7 @@
}
}
memInfo.readMemInfo();
- synchronized (this) {
+ synchronized (ActivityManagerService.this) {
if (DEBUG_PSS) Slog.d(TAG, "Collected native and kernel memory in "
+ (SystemClock.uptimeMillis()-start) + "ms");
mProcessStats.addSysMemUsageLocked(memInfo.getCachedSizeKb(),
@@ -2182,7 +2189,7 @@
return;
}
- synchronized (mActivityManagerService.mProcessCpuThread) {
+ synchronized (mActivityManagerService.mProcessCpuTracker) {
pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentLoad());
pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentState(
SystemClock.uptimeMillis()));
@@ -2378,7 +2385,7 @@
}
void updateCpuStatsNow() {
- synchronized (mProcessCpuThread) {
+ synchronized (mProcessCpuTracker) {
mProcessCpuMutexFree.set(false);
final long now = SystemClock.uptimeMillis();
boolean haveNewCpuStats = false;
@@ -3124,6 +3131,11 @@
requiredAbi = Build.SUPPORTED_ABIS[0];
}
+ String instructionSet = null;
+ if (app.info.primaryCpuAbi != null) {
+ instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
+ }
+
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
boolean isActivityProcess = (entryPoint == null);
@@ -3131,7 +3143,8 @@
checkTime(startTime, "startProcess: asking zygote to start proc");
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
- app.info.targetSdkVersion, app.info.seinfo, requiredAbi, entryPointArgs);
+ app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
+ entryPointArgs);
checkTime(startTime, "startProcess: returned from zygote!");
if (app.isolated) {
@@ -3357,6 +3370,16 @@
}
}
+ void enforceShellRestriction(String restriction, int userHandle) {
+ if (Binder.getCallingUid() == Process.SHELL_UID) {
+ if (userHandle < 0
+ || mUserManager.hasUserRestriction(restriction, userHandle)) {
+ throw new SecurityException("Shell does not have permission to access user "
+ + userHandle);
+ }
+ }
+ }
+
@Override
public int getFrontActivityScreenCompatMode() {
enforceNotIsolatedCaller("getFrontActivityScreenCompatMode");
@@ -5067,7 +5090,7 @@
String cpuInfo = null;
if (MONITOR_CPU_USAGE) {
updateCpuStatsNow();
- synchronized (mProcessCpuThread) {
+ synchronized (mProcessCpuTracker) {
cpuInfo = mProcessCpuTracker.printCurrentState(anrTime);
}
info.append(processCpuTracker.printCurrentLoad());
@@ -6188,6 +6211,14 @@
}
final void finishBooting() {
+ synchronized (this) {
+ if (!mBootAnimationComplete) {
+ mCallFinishBooting = true;
+ return;
+ }
+ mCallFinishBooting = false;
+ }
+
// Register receivers to handle package update events
mPackageMonitor.register(mContext, Looper.getMainLooper(), false);
@@ -6246,6 +6277,18 @@
}
}
+ @Override
+ public void bootAnimationComplete() {
+ final boolean callFinishBooting;
+ synchronized (this) {
+ callFinishBooting = mCallFinishBooting;
+ mBootAnimationComplete = true;
+ }
+ if (callFinishBooting) {
+ finishBooting();
+ }
+ }
+
final void ensureBootCompleted() {
boolean booting;
boolean enableScreen;
@@ -7439,12 +7482,33 @@
// Does the caller have this permission on the URI?
if (!checkHoldingPermissionsLocked(pm, pi, grantUri, callingUid, modeFlags)) {
- // Right now, if you are not the original owner of the permission,
- // you are not allowed to revoke it.
- //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
- throw new SecurityException("Uid " + callingUid
- + " does not have permission to uri " + grantUri);
- //}
+ // Have they don't have direct access to the URI, then revoke any URI
+ // permissions that have been granted to them.
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
+ if (perms != null) {
+ boolean persistChanged = false;
+ for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) {
+ final UriPermission perm = it.next();
+ if (perm.uri.sourceUserId == grantUri.sourceUserId
+ && perm.uri.uri.isPathPrefixMatch(grantUri.uri)) {
+ if (DEBUG_URI_PERMISSION)
+ Slog.v(TAG,
+ "Revoking " + perm.targetUid + " permission to " + perm.uri);
+ persistChanged |= perm.revokeModes(
+ modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
+ if (perm.modeFlags == 0) {
+ it.remove();
+ }
+ }
+ }
+ if (perms.isEmpty()) {
+ mGrantedUriPermissions.remove(callingUid);
+ }
+ if (persistChanged) {
+ schedulePersistUriGrants();
+ }
+ }
+ return;
}
boolean persistChanged = false;
@@ -9658,14 +9722,9 @@
long ident = 0;
boolean clearedIdentity = false;
userId = unsafeConvertIncomingUser(userId);
- if (UserHandle.getUserId(callingUid) != userId) {
- if (checkComponentPermission(INTERACT_ACROSS_USERS, callingPid,
- callingUid, -1, true) == PackageManager.PERMISSION_GRANTED
- || checkComponentPermission(INTERACT_ACROSS_USERS_FULL, callingPid,
- callingUid, -1, true) == PackageManager.PERMISSION_GRANTED) {
- clearedIdentity = true;
- ident = Binder.clearCallingIdentity();
- }
+ if (canClearIdentity(callingPid, callingUid, userId)) {
+ clearedIdentity = true;
+ ident = Binder.clearCallingIdentity();
}
ContentProviderHolder holder = null;
try {
@@ -9693,6 +9752,19 @@
return null;
}
+ private boolean canClearIdentity(int callingPid, int callingUid, int userId) {
+ if (UserHandle.getUserId(callingUid) == userId) {
+ return true;
+ }
+ if (checkComponentPermission(INTERACT_ACROSS_USERS, callingPid,
+ callingUid, -1, true) == PackageManager.PERMISSION_GRANTED
+ || checkComponentPermission(INTERACT_ACROSS_USERS_FULL, callingPid,
+ callingUid, -1, true) == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+ return false;
+ }
+
// =========================================================
// GLOBAL MANAGEMENT
// =========================================================
@@ -13693,7 +13765,7 @@
findPid = Integer.parseInt(args[opti]);
} catch (NumberFormatException e) {
}
- synchronized (mProcessCpuThread) {
+ synchronized (mProcessCpuTracker) {
final int N = mProcessCpuTracker.countStats();
for (int i=0; i<N; i++) {
ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
@@ -13855,7 +13927,7 @@
// If we are showing aggregations, also look for native processes to
// include so that our aggregations are more accurate.
updateCpuStatsNow();
- synchronized (mProcessCpuThread) {
+ synchronized (mProcessCpuTracker) {
final int N = mProcessCpuTracker.countStats();
for (int i=0; i<N; i++) {
ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
@@ -14541,6 +14613,14 @@
throw new IllegalArgumentException(
"Call does not support special user #" + targetUserId);
}
+ // Check shell permission
+ if (callingUid == Process.SHELL_UID && targetUserId >= UserHandle.USER_OWNER) {
+ if (mUserManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES,
+ targetUserId)) {
+ throw new SecurityException("Shell does not have permission to access user "
+ + targetUserId + "\n " + Debug.getCallers(3));
+ }
+ }
return targetUserId;
}
@@ -14599,6 +14679,7 @@
Intent service, String resolvedType,
IServiceConnection connection, int flags, int userId) {
enforceNotIsolatedCaller("bindService");
+
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -15033,12 +15114,18 @@
}
private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
- int[] users) {
+ int callingUid, int[] users) {
List<ResolveInfo> receivers = null;
try {
HashSet<ComponentName> singleUserReceivers = null;
boolean scannedFirstReceivers = false;
for (int user : users) {
+ // Skip users that have Shell restrictions
+ if (callingUid == Process.SHELL_UID
+ && getUserManagerLocked().hasUserRestriction(
+ UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
+ continue;
+ }
List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
.queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS, user);
if (user != 0 && newReceivers != null) {
@@ -15127,7 +15214,6 @@
// Make sure that the user who is receiving this broadcast is started.
// If not, we will just skip it.
-
if (userId != UserHandle.USER_ALL && mStartedUsers.get(userId) == null) {
if (callingUid != Process.SYSTEM_UID || (intent.getFlags()
& Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
@@ -15392,11 +15478,30 @@
// Need to resolve the intent to interested receivers...
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
== 0) {
- receivers = collectReceiverComponents(intent, resolvedType, users);
+ receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
}
if (intent.getComponent() == null) {
- registeredReceivers = mReceiverResolver.queryIntent(intent,
- resolvedType, false, userId);
+ if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
+ // Query one target user at a time, excluding shell-restricted users
+ UserManagerService ums = getUserManagerLocked();
+ for (int i = 0; i < users.length; i++) {
+ if (ums.hasUserRestriction(
+ UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
+ continue;
+ }
+ List<BroadcastFilter> registeredReceiversForUser =
+ mReceiverResolver.queryIntent(intent,
+ resolvedType, false, users[i]);
+ if (registeredReceivers == null) {
+ registeredReceivers = registeredReceiversForUser;
+ } else if (registeredReceiversForUser != null) {
+ registeredReceivers.addAll(registeredReceiversForUser);
+ }
+ }
+ } else {
+ registeredReceivers = mReceiverResolver.queryIntent(intent,
+ resolvedType, false, userId);
+ }
}
final boolean replacePending =
@@ -15558,7 +15663,7 @@
enforceNotIsolatedCaller("broadcastIntent");
synchronized(this) {
intent = verifyBroadcastLocked(intent);
-
+
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
@@ -17966,6 +18071,7 @@
@Override
public boolean switchUser(final int userId) {
+ enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId);
String userName;
synchronized (this) {
UserInfo userInfo = getUserManagerLocked().getUserInfo(userId);
@@ -18407,6 +18513,7 @@
if (userId <= 0) {
throw new IllegalArgumentException("Can't stop primary user " + userId);
}
+ enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId);
synchronized (this) {
return stopUserLocked(userId, callback);
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 77b4cc9..e043f03 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -698,12 +698,12 @@
case ActivityOptions.ANIM_SCALE_UP:
service.mWindowManager.overridePendingAppTransitionScaleUp(
pendingOptions.getStartX(), pendingOptions.getStartY(),
- pendingOptions.getStartWidth(), pendingOptions.getStartHeight());
+ pendingOptions.getWidth(), pendingOptions.getHeight());
if (intent.getSourceBounds() == null) {
intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
pendingOptions.getStartY(),
- pendingOptions.getStartX()+pendingOptions.getStartWidth(),
- pendingOptions.getStartY()+pendingOptions.getStartHeight()));
+ pendingOptions.getStartX()+pendingOptions.getWidth(),
+ pendingOptions.getStartY()+pendingOptions.getHeight()));
}
break;
case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP:
@@ -728,15 +728,14 @@
service.mWindowManager.overridePendingAppTransitionAspectScaledThumb(
pendingOptions.getThumbnail(),
pendingOptions.getStartX(), pendingOptions.getStartY(),
+ pendingOptions.getWidth(), pendingOptions.getHeight(),
pendingOptions.getOnAnimationStartListener(),
(animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP));
if (intent.getSourceBounds() == null) {
intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
pendingOptions.getStartY(),
- pendingOptions.getStartX()
- + pendingOptions.getThumbnail().getWidth(),
- pendingOptions.getStartY()
- + pendingOptions.getThumbnail().getHeight()));
+ pendingOptions.getStartX() + pendingOptions.getWidth(),
+ pendingOptions.getStartY() + pendingOptions.getHeight()));
}
break;
default:
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 6168546..d71f94e 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -425,13 +425,13 @@
}
final ActivityRecord topActivity() {
- // Iterate to find the first non-empty task stack. Note that this code can
- // be simplified once we stop storing tasks with empty mActivities lists.
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
- final int topActivityNdx = activities.size() - 1;
- if (topActivityNdx >= 0) {
- return activities.get(topActivityNdx);
+ for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+ final ActivityRecord r = activities.get(activityNdx);
+ if (!r.finishing) {
+ return r;
+ }
}
}
return null;
@@ -1042,11 +1042,8 @@
if (prev.app != null && prev.cpuTimeAtResume > 0
&& mService.mBatteryStatsService.isOnBattery()) {
- long diff;
- synchronized (mService.mProcessCpuThread) {
- diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
- - prev.cpuTimeAtResume;
- }
+ long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
+ - prev.cpuTimeAtResume;
if (diff > 0) {
BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
synchronized (bsi) {
@@ -1097,9 +1094,7 @@
// TODO: To be more accurate, the mark should be before the onCreate,
// not after the onResume. But for subsequent starts, onResume is fine.
if (next.app != null) {
- synchronized (mService.mProcessCpuThread) {
- next.cpuTimeAtResume = mService.mProcessCpuTracker.getCpuTimeForPid(next.app.pid);
- }
+ next.cpuTimeAtResume = mService.mProcessCpuTracker.getCpuTimeForPid(next.app.pid);
} else {
next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index f821daf..b8261a4 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1772,7 +1772,7 @@
if (intentActivity != null) {
if (isLockTaskModeViolation(intentActivity.task)) {
showLockTaskToast();
- Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode");
+ Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
if (r.task == null) {
@@ -2783,9 +2783,8 @@
}
// A non-top activity is reporting a visibility change.
- if ((visible && (top.fullscreen || top.state != ActivityState.RESUMED)) ||
- top.app == null || top.app.thread == null) {
- // Can't carry out this request.
+ if (visible && top.fullscreen) {
+ // Let the caller know that it can't be seen.
if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG, "requestVisibleBehind: returning top.fullscreen="
+ top.fullscreen + " top.state=" + top.state + " top.app=" + top.app +
" top.app.thread=" + top.app.thread);
@@ -2807,9 +2806,12 @@
mService.convertFromTranslucent(next.appToken);
}
}
- try {
- top.app.thread.scheduleBackgroundVisibleBehindChanged(top.appToken, visible);
- } catch (RemoteException e) {
+ if (top.app != null && top.app.thread != null) {
+ // Notify the top app of the change.
+ try {
+ top.app.thread.scheduleBackgroundVisibleBehindChanged(top.appToken, visible);
+ } catch (RemoteException e) {
+ }
}
return true;
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 5a97aee..bba786d 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -47,6 +47,7 @@
public final NetworkMonitor networkMonitor;
public final NetworkMisc networkMisc;
public boolean created;
+ public boolean validated;
// The list of NetworkRequests being satisfied by this Network.
public final SparseArray<NetworkRequest> networkRequests = new SparseArray<NetworkRequest>();
@@ -68,6 +69,7 @@
networkMonitor = new NetworkMonitor(context, handler, this);
networkMisc = misc;
created = false;
+ validated = false;
}
public void addRequest(NetworkRequest networkRequest) {
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index ff319d3..96872a7 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -27,6 +27,7 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
+import android.net.TrafficStats;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
@@ -140,34 +141,28 @@
private static final int CMD_REEVALUATE = BASE + 6;
/**
- * Message to self indicating network evaluation is complete.
- * arg1 = Token to ignore old messages.
- * arg2 = HTTP response code of network evaluation.
- */
- private static final int EVENT_REEVALUATION_COMPLETE = BASE + 7;
-
- /**
* Inform NetworkMonitor that the network has disconnected.
*/
- public static final int CMD_NETWORK_DISCONNECTED = BASE + 8;
+ public static final int CMD_NETWORK_DISCONNECTED = BASE + 7;
/**
* Force evaluation even if it has succeeded in the past.
+ * arg1 = UID responsible for requesting this reeval. Will be billed for data.
*/
- public static final int CMD_FORCE_REEVALUATION = BASE + 9;
+ public static final int CMD_FORCE_REEVALUATION = BASE + 8;
/**
* Message to self indicating captive portal login is complete.
* arg1 = Token to ignore old messages.
* arg2 = 1 if we should use this network, 0 otherwise.
*/
- private static final int CMD_CAPTIVE_PORTAL_LOGGED_IN = BASE + 10;
+ private static final int CMD_CAPTIVE_PORTAL_LOGGED_IN = BASE + 9;
/**
* Message to self indicating user desires to log into captive portal.
* arg1 = Token to ignore old messages.
*/
- private static final int CMD_USER_WANTS_SIGN_IN = BASE + 11;
+ private static final int CMD_USER_WANTS_SIGN_IN = BASE + 10;
/**
* Request ConnectivityService display provisioning notification.
@@ -175,22 +170,22 @@
* arg2 = NetID.
* obj = Intent to be launched when notification selected by user, null if !arg1.
*/
- public static final int EVENT_PROVISIONING_NOTIFICATION = BASE + 12;
+ public static final int EVENT_PROVISIONING_NOTIFICATION = BASE + 11;
/**
* Message to self indicating sign-in app bypassed captive portal.
*/
- private static final int EVENT_APP_BYPASSED_CAPTIVE_PORTAL = BASE + 13;
+ private static final int EVENT_APP_BYPASSED_CAPTIVE_PORTAL = BASE + 12;
/**
* Message to self indicating no sign-in app responded.
*/
- private static final int EVENT_NO_APP_RESPONSE = BASE + 14;
+ private static final int EVENT_NO_APP_RESPONSE = BASE + 13;
/**
* Message to self indicating sign-in app indicates sign-in is not possible.
*/
- private static final int EVENT_APP_INDICATES_SIGN_IN_IMPOSSIBLE = BASE + 15;
+ private static final int EVENT_APP_INDICATES_SIGN_IN_IMPOSSIBLE = BASE + 14;
private static final String LINGER_DELAY_PROPERTY = "persist.netmon.linger";
// Default to 30s linger time-out.
@@ -205,6 +200,8 @@
private static final int MAX_RETRIES = 10;
private final int mReevaluateDelayMs;
private int mReevaluateToken = 0;
+ private static final int INVALID_UID = -1;
+ private int mUidResponsibleForReeval = INVALID_UID;
private int mCaptivePortalLoggedInToken = 0;
private int mUserPromptedToken = 0;
@@ -282,6 +279,7 @@
return HANDLED;
case CMD_FORCE_REEVALUATION:
if (DBG) log("Forcing reevaluation");
+ mUidResponsibleForReeval = message.arg1;
transitionTo(mEvaluatingState);
return HANDLED;
default:
@@ -322,20 +320,14 @@
private class EvaluatingState extends State {
private int mRetries;
- private class EvaluateInternetConnectivity extends Thread {
- private int mToken;
- EvaluateInternetConnectivity(int token) {
- mToken = token;
- }
- public void run() {
- sendMessage(EVENT_REEVALUATION_COMPLETE, mToken, isCaptivePortal());
- }
- }
-
@Override
public void enter() {
mRetries = 0;
sendMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
+ if (mUidResponsibleForReeval != INVALID_UID) {
+ TrafficStats.setThreadStatsUid(mUidResponsibleForReeval);
+ mUidResponsibleForReeval = INVALID_UID;
+ }
}
@Override
@@ -356,14 +348,7 @@
transitionTo(mValidatedState);
return HANDLED;
}
- // Kick off a thread to perform internet connectivity evaluation.
- Thread thread = new EvaluateInternetConnectivity(mReevaluateToken);
- thread.run();
- return HANDLED;
- case EVENT_REEVALUATION_COMPLETE:
- if (message.arg1 != mReevaluateToken)
- return HANDLED;
- int httpResponseCode = message.arg2;
+ int httpResponseCode = isCaptivePortal();
if (httpResponseCode == 204) {
transitionTo(mValidatedState);
} else if (httpResponseCode >= 200 && httpResponseCode <= 399) {
@@ -375,10 +360,18 @@
sendMessageDelayed(msg, mReevaluateDelayMs);
}
return HANDLED;
+ case CMD_FORCE_REEVALUATION:
+ // Ignore duplicate requests.
+ return HANDLED;
default:
return NOT_HANDLED;
}
}
+
+ @Override
+ public void exit() {
+ TrafficStats.clearThreadStatsUid();
+ }
}
private class UserPromptedState extends State {
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index f6beb9a..9292d45 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -16,6 +16,7 @@
package com.android.server.content;
+import android.Manifest;
import android.accounts.Account;
import android.accounts.AccountAndUser;
import android.accounts.AccountManager;
@@ -478,7 +479,7 @@
mContext.registerReceiverAsUser(mAccountsUpdatedReceiver,
UserHandle.ALL,
new IntentFilter(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION),
- null, null);
+ Manifest.permission.ACCOUNT_MANAGER, null);
}
// Pick a random second in a day to seed all periodic syncs
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index f6399a3..a6a9a89 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -69,7 +69,7 @@
try {
if (projection != null) {
- projection.addCallback(new MediaProjectionCallback(appToken));
+ projection.registerCallback(new MediaProjectionCallback(appToken));
}
appToken.linkToDeath(device, 0);
} catch (RemoteException ex) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 38c6fb3..5cd7c01 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -256,7 +256,7 @@
private List<HdmiDeviceInfo> mMhlDevices;
@Nullable
- private HdmiMhlController mMhlController;
+ private HdmiMhlControllerStub mMhlController;
// Last input port before switching to the MHL port. Should switch back to this port
// when the mobile device sends the request one touch play with off.
@@ -305,7 +305,7 @@
Slog.i(TAG, "Device does not support HDMI-CEC.");
}
- mMhlController = HdmiMhlController.create(this);
+ mMhlController = HdmiMhlControllerStub.create(this);
if (!mMhlController.isReady()) {
Slog.i(TAG, "Device does not support MHL-control.");
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiMhlControllerStub.java b/services/core/java/com/android/server/hdmi/HdmiMhlControllerStub.java
new file mode 100644
index 0000000..c27cf18
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiMhlControllerStub.java
@@ -0,0 +1,149 @@
+/*
+ * 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.hdmi;
+
+import android.hardware.hdmi.HdmiPortInfo;
+import android.util.SparseArray;
+
+import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
+
+/**
+ * A handler class for MHL control command. It converts user's command into MHL command and pass it
+ * to MHL HAL layer.
+ * <p>
+ * It can be created only by {@link HdmiMhlControllerStub#create}.
+ */
+final class HdmiMhlControllerStub {
+
+ private static final SparseArray<HdmiMhlLocalDevice> mLocalDevices = new SparseArray<>();
+ private static final HdmiPortInfo[] EMPTY_PORT_INFO = new HdmiPortInfo[0];
+ private static final int INVALID_MHL_VERSION = 0;
+ private static final int NO_SUPPORTED_FEATURES = 0;
+ private static final int INVALID_DEVICE_ROLES = 0;
+
+ // Private constructor. Use HdmiMhlControllerStub.create().
+ private HdmiMhlControllerStub(HdmiControlService service) {
+ }
+
+ // Returns true if MHL controller is initialized and ready to use.
+ boolean isReady() {
+ return false;
+ }
+
+ static HdmiMhlControllerStub create(HdmiControlService service) {
+ return new HdmiMhlControllerStub(service);
+ }
+
+ HdmiPortInfo[] getPortInfos() {
+ return EMPTY_PORT_INFO;
+ }
+
+ /**
+ * Return {@link HdmiMhlLocalDevice} matched with the given port id.
+ *
+ * @return null if has no matched port id
+ */
+ HdmiMhlLocalDevice getLocalDevice(int portId) {
+ return null;
+ }
+
+ /**
+ * Return {@link HdmiMhlLocalDevice} matched with the given device id.
+ *
+ * @return null if has no matched id
+ */
+ HdmiMhlLocalDevice getLocalDeviceById(int deviceId) {
+ return null;
+ }
+
+ SparseArray<HdmiMhlLocalDevice> getAllLocalDevices() {
+ return mLocalDevices;
+ }
+
+ /**
+ * Remove a {@link HdmiMhlLocalDevice} matched with the given port id.
+ *
+ * @return removed {@link HdmiMhlLocalDevice}. Return null if no matched port id.
+ */
+ HdmiMhlLocalDevice removeLocalDevice(int portId) {
+ return null;
+ }
+
+ /**
+ * Add a new {@link HdmiMhlLocalDevice}.
+ *
+ * @return old {@link HdmiMhlLocalDevice} having same port id
+ */
+ HdmiMhlLocalDevice addLocalDevice(HdmiMhlLocalDevice device) {
+ return null;
+ }
+
+ void clearAllLocalDevices() {
+ }
+
+ /**
+ * Send MHL MSC-Subcommand to the device connected to the given port.
+ */
+ void sendSubcommand(int portId, HdmiMhlSubcommand command) {
+ }
+
+ void sendSubcommand(final int portId, final HdmiMhlSubcommand command,
+ SendMessageCallback callback) {
+ }
+
+
+ void sendScratchpadCommand(int portId, int offset, int length, byte[] data) {
+ }
+
+ void setOption(int flag, int value) {
+ }
+
+ /**
+ * Get the MHL version supported by underlying hardware port of the given {@code portId}.
+ * MHL specification version 2.0 returns 0x20, 3.0 will return 0x30 respectively.
+ * The return value is stored in 'version'. Return INVALID_VERSION if MHL hardware layer
+ * is not ready.
+ */
+ int getMhlVersion(int portId) {
+ return INVALID_MHL_VERSION;
+ }
+
+ /**
+ * Get MHL version of a device which is connected to a port of the given {@code portId}.
+ * MHL specification version 2.0 returns 0x20, 3.0 will return 0x30 respectively.
+ * The return value is stored in 'version'.
+ */
+ int getPeerMhlVersion(int portId) {
+ return INVALID_MHL_VERSION;
+ }
+
+ /**
+ * Get the bit flags describing the features supported by the system. Refer to feature support
+ * flag register info in MHL specification.
+ */
+ int getSupportedFeatures(int portId) {
+ return NO_SUPPORTED_FEATURES;
+ }
+
+ /**
+ * Get the bit flags describing the roles which ECBUS device can play. Refer to the
+ * ECBUS_DEV_ROLES Register info MHL3.0 specification
+ */
+ int getEcbusDeviceRoles(int portId) {
+ return INVALID_DEVICE_ROLES;
+ }
+}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index bbb8371..9c567ac 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -697,7 +697,9 @@
synchronized (mDataStore) {
for (int i = 0; i < numFullKeyboards; i++) {
final InputDevice inputDevice = mTempFullKeyboards.get(i);
- if (mDataStore.getCurrentKeyboardLayout(inputDevice.getDescriptor()) == null) {
+ final String layout =
+ getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier());
+ if (layout == null) {
missingLayoutForExternalKeyboard = true;
if (i < numFullKeyboardsAdded) {
missingLayoutForExternalKeyboardAdded = true;
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 344c57b..d0447bc 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -153,7 +153,8 @@
}
mRunningJob = job;
- mParams = new JobParameters(job.getJobId(), job.getExtras(), this);
+ mParams = new JobParameters(this, job.getJobId(), job.getExtras(),
+ !job.isConstraintsSatisfied());
mExecutionStartTimeElapsed = SystemClock.elapsedRealtime();
mVerb = VERB_BINDING;
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index f562721..e3c55b6 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -195,16 +195,23 @@
}
/**
- * @return Whether or not this job is ready to run, based on its requirements.
+ * @return Whether or not this job is ready to run, based on its requirements. This is true if
+ * the constraints are satisfied <strong>or</strong> the deadline on the job has expired.
*/
public synchronized boolean isReady() {
+ return isConstraintsSatisfied()
+ || (hasDeadlineConstraint() && deadlineConstraintSatisfied.get());
+ }
+
+ /**
+ * @return Whether the constraints set on this job are satisfied.
+ */
+ public synchronized boolean isConstraintsSatisfied() {
return (!hasChargingConstraint() || chargingConstraintSatisfied.get())
&& (!hasTimingDelayConstraint() || timeDelayConstraintSatisfied.get())
&& (!hasConnectivityConstraint() || connectivityConstraintSatisfied.get())
&& (!hasUnmeteredConstraint() || unmeteredConstraintSatisfied.get())
- && (!hasIdleConstraint() || idleConstraintSatisfied.get())
- // Also ready if the deadline has expired - special case.
- || (hasDeadlineConstraint() && deadlineConstraintSatisfied.get());
+ && (!hasIdleConstraint() || idleConstraintSatisfied.get());
}
public boolean matches(int uid, int jobId) {
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 0cb8eb8..11818d8 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -331,6 +331,7 @@
private int mSuplServerPort;
private String mC2KServerHost;
private int mC2KServerPort;
+ private boolean mSuplEsEnabled = false;
private final Context mContext;
private final NtpTrustedTime mNtpTime;
@@ -493,6 +494,7 @@
Log.d(TAG, "SIM STATE is ready, SIM MCC/MNC is " + mccMnc);
synchronized (mLock) {
reloadGpsProperties(context, mProperties);
+ mNIHandler.setSuplEsEnablement(mSuplEsEnabled);
}
}
}
@@ -570,6 +572,16 @@
} catch (IOException ex) {
Log.w(TAG, "failed to dump properties contents");
}
+
+ // SUPL_ES configuration.
+ String suplESProperty = mProperties.getProperty("SUPL_ES");
+ if (suplESProperty != null) {
+ try {
+ mSuplEsEnabled = (Integer.parseInt(suplESProperty) == 1);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "unable to parse SUPL_ES: " + suplESProperty);
+ }
+ }
}
private void loadPropertiesFromResource(Context context,
@@ -611,7 +623,6 @@
mContext = context;
mNtpTime = NtpTrustedTime.getInstance(context);
mILocationManager = ilocationManager;
- mNIHandler = new GpsNetInitiatedHandler(context);
mLocation.setExtras(mLocationExtras);
@@ -638,6 +649,11 @@
mProperties = new Properties();
reloadGpsProperties(mContext, mProperties);
+ // Create a GPS net-initiated handler.
+ mNIHandler = new GpsNetInitiatedHandler(context,
+ mNetInitiatedListener,
+ mSuplEsEnabled);
+
// construct handler, listen for events
mHandler = new ProviderHandler(looper);
listenForBroadcasts();
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 8ec9b254..8a1f3ad 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -389,7 +389,7 @@
throw new IllegalStateException(
"Cannot start already started MediaProjection");
}
- addCallback(callback);
+ registerCallback(callback);
try {
mToken = callback.asBinder();
mDeathEater = new IBinder.DeathRecipient() {
@@ -424,7 +424,7 @@
}
@Override
- public void addCallback(IMediaProjectionCallback callback) {
+ public void registerCallback(IMediaProjectionCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback must not be null");
}
@@ -432,7 +432,7 @@
}
@Override
- public void removeCallback(IMediaProjectionCallback callback) {
+ public void unregisterCallback(IMediaProjectionCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback must not be null");
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 9e5fa41..cf19416 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -433,14 +433,12 @@
// listen for configured wifi networks to be removed
final IntentFilter wifiConfigFilter = new IntentFilter(CONFIGURED_NETWORKS_CHANGED_ACTION);
- mContext.registerReceiver(
- mWifiConfigReceiver, wifiConfigFilter, CONNECTIVITY_INTERNAL, mHandler);
+ mContext.registerReceiver(mWifiConfigReceiver, wifiConfigFilter, null, mHandler);
// listen for wifi state changes to catch metered hint
final IntentFilter wifiStateFilter = new IntentFilter(
WifiManager.NETWORK_STATE_CHANGED_ACTION);
- mContext.registerReceiver(
- mWifiStateReceiver, wifiStateFilter, CONNECTIVITY_INTERNAL, mHandler);
+ mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler);
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index f995dee..b5aa4d8 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -318,7 +318,7 @@
// watch for tethering changes
final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
- mContext.registerReceiver(mTetherReceiver, tetherFilter, CONNECTIVITY_INTERNAL, mHandler);
+ mContext.registerReceiver(mTetherReceiver, tetherFilter, null, mHandler);
// listen for periodic polling events
final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
diff --git a/services/core/java/com/android/server/notification/DowntimeConditionProvider.java b/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
index 317ebef..b71bad8 100644
--- a/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
+++ b/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
@@ -43,6 +43,7 @@
import java.util.Date;
import java.util.Locale;
import java.util.Objects;
+import java.util.TimeZone;
/** Built-in zen condition provider for managing downtime */
public class DowntimeConditionProvider extends ConditionProviderService {
@@ -275,6 +276,9 @@
final long schTime = intent.getLongExtra(EXTRA_TIME, 0);
if (DEBUG) Slog.d(TAG, String.format("%s scheduled for %s, fired at %s, delta=%s",
action, ts(schTime), ts(now), now - schTime));
+ } else if (Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
+ if (DEBUG) Slog.d(TAG, "timezone changed to " + TimeZone.getDefault());
+ mCalendar.setTimeZone(TimeZone.getDefault());
} else {
if (DEBUG) Slog.d(TAG, action + " fired at " + now);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 54f043d..c09eff8 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -49,6 +49,7 @@
import android.database.ContentObserver;
import android.media.AudioAttributes;
import android.media.AudioManager;
+import android.media.AudioSystem;
import android.media.IRingtonePlayer;
import android.net.Uri;
import android.os.Binder;
@@ -1945,14 +1946,19 @@
}
private static AudioAttributes audioAttributesForNotification(Notification n) {
- if (n.audioAttributes != null
- && !Notification.AUDIO_ATTRIBUTES_DEFAULT.equals(n.audioAttributes)) {
+ if (n.audioAttributes != null) {
return n.audioAttributes;
+ } else if (n.audioStreamType >= 0 && n.audioStreamType < AudioSystem.getNumStreamTypes()) {
+ // the stream type is valid, use it
+ return new AudioAttributes.Builder()
+ .setInternalLegacyStreamType(n.audioStreamType)
+ .build();
+ } else if (n.audioStreamType == AudioSystem.STREAM_DEFAULT) {
+ return Notification.AUDIO_ATTRIBUTES_DEFAULT;
+ } else {
+ Log.w(TAG, String.format("Invalid stream type: %d", n.audioStreamType));
+ return Notification.AUDIO_ATTRIBUTES_DEFAULT;
}
- return new AudioAttributes.Builder()
- .setLegacyStreamType(n.audioStreamType)
- .setUsage(AudioAttributes.usageForLegacyStreamType(n.audioStreamType))
- .build();
}
void showNextToastLocked() {
@@ -2648,6 +2654,11 @@
if (speedBumpIndex == -1 &&
// Intrusiveness trumps priority, hence ignore intrusives.
!record.isRecentlyIntrusive() &&
+ // Currently, package priority is either PRIORITY_DEFAULT or PRIORITY_MAX, so
+ // scanning for PRIORITY_MIN within the package bucket PRIORITY_DEFAULT
+ // (or lower as a safeguard) is sufficient to find the speedbump index.
+ // We'll have to revisit this when more package priority buckets are introduced.
+ record.getPackagePriority() <= Notification.PRIORITY_DEFAULT &&
record.sbn.getNotification().priority == Notification.PRIORITY_MIN) {
speedBumpIndex = keys.size() - 1;
}
@@ -2960,15 +2971,18 @@
*/
private static final class StatusBarNotificationHolder
extends IStatusBarNotificationHolder.Stub {
- private final StatusBarNotification mValue;
+ private StatusBarNotification mValue;
public StatusBarNotificationHolder(StatusBarNotification value) {
mValue = value;
}
+ /** Get the held value and clear it. This function should only be called once per holder */
@Override
public StatusBarNotification get() {
- return mValue;
+ StatusBarNotification value = mValue;
+ mValue = null;
+ return value;
}
}
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 168328f..41d7fa8f 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -18,7 +18,6 @@
import static android.media.AudioAttributes.USAGE_ALARM;
import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
-import static android.media.AudioAttributes.USAGE_UNKNOWN;
import android.app.AppOpsManager;
import android.app.Notification;
@@ -225,11 +224,6 @@
muteCalls ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
exceptionPackages);
- // restrict vibrations with no hints
- mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, USAGE_UNKNOWN,
- zen ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
- exceptionPackages);
-
// alarm restrictions
final boolean muteAlarms = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, USAGE_ALARM,
@@ -307,8 +301,8 @@
final int ringerMode = mAudioManager.getRingerMode();
int newZen = -1;
if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
- if (mZenMode != Global.ZEN_MODE_NO_INTERRUPTIONS) {
- newZen = Global.ZEN_MODE_NO_INTERRUPTIONS;
+ if (mZenMode == Global.ZEN_MODE_OFF) {
+ newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
}
} else if ((ringerMode == AudioManager.RINGER_MODE_NORMAL
|| ringerMode == AudioManager.RINGER_MODE_VIBRATE)
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index b7b1c23..dcc4f8d 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -199,8 +199,7 @@
mainIntent.setPackage(packageName);
long ident = Binder.clearCallingIdentity();
try {
- List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent,
- PackageManager.NO_CROSS_PROFILE, // We only want the apps for this user
+ List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent, 0 /* flags */,
user.getIdentifier());
return apps;
} finally {
@@ -288,8 +287,7 @@
// as calling startActivityAsUser ignores the category and just
// resolves based on the component if present.
List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(launchIntent,
- PackageManager.NO_CROSS_PROFILE, // We only want the apps for this user
- user.getIdentifier());
+ 0 /* flags */, user.getIdentifier());
final int size = apps.size();
for (int i = 0; i < size; ++i) {
ActivityInfo activityInfo = apps.get(i).activityInfo;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 89ea905..ed678d2 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -42,7 +42,6 @@
import android.content.Intent;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
-import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageInstaller;
import android.content.pm.IPackageInstallerCallback;
import android.content.pm.IPackageInstallerSession;
@@ -50,15 +49,11 @@
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageInstaller.SessionParams;
import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.PackageLite;
-import android.content.pm.PackageParser.PackageParserException;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
-import android.os.Environment.UserEnvironment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
@@ -70,7 +65,6 @@
import android.os.SELinux;
import android.os.UserHandle;
import android.os.UserManager;
-import android.os.storage.StorageManager;
import android.system.ErrnoException;
import android.system.Os;
import android.text.TextUtils;
@@ -126,6 +120,7 @@
private static final String ATTR_CREATED_MILLIS = "createdMillis";
private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir";
private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid";
+ private static final String ATTR_PREPARED = "prepared";
private static final String ATTR_SEALED = "sealed";
private static final String ATTR_MODE = "mode";
private static final String ATTR_INSTALL_FLAGS = "installFlags";
@@ -148,7 +143,6 @@
private final Context mContext;
private final PackageManagerService mPm;
private final AppOpsManager mAppOps;
- private final StorageManager mStorage;
private final File mStagingDir;
private final HandlerThread mInstallThread;
@@ -190,7 +184,6 @@
mContext = context;
mPm = pm;
mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
- mStorage = StorageManager.from(mContext);
mStagingDir = stagingDir;
@@ -266,7 +259,9 @@
try {
final int sessionId = allocateSessionIdLocked();
mLegacySessions.put(sessionId, true);
- return prepareInternalStageDir(sessionId);
+ final File stageDir = buildInternalStageDir(sessionId);
+ prepareInternalStageDir(stageDir);
+ return stageDir;
} catch (IllegalStateException e) {
throw new IOException(e);
}
@@ -345,6 +340,7 @@
final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR);
final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null;
final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID);
+ final boolean prepared = readBooleanAttribute(in, ATTR_PREPARED, true);
final boolean sealed = readBooleanAttribute(in, ATTR_SEALED);
final SessionParams params = new SessionParams(
@@ -362,7 +358,7 @@
return new PackageInstallerSession(mInternalCallback, mContext, mPm,
mInstallThread.getLooper(), sessionId, userId, installerPackageName, params,
- createdMillis, stageDir, stageCid, sealed);
+ createdMillis, stageDir, stageCid, prepared, sealed);
}
private void writeSessionsLocked() {
@@ -410,6 +406,7 @@
if (session.stageCid != null) {
writeStringAttribute(out, ATTR_SESSION_STAGE_CID, session.stageCid);
}
+ writeBooleanAttribute(out, ATTR_PREPARED, session.isPrepared());
writeBooleanAttribute(out, ATTR_SEALED, session.isSealed());
writeIntAttribute(out, ATTR_MODE, params.mode);
@@ -449,7 +446,7 @@
private int createSessionInternal(SessionParams params, String installerPackageName, int userId)
throws IOException {
final int callingUid = Binder.getCallingUid();
- mPm.enforceCrossUserPermission(callingUid, userId, true, "createSession");
+ mPm.enforceCrossUserPermission(callingUid, userId, true, false, "createSession");
if (mPm.isUserRestricted(UserHandle.getUserId(callingUid),
UserManager.DISALLOW_INSTALL_APPS)) {
@@ -483,14 +480,10 @@
}
}
- // TODO: treat INHERIT_EXISTING as install for user
-
- // Figure out where we're going to be staging session data
- final boolean stageInternal;
-
- if (params.mode == SessionParams.MODE_FULL_INSTALL) {
- // Brand new install, use best resolved location. This also verifies
- // that target has enough free space for the install.
+ if (params.mode == SessionParams.MODE_FULL_INSTALL
+ || params.mode == SessionParams.MODE_INHERIT_EXISTING) {
+ // Resolve best location for install, based on combination of
+ // requested install flags, delta size, and manifest settings.
final long ident = Binder.clearCallingIdentity();
try {
final int resolved = PackageHelper.resolveInstallLocation(mContext,
@@ -498,46 +491,15 @@
params.installFlags);
if (resolved == PackageHelper.RECOMMEND_INSTALL_INTERNAL) {
- stageInternal = true;
+ params.setInstallFlagsInternal();
} else if (resolved == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
- stageInternal = false;
+ params.setInstallFlagsExternal();
} else {
throw new IOException("No storage with enough free space; res=" + resolved);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
- } else if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
- // Inheriting existing install, so stay on the same storage medium.
- final ApplicationInfo existingApp = mPm.getApplicationInfo(params.appPackageName, 0,
- userId);
- if (existingApp == null) {
- throw new IllegalStateException(
- "Missing existing app " + params.appPackageName);
- }
-
- final long existingSize;
- try {
- final PackageLite existingPkg = PackageParser.parsePackageLite(
- new File(existingApp.getCodePath()), 0);
- existingSize = PackageHelper.calculateInstalledSize(existingPkg, false,
- params.abiOverride);
- } catch (PackageParserException e) {
- throw new IllegalStateException(
- "Failed to calculate size of " + params.appPackageName);
- }
-
- if ((existingApp.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0) {
- // Internal we can link existing install into place, so we only
- // need enough space for the new data.
- checkInternalStorage(params.sizeBytes);
- stageInternal = true;
- } else {
- // External we're going to copy existing install into our
- // container, so we need footprint of both.
- checkExternalStorage(params.sizeBytes + existingSize);
- stageInternal = false;
- }
} else {
throw new IllegalArgumentException("Invalid install mode: " + params.mode);
}
@@ -563,15 +525,15 @@
// We're staging to exactly one location
File stageDir = null;
String stageCid = null;
- if (stageInternal) {
- stageDir = prepareInternalStageDir(sessionId);
+ if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
+ stageDir = buildInternalStageDir(sessionId);
} else {
- stageCid = prepareExternalStageCid(sessionId, params.sizeBytes);
+ stageCid = buildExternalStageCid(sessionId);
}
session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
mInstallThread.getLooper(), sessionId, userId, installerPackageName, params,
- createdMillis, stageDir, stageCid, false);
+ createdMillis, stageDir, stageCid, false, false);
mSessions.put(sessionId, session);
}
@@ -615,32 +577,16 @@
}
}
- private void checkInternalStorage(long sizeBytes) throws IOException {
- if (sizeBytes <= 0) return;
-
- final File target = Environment.getDataDirectory();
- final long targetBytes = sizeBytes + mStorage.getStorageLowBytes(target);
-
- mPm.freeStorage(targetBytes);
- if (target.getUsableSpace() < targetBytes) {
- throw new IOException("Not enough internal space to write " + sizeBytes + " bytes");
- }
- }
-
- private void checkExternalStorage(long sizeBytes) throws IOException {
- if (sizeBytes <= 0) return;
-
- final File target = new UserEnvironment(UserHandle.USER_OWNER)
- .getExternalStorageDirectory();
- final long targetBytes = sizeBytes + mStorage.getStorageLowBytes(target);
-
- if (target.getUsableSpace() < targetBytes) {
- throw new IOException("Not enough external space to write " + sizeBytes + " bytes");
- }
- }
-
@Override
public IPackageInstallerSession openSession(int sessionId) {
+ try {
+ return openSessionInternal(sessionId);
+ } catch (IOException e) {
+ throw ExceptionUtils.wrap(e);
+ }
+ }
+
+ private IPackageInstallerSession openSessionInternal(int sessionId) throws IOException {
synchronized (mSessions) {
final PackageInstallerSession session = mSessions.get(sessionId);
if (session == null || !isCallingUidOwner(session)) {
@@ -665,40 +611,37 @@
throw new IllegalStateException("Failed to allocate session ID");
}
- private File prepareInternalStageDir(int sessionId) throws IOException {
- final File file = new File(mStagingDir, "vmdl" + sessionId + ".tmp");
+ private File buildInternalStageDir(int sessionId) {
+ return new File(mStagingDir, "vmdl" + sessionId + ".tmp");
+ }
- if (file.exists()) {
- throw new IOException("Session dir already exists: " + file);
+ static void prepareInternalStageDir(File stageDir) throws IOException {
+ if (stageDir.exists()) {
+ throw new IOException("Session dir already exists: " + stageDir);
}
try {
- Os.mkdir(file.getAbsolutePath(), 0755);
- Os.chmod(file.getAbsolutePath(), 0755);
+ Os.mkdir(stageDir.getAbsolutePath(), 0755);
+ Os.chmod(stageDir.getAbsolutePath(), 0755);
} catch (ErrnoException e) {
// This purposefully throws if directory already exists
- throw new IOException("Failed to prepare session dir", e);
+ throw new IOException("Failed to prepare session dir: " + stageDir, e);
}
- if (!SELinux.restorecon(file)) {
- throw new IOException("Failed to restorecon session dir");
+ if (!SELinux.restorecon(stageDir)) {
+ throw new IOException("Failed to restorecon session dir: " + stageDir);
}
-
- return file;
}
- private String prepareExternalStageCid(int sessionId, long sizeBytes) throws IOException {
- if (sizeBytes <= 0) {
- throw new IOException("Session must provide valid size for ASEC");
- }
+ private String buildExternalStageCid(int sessionId) {
+ return "smdl" + sessionId + ".tmp";
+ }
- final String cid = "smdl" + sessionId + ".tmp";
- if (PackageHelper.createSdDir(sizeBytes, cid, PackageManagerService.getEncryptKey(),
+ static void prepareExternalStageCid(String stageCid, long sizeBytes) throws IOException {
+ if (PackageHelper.createSdDir(sizeBytes, stageCid, PackageManagerService.getEncryptKey(),
Process.SYSTEM_UID, true) == null) {
- throw new IOException("Failed to create ASEC");
+ throw new IOException("Failed to create session cid: " + stageCid);
}
-
- return cid;
}
@Override
@@ -711,7 +654,7 @@
@Override
public List<SessionInfo> getAllSessions(int userId) {
- mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getAllSessions");
+ mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "getAllSessions");
final List<SessionInfo> result = new ArrayList<>();
synchronized (mSessions) {
@@ -727,7 +670,7 @@
@Override
public List<SessionInfo> getMySessions(String installerPackageName, int userId) {
- mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getMySessions");
+ mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "getMySessions");
mAppOps.checkPackage(Binder.getCallingUid(), installerPackageName);
final List<SessionInfo> result = new ArrayList<>();
@@ -745,7 +688,7 @@
@Override
public void uninstall(String packageName, int flags, IntentSender statusReceiver, int userId) {
- mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "uninstall");
+ mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "uninstall");
final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
statusReceiver, packageName);
@@ -774,7 +717,7 @@
@Override
public void registerCallback(IPackageInstallerCallback callback, int userId) {
- mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "registerCallback");
+ mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "registerCallback");
mCallbacks.register(callback, userId);
}
@@ -1031,6 +974,12 @@
writeSessionsAsync();
}
+ public void onSessionPrepared(PackageInstallerSession session) {
+ // We prepared the destination to write into; we want to persist
+ // this, but it's not critical enough to block for.
+ writeSessionsAsync();
+ }
+
public void onSessionSealed(PackageInstallerSession session) {
// It's very important that we block until we've recorded the
// session as being sealed, since we never want to allow mutation
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index f8273c0..06f550d 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -17,15 +17,15 @@
package com.android.server.pm;
import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
-import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
import static android.content.pm.PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
-import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDONLY;
import static android.system.OsConstants.O_WRONLY;
+import static com.android.server.pm.PackageInstallerService.prepareExternalStageCid;
+import static com.android.server.pm.PackageInstallerService.prepareInternalStageDir;
import android.content.Context;
import android.content.Intent;
@@ -88,8 +88,6 @@
// TODO: enforce INSTALL_ALLOW_TEST
// TODO: enforce INSTALL_ALLOW_DOWNGRADE
- // TODO: treat INHERIT_EXISTING as installExistingPackage()
-
private final PackageInstallerService.InternalCallback mCallback;
private final Context mContext;
private final PackageManagerService mPm;
@@ -108,18 +106,23 @@
/** Note that UID is not persisted; it's always derived at runtime. */
final int installerUid;
- private final AtomicInteger mOpenCount = new AtomicInteger();
+ private final AtomicInteger mActiveCount = new AtomicInteger();
private final Object mLock = new Object();
@GuardedBy("mLock")
private float mClientProgress = 0;
@GuardedBy("mLock")
+ private float mInternalProgress = 0;
+
+ @GuardedBy("mLock")
private float mProgress = 0;
@GuardedBy("mLock")
private float mReportedProgress = -1;
@GuardedBy("mLock")
+ private boolean mPrepared = false;
+ @GuardedBy("mLock")
private boolean mSealed = false;
@GuardedBy("mLock")
private boolean mPermissionsAccepted = false;
@@ -184,7 +187,7 @@
public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
Context context, PackageManagerService pm, Looper looper, int sessionId, int userId,
String installerPackageName, SessionParams params, long createdMillis,
- File stageDir, String stageCid, boolean sealed) {
+ File stageDir, String stageCid, boolean prepared, boolean sealed) {
mCallback = callback;
mContext = context;
mPm = pm;
@@ -203,6 +206,7 @@
"Exactly one of stageDir or stageCid stage must be set");
}
+ mPrepared = prepared;
mSealed = sealed;
// Always derived at runtime
@@ -214,8 +218,6 @@
} else {
mPermissionsAccepted = false;
}
-
- computeProgressLocked();
}
public SessionInfo generateInfo() {
@@ -227,7 +229,7 @@
mResolvedBaseFile.getAbsolutePath() : null;
info.progress = mProgress;
info.sealed = mSealed;
- info.active = mOpenCount.get() > 0;
+ info.active = mActiveCount.get() > 0;
info.mode = params.mode;
info.sizeBytes = params.sizeBytes;
@@ -238,14 +240,23 @@
return info;
}
+ public boolean isPrepared() {
+ synchronized (mLock) {
+ return mPrepared;
+ }
+ }
+
public boolean isSealed() {
synchronized (mLock) {
return mSealed;
}
}
- private void assertNotSealed(String cookie) {
+ private void assertPreparedAndNotSealed(String cookie) {
synchronized (mLock) {
+ if (!mPrepared) {
+ throw new IllegalStateException(cookie + " before prepared");
+ }
if (mSealed) {
throw new SecurityException(cookie + " not allowed after commit");
}
@@ -278,30 +289,26 @@
@Override
public void setClientProgress(float progress) {
synchronized (mLock) {
+ // Always publish first staging movement
+ final boolean forcePublish = (mClientProgress == 0);
mClientProgress = progress;
- computeProgressLocked();
+ computeProgressLocked(forcePublish);
}
- maybePublishProgress();
}
@Override
public void addClientProgress(float progress) {
synchronized (mLock) {
- mClientProgress += progress;
- computeProgressLocked();
- }
- maybePublishProgress();
- }
-
- private void computeProgressLocked() {
- if (mProgress <= 0.8f) {
- mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f);
+ setClientProgress(mClientProgress + progress);
}
}
- private void maybePublishProgress() {
+ private void computeProgressLocked(boolean forcePublish) {
+ mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f)
+ + MathUtils.constrain(mInternalProgress * 0.2f, 0f, 0.2f);
+
// Only publish when meaningful change
- if (Math.abs(mProgress - mReportedProgress) > 0.01) {
+ if (forcePublish || Math.abs(mProgress - mReportedProgress) >= 0.01) {
mReportedProgress = mProgress;
mCallback.onSessionProgressChanged(this, mProgress);
}
@@ -309,7 +316,7 @@
@Override
public String[] getNames() {
- assertNotSealed("getNames");
+ assertPreparedAndNotSealed("getNames");
try {
return resolveStageDir().list();
} catch (IOException e) {
@@ -333,7 +340,7 @@
// will block any attempted install transitions.
final FileBridge bridge;
synchronized (mLock) {
- assertNotSealed("openWrite");
+ assertPreparedAndNotSealed("openWrite");
bridge = new FileBridge();
mBridges.add(bridge);
@@ -387,7 +394,7 @@
}
private ParcelFileDescriptor openReadInternal(String name) throws IOException {
- assertNotSealed("openRead");
+ assertPreparedAndNotSealed("openRead");
try {
if (!FileUtils.isValidExtFilename(name)) {
@@ -407,6 +414,30 @@
public void commit(IntentSender statusReceiver) {
Preconditions.checkNotNull(statusReceiver);
+ synchronized (mLock) {
+ if (!mSealed) {
+ // Verify that all writers are hands-off
+ for (FileBridge bridge : mBridges) {
+ if (!bridge.isClosed()) {
+ throw new SecurityException("Files still open");
+ }
+ }
+
+ // Persist the fact that we've sealed ourselves to prevent
+ // mutations of any hard links we create.
+ mSealed = true;
+ mCallback.onSessionSealed(this);
+ }
+ }
+
+ // Client staging is fully done at this point
+ mClientProgress = 1f;
+ computeProgressLocked(true);
+
+ // This ongoing commit should keep session active, even though client
+ // will probably close their end.
+ mActiveCount.incrementAndGet();
+
final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(mContext,
statusReceiver, sessionId);
mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();
@@ -414,22 +445,10 @@
private void commitLocked() throws PackageManagerException {
if (mDestroyed) {
- throw new PackageManagerException(INSTALL_FAILED_ALREADY_EXISTS, "Invalid session");
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed");
}
-
- // Verify that all writers are hands-off
if (!mSealed) {
- for (FileBridge bridge : mBridges) {
- if (!bridge.isClosed()) {
- throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
- "Files still open");
- }
- }
- mSealed = true;
-
- // Persist the fact that we've sealed ourselves to prevent mutations
- // of any hard links we create below.
- mCallback.onSessionSealed(this);
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed");
}
try {
@@ -458,6 +477,10 @@
mRemoteObserver.onUserActionRequired(intent);
} catch (RemoteException ignored) {
}
+
+ // Commit was keeping session marked as active until now; release
+ // that extra refcount so session appears idle.
+ close();
return;
}
@@ -487,8 +510,8 @@
}
// TODO: surface more granular state from dexopt
- mProgress = 0.9f;
- maybePublishProgress();
+ mInternalProgress = 0.5f;
+ computeProgressLocked(true);
// Unpack native libraries
extractNativeLibraries(mResolvedStageDir, params.abiOverride);
@@ -556,8 +579,7 @@
try {
apk = PackageParser.parseApkLite(file, PackageParser.PARSE_COLLECT_CERTIFICATES);
} catch (PackageParserException e) {
- throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
- "Failed to parse " + file + ": " + e);
+ throw PackageManagerException.from(e);
}
if (!stagedSplits.add(apk.splitName)) {
@@ -623,8 +645,7 @@
existingBase = PackageParser.parseApkLite(new File(app.getBaseCodePath()),
PackageParser.PARSE_COLLECT_CERTIFICATES);
} catch (PackageParserException e) {
- throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
- "Failed to parse existing package " + app.getCodePath() + ": " + e);
+ throw PackageManagerException.from(e);
}
assertApkConsistent("Existing base", existingBase);
@@ -676,8 +697,7 @@
try {
baseApk = PackageParser.parseApkLite(mResolvedBaseFile, 0);
} catch (PackageParserException e) {
- throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
- "Failed to parse base package " + mResolvedBaseFile + ": " + e);
+ throw PackageManagerException.from(e);
}
final List<String> splitPaths = new ArrayList<>();
@@ -831,15 +851,35 @@
}
}
- public void open() {
- if (mOpenCount.getAndIncrement() == 0) {
+ public void open() throws IOException {
+ if (mActiveCount.getAndIncrement() == 0) {
mCallback.onSessionActiveChanged(this, true);
}
+
+ synchronized (mLock) {
+ if (!mPrepared) {
+ if (stageDir != null) {
+ prepareInternalStageDir(stageDir);
+ } else if (stageCid != null) {
+ prepareExternalStageCid(stageCid, params.sizeBytes);
+
+ // TODO: deliver more granular progress for ASEC allocation
+ mInternalProgress = 0.25f;
+ computeProgressLocked(true);
+ } else {
+ throw new IllegalArgumentException(
+ "Exactly one of stageDir or stageCid stage must be set");
+ }
+
+ mPrepared = true;
+ mCallback.onSessionPrepared(this);
+ }
+ }
}
@Override
public void close() {
- if (mOpenCount.decrementAndGet() == 0) {
+ if (mActiveCount.decrementAndGet() == 0) {
mCallback.onSessionActiveChanged(this, false);
}
}
@@ -869,6 +909,11 @@
synchronized (mLock) {
mSealed = true;
mDestroyed = true;
+
+ // Force shut down all bridges
+ for (FileBridge bridge : mBridges) {
+ bridge.forceClose();
+ }
}
if (stageDir != null) {
FileUtils.deleteContents(stageDir);
diff --git a/services/core/java/com/android/server/pm/PackageManagerException.java b/services/core/java/com/android/server/pm/PackageManagerException.java
index 0cbdcdc..a41636e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerException.java
+++ b/services/core/java/com/android/server/pm/PackageManagerException.java
@@ -16,6 +16,8 @@
package com.android.server.pm;
+import android.content.pm.PackageParser.PackageParserException;
+
/** {@hide} */
public class PackageManagerException extends Exception {
public final int error;
@@ -29,4 +31,9 @@
super(detailMessage, throwable);
this.error = error;
}
+
+ public static PackageManagerException from(PackageParserException e)
+ throws PackageManagerException {
+ throw new PackageManagerException(e.error, e.getMessage(), e.getCause());
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7b4270b..3e5d514 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -138,6 +138,7 @@
import android.os.Environment;
import android.os.Environment.UserEnvironment;
import android.os.storage.StorageManager;
+import android.os.Debug;
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
@@ -1845,7 +1846,7 @@
@Override
public boolean isPackageAvailable(String packageName, int userId) {
if (!sUserManager.exists(userId)) return false;
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "is package available");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "is package available");
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
if (p != null) {
@@ -1864,7 +1865,7 @@
@Override
public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get package info");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get package info");
// reader
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
@@ -1909,7 +1910,7 @@
@Override
public int getPackageUid(String packageName, int userId) {
if (!sUserManager.exists(userId)) return -1;
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get package uid");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get package uid");
// reader
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
@@ -2059,7 +2060,7 @@
@Override
public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get application info");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get application info");
// writer
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
@@ -2150,7 +2151,7 @@
@Override
public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get activity info");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get activity info");
synchronized (mPackages) {
PackageParser.Activity a = mActivities.mActivities.get(component);
@@ -2189,7 +2190,7 @@
@Override
public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get receiver info");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get receiver info");
synchronized (mPackages) {
PackageParser.Activity a = mReceivers.mActivities.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
@@ -2207,7 +2208,7 @@
@Override
public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get service info");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get service info");
synchronized (mPackages) {
PackageParser.Service s = mServices.mServices.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
@@ -2225,7 +2226,7 @@
@Override
public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get provider info");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get provider info");
synchronized (mPackages) {
PackageParser.Provider p = mProviders.mProviders.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
@@ -2329,13 +2330,17 @@
/**
* Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS
* or INTERACT_ACROSS_USERS_FULL permissions, if the userid is not for the caller.
+ * @param checkShell TODO(yamasani):
* @param message the message to log on security exception
*/
void enforceCrossUserPermission(int callingUid, int userId, boolean requireFullPermission,
- String message) {
+ boolean checkShell, String message) {
if (userId < 0) {
throw new IllegalArgumentException("Invalid userId " + userId);
}
+ if (checkShell) {
+ enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId);
+ }
if (userId == UserHandle.getUserId(callingUid)) return;
if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
if (requireFullPermission) {
@@ -2353,6 +2358,19 @@
}
}
+ void enforceShellRestriction(String restriction, int callingUid, int userHandle) {
+ if (callingUid == Process.SHELL_UID) {
+ if (userHandle >= 0
+ && sUserManager.hasUserRestriction(restriction, userHandle)) {
+ throw new SecurityException("Shell does not have permission to access user "
+ + userHandle);
+ } else if (userHandle < 0) {
+ Slog.e(TAG, "Unable to check shell permission for user " + userHandle + "\n\t"
+ + Debug.getCallers(3));
+ }
+ }
+ }
+
private BasePermission findPermissionTreeLP(String permName) {
for(BasePermission bp : mSettings.mPermissionTrees.values()) {
if (permName.startsWith(bp.name) &&
@@ -2876,7 +2894,7 @@
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "resolve intent");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "resolve intent");
List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
return chooseBestActivity(intent, resolvedType, flags, query, userId);
}
@@ -3183,24 +3201,6 @@
if (matches.get(i).getTargetUserId() == targetUserId) return true;
}
}
- ArrayList<String> packageNames = null;
- SparseArray<ArrayList<String>> fromSource =
- mSettings.mCrossProfilePackageInfo.get(sourceUserId);
- if (fromSource != null) {
- packageNames = fromSource.get(targetUserId);
- if (packageNames != null) {
- // We need the package name, so we try to resolve with the loosest flags possible
- List<ResolveInfo> resolveInfos = mActivities.queryIntent(intent, resolvedType,
- PackageManager.GET_UNINSTALLED_PACKAGES, targetUserId);
- int count = resolveInfos.size();
- for (int i = 0; i < count; i++) {
- ResolveInfo resolveInfo = resolveInfos.get(i);
- if (packageNames.contains(resolveInfo.activityInfo.packageName)) {
- return true;
- }
- }
- }
- }
return false;
}
@@ -3217,7 +3217,7 @@
public List<ResolveInfo> queryIntentActivities(Intent intent,
String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "query intent activities");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "query intent activities");
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -3240,32 +3240,21 @@
// reader
synchronized (mPackages) {
final String pkgName = intent.getPackage();
- boolean queryCrossProfile = (flags & PackageManager.NO_CROSS_PROFILE) == 0;
if (pkgName == null) {
- ResolveInfo resolveInfo = null;
- if (queryCrossProfile) {
- // Check if the intent needs to be forwarded to another user for this package
- ArrayList<ResolveInfo> crossProfileResult =
- queryIntentActivitiesCrossProfilePackage(
- intent, resolvedType, flags, userId);
- if (!crossProfileResult.isEmpty()) {
- // Skip the current profile
- return crossProfileResult;
- }
- List<CrossProfileIntentFilter> matchingFilters =
- getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
- // Check for results that need to skip the current profile.
- resolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent,
- resolvedType, flags, userId);
- if (resolveInfo != null) {
- List<ResolveInfo> result = new ArrayList<ResolveInfo>(1);
- result.add(resolveInfo);
- return result;
- }
- // Check for cross profile results.
- resolveInfo = queryCrossProfileIntents(
- matchingFilters, intent, resolvedType, flags, userId);
+ List<CrossProfileIntentFilter> matchingFilters =
+ getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
+ // Check for results that need to skip the current profile.
+ ResolveInfo resolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent,
+ resolvedType, flags, userId);
+ if (resolveInfo != null) {
+ List<ResolveInfo> result = new ArrayList<ResolveInfo>(1);
+ result.add(resolveInfo);
+ return result;
}
+ // Check for cross profile results.
+ resolveInfo = queryCrossProfileIntents(
+ matchingFilters, intent, resolvedType, flags, userId);
+
// Check for results in the current profile.
List<ResolveInfo> result = mActivities.queryIntent(
intent, resolvedType, flags, userId);
@@ -3277,15 +3266,6 @@
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
- if (queryCrossProfile) {
- ArrayList<ResolveInfo> crossProfileResult =
- queryIntentActivitiesCrossProfilePackage(
- intent, resolvedType, flags, userId, pkg, pkgName);
- if (!crossProfileResult.isEmpty()) {
- // Skip the current profile
- return crossProfileResult;
- }
- }
return mActivities.queryIntentForPackage(intent, resolvedType, flags,
pkg.activities, userId);
}
@@ -3314,56 +3294,6 @@
return null;
}
- private ArrayList<ResolveInfo> queryIntentActivitiesCrossProfilePackage(
- Intent intent, String resolvedType, int flags, int userId) {
- ArrayList<ResolveInfo> matchingResolveInfos = new ArrayList<ResolveInfo>();
- SparseArray<ArrayList<String>> sourceForwardingInfo =
- mSettings.mCrossProfilePackageInfo.get(userId);
- if (sourceForwardingInfo != null) {
- int NI = sourceForwardingInfo.size();
- for (int i = 0; i < NI; i++) {
- int targetUserId = sourceForwardingInfo.keyAt(i);
- ArrayList<String> packageNames = sourceForwardingInfo.valueAt(i);
- List<ResolveInfo> resolveInfos = mActivities.queryIntent(
- intent, resolvedType, flags, targetUserId);
- int NJ = resolveInfos.size();
- for (int j = 0; j < NJ; j++) {
- ResolveInfo resolveInfo = resolveInfos.get(j);
- if (packageNames.contains(resolveInfo.activityInfo.packageName)) {
- matchingResolveInfos.add(createForwardingResolveInfo(
- resolveInfo.filter, userId, targetUserId));
- }
- }
- }
- }
- return matchingResolveInfos;
- }
-
- private ArrayList<ResolveInfo> queryIntentActivitiesCrossProfilePackage(
- Intent intent, String resolvedType, int flags, int userId, PackageParser.Package pkg,
- String packageName) {
- ArrayList<ResolveInfo> matchingResolveInfos = new ArrayList<ResolveInfo>();
- SparseArray<ArrayList<String>> sourceForwardingInfo =
- mSettings.mCrossProfilePackageInfo.get(userId);
- if (sourceForwardingInfo != null) {
- int NI = sourceForwardingInfo.size();
- for (int i = 0; i < NI; i++) {
- int targetUserId = sourceForwardingInfo.keyAt(i);
- if (sourceForwardingInfo.valueAt(i).contains(packageName)) {
- List<ResolveInfo> resolveInfos = mActivities.queryIntentForPackage(
- intent, resolvedType, flags, pkg.activities, targetUserId);
- int NJ = resolveInfos.size();
- for (int j = 0; j < NJ; j++) {
- ResolveInfo resolveInfo = resolveInfos.get(j);
- matchingResolveInfos.add(createForwardingResolveInfo(
- resolveInfo.filter, userId, targetUserId));
- }
- }
- }
- }
- return matchingResolveInfos;
- }
-
// Return matching ResolveInfo if any for skip current profile intent filters.
private ResolveInfo queryCrossProfileIntents(
List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
@@ -3434,7 +3364,7 @@
String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
enforceCrossUserPermission(Binder.getCallingUid(), userId, false,
- "query intent activity options");
+ false, "query intent activity options");
final String resultsAction = intent.getAction();
List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
@@ -3730,7 +3660,7 @@
public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "get installed packages");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "get installed packages");
// writer
synchronized (mPackages) {
@@ -4165,8 +4095,7 @@
pp.collectCertificates(pkg, parseFlags);
pp.collectManifestDigest(pkg);
} catch (PackageParserException e) {
- throw new PackageManagerException(e.error, "Failed to collect certificates for "
- + pkg.packageName + ": " + e.getMessage());
+ throw PackageManagerException.from(e);
}
}
@@ -4191,8 +4120,7 @@
try {
pkg = pp.parsePackage(scanFile, parseFlags);
} catch (PackageParserException e) {
- throw new PackageManagerException(e.error,
- "Failed to scan " + scanFile + ": " + e.getMessage());
+ throw PackageManagerException.from(e);
}
PackageSetting ps = null;
@@ -7750,7 +7678,7 @@
final File originFile = new File(originPath);
final int uid = Binder.getCallingUid();
- if (isUserRestricted(UserHandle.getUserId(uid), UserManager.DISALLOW_INSTALL_APPS)) {
+ if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
try {
if (observer != null) {
observer.onPackageInstalled("", INSTALL_FAILED_USER_RESTRICTED, null, null);
@@ -7838,11 +7766,8 @@
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
PackageSetting pkgSetting;
final int uid = Binder.getCallingUid();
- if (UserHandle.getUserId(uid) != userId) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
- "setApplicationHiddenSetting for user " + userId);
- }
+ enforceCrossUserPermission(uid, userId, true, true,
+ "setApplicationHiddenSetting for user " + userId);
if (hidden && isPackageDeviceAdmin(packageName, userId)) {
Slog.w(TAG, "Not hiding package " + packageName + ": has active device admin");
@@ -7901,7 +7826,7 @@
public boolean getApplicationHiddenSettingAsUser(String packageName, int userId) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
enforceCrossUserPermission(Binder.getCallingUid(), userId, true,
- "getApplicationHidden for user " + userId);
+ false, "getApplicationHidden for user " + userId);
PackageSetting pkgSetting;
long callingId = Binder.clearCallingIdentity();
try {
@@ -7927,7 +7852,8 @@
null);
PackageSetting pkgSetting;
final int uid = Binder.getCallingUid();
- enforceCrossUserPermission(uid, userId, true, "installExistingPackage for user " + userId);
+ enforceCrossUserPermission(uid, userId, true, true, "installExistingPackage for user "
+ + userId);
if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
return PackageManager.INSTALL_FAILED_USER_RESTRICTED;
}
@@ -11051,7 +10977,7 @@
final IPackageDataObserver observer, final int userId) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CLEAR_APP_USER_DATA, null);
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "clear application data");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "clear application data");
// Queue up an async operation since the package deletion may take a little while.
mHandler.post(new Runnable() {
public void run() {
@@ -11351,7 +11277,7 @@
String opname) {
// writer
int callingUid = Binder.getCallingUid();
- enforceCrossUserPermission(callingUid, userId, true, "add preferred activity");
+ enforceCrossUserPermission(callingUid, userId, true, false, "add preferred activity");
if (filter.countActions() == 0) {
Slog.w(TAG, "Cannot set a preferred activity with no filter actions");
return;
@@ -11396,7 +11322,7 @@
}
final int callingUid = Binder.getCallingUid();
- enforceCrossUserPermission(callingUid, userId, true, "replace preferred activity");
+ enforceCrossUserPermission(callingUid, userId, true, false, "replace preferred activity");
synchronized (mPackages) {
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
@@ -11537,6 +11463,7 @@
@Override
public void resetPreferredActivities(int userId) {
+ /* TODO: Actually use userId. Why is it being passed in? */
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
// writer
@@ -11651,6 +11578,7 @@
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
int callingUid = Binder.getCallingUid();
enforceOwnerRights(ownerPackage, ownerUserId, callingUid);
+ enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId);
if (intentFilter.countActions() == 0) {
Slog.w(TAG, "Cannot set a crossProfile intent filter with no filter actions");
return;
@@ -11664,30 +11592,13 @@
}
@Override
- public void addCrossProfileIntentsForPackage(String packageName,
- int sourceUserId, int targetUserId) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
- mSettings.addCrossProfilePackage(packageName, sourceUserId, targetUserId);
- mSettings.writePackageRestrictionsLPr(sourceUserId);
- }
-
- @Override
- public void removeCrossProfileIntentsForPackage(String packageName,
- int sourceUserId, int targetUserId) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
- mSettings.removeCrossProfilePackage(packageName, sourceUserId, targetUserId);
- mSettings.writePackageRestrictionsLPr(sourceUserId);
- }
-
- @Override
public void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage,
int ownerUserId) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
int callingUid = Binder.getCallingUid();
enforceOwnerRights(ownerPackage, ownerUserId, callingUid);
+ enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId);
int callingUserId = UserHandle.getUserId(callingUid);
synchronized (mPackages) {
CrossProfileIntentResolver resolver =
@@ -11782,7 +11693,7 @@
final int uid = Binder.getCallingUid();
final int permission = mContext.checkCallingOrSelfPermission(
android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
- enforceCrossUserPermission(uid, userId, false, "set enabled");
+ enforceCrossUserPermission(uid, userId, false, true, "set enabled");
final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
boolean sendNow = false;
boolean isApp = (className == null);
@@ -11916,7 +11827,7 @@
final int permission = mContext.checkCallingOrSelfPermission(
android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
- enforceCrossUserPermission(uid, userId, true, "stop package");
+ enforceCrossUserPermission(uid, userId, true, true, "stop package");
// writer
synchronized (mPackages) {
if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission,
@@ -11938,7 +11849,7 @@
public int getApplicationEnabledSetting(String packageName, int userId) {
if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
int uid = Binder.getCallingUid();
- enforceCrossUserPermission(uid, userId, false, "get enabled");
+ enforceCrossUserPermission(uid, userId, false, false, "get enabled");
// reader
synchronized (mPackages) {
return mSettings.getApplicationEnabledSettingLPr(packageName, userId);
@@ -11949,7 +11860,7 @@
public int getComponentEnabledSetting(ComponentName componentName, int userId) {
if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
int uid = Binder.getCallingUid();
- enforceCrossUserPermission(uid, userId, false, "get component enabled");
+ enforceCrossUserPermission(uid, userId, false, false, "get component enabled");
// reader
synchronized (mPackages) {
return mSettings.getComponentEnabledSettingLPr(componentName, userId);
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index c1caeac..0dadee7 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -138,10 +138,6 @@
"persistent-preferred-activities";
static final String TAG_CROSS_PROFILE_INTENT_FILTERS =
"crossProfile-intent-filters";
- private static final String TAG_CROSS_PROFILE_PACKAGE_INFO = "cross-profile-package-info";
- private static final String CROSS_PROFILE_PACKAGE_INFO_ATTR_TARGET_USER_ID = "target-user-id";
- private static final String CROSS_PROFILE_PACKAGE_INFO_TAG_PACKAGE_NAME = "package-name";
- private static final String CROSS_PROFILE_PACKAGE_INFO_ATTR_PACKAGE_NAME = "value";
private static final String ATTR_NAME = "name";
private static final String ATTR_USER = "user";
@@ -249,23 +245,15 @@
*/
private final ArrayList<PendingPackage> mPendingPackages = new ArrayList<PendingPackage>();
- private final Context mContext;
-
private final File mSystemDir;
public final KeySetManagerService mKeySetManagerService = new KeySetManagerService(mPackages);
- // A mapping of (sourceUserId, targetUserId, packageNames) for forwarding the intents of a
- // package.
- final SparseArray<SparseArray<ArrayList<String>>>
- mCrossProfilePackageInfo = new SparseArray<SparseArray<ArrayList<String>>>();
-
Settings(Context context) {
this(context, Environment.getDataDirectory());
}
Settings(Context context, File dataDir) {
- mContext = context;
mSystemDir = new File(dataDir, "system");
mSystemDir.mkdirs();
FileUtils.setPermissions(mSystemDir.toString(),
@@ -282,47 +270,6 @@
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}
- public void addCrossProfilePackage(
- String packageName, int sourceUserId, int targetUserId) {
- synchronized(mCrossProfilePackageInfo) {
- SparseArray<ArrayList<String>> sourceForwardingInfo =
- mCrossProfilePackageInfo.get(sourceUserId);
- if (sourceForwardingInfo == null) {
- sourceForwardingInfo = new SparseArray<ArrayList<String>>();
- mCrossProfilePackageInfo.put(sourceUserId, sourceForwardingInfo);
- }
- ArrayList<String> packageNames = sourceForwardingInfo.get(targetUserId);
- if (packageNames == null) {
- packageNames = new ArrayList<String>();
- sourceForwardingInfo.put(targetUserId, packageNames);
- }
- if (!packageNames.contains(packageName)) {
- packageNames.add(packageName);
- }
- }
- }
-
- public void removeCrossProfilePackage(
- String packageName, int sourceUserId, int targetUserId) {
- synchronized(mCrossProfilePackageInfo) {
- SparseArray<ArrayList<String>> sourceForwardingInfo =
- mCrossProfilePackageInfo.get(sourceUserId);
- if (sourceForwardingInfo == null) {
- return;
- }
- ArrayList<String> packageNames = sourceForwardingInfo.get(targetUserId);
- if (packageNames != null && packageNames.contains(packageName)) {
- packageNames.remove(packageName);
- if (packageNames.isEmpty()) {
- sourceForwardingInfo.remove(targetUserId);
- if (sourceForwardingInfo.size() == 0) {
- mCrossProfilePackageInfo.remove(sourceUserId);
- }
- }
- }
- }
- }
-
PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi,
@@ -517,6 +464,7 @@
int vc, int pkgFlags, UserHandle installUser, boolean add,
boolean allowInstall) {
PackageSetting p = mPackages.get(name);
+ UserManagerService userManager = UserManagerService.getInstance();
if (p != null) {
p.primaryCpuAbiString = primaryCpuAbiString;
p.secondaryCpuAbiString = secondaryCpuAbiString;
@@ -594,6 +542,7 @@
Slog.i(PackageManagerService.TAG, "Stopping package " + name, e);
}
List<UserInfo> users = getAllUsers();
+ final int installUserId = installUser != null ? installUser.getIdentifier() : 0;
if (users != null && allowInstall) {
for (UserInfo user : users) {
// By default we consider this app to be installed
@@ -603,8 +552,9 @@
// asked to install for all users, or this is the
// user we are installing for.
final boolean installed = installUser == null
- || installUser.getIdentifier() == UserHandle.USER_ALL
- || installUser.getIdentifier() == user.id;
+ || (installUserId == UserHandle.USER_ALL
+ && !isAdbInstallDisallowed(userManager, user.id))
+ || installUserId == user.id;
p.setUserState(user.id, COMPONENT_ENABLED_STATE_DEFAULT,
installed,
true, // stopped,
@@ -670,7 +620,8 @@
List<UserInfo> users = getAllUsers();
if (users != null) {
for (UserInfo user : users) {
- if (installUser.getIdentifier() == UserHandle.USER_ALL
+ if ((installUser.getIdentifier() == UserHandle.USER_ALL
+ && !isAdbInstallDisallowed(userManager, user.id))
|| installUser.getIdentifier() == user.id) {
boolean installed = p.getInstalled(user.id);
if (!installed) {
@@ -685,6 +636,11 @@
return p;
}
+ boolean isAdbInstallDisallowed(UserManagerService userManager, int userId) {
+ return userManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES,
+ userId);
+ }
+
void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) {
p.pkg = pkg;
// pkg.mSetEnabled = p.getEnabled(userId);
@@ -1068,68 +1024,6 @@
}
}
- private void readCrossProfilePackageInfoLPw(XmlPullParser parser, int userId)
- throws XmlPullParserException, IOException {
- int outerDepth = parser.getDepth();
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
- String tagName = parser.getName();
- if (tagName.equals(TAG_ITEM)) {
- String targetUserIdString = parser.getAttributeValue(null,
- CROSS_PROFILE_PACKAGE_INFO_ATTR_TARGET_USER_ID);
- if (targetUserIdString == null) {
- String msg = "Missing element under " + TAG +": "
- + CROSS_PROFILE_PACKAGE_INFO_ATTR_TARGET_USER_ID + " at " +
- parser.getPositionDescription();
- PackageManagerService.reportSettingsProblem(Log.WARN, msg);
- continue;
- }
- int targetUserId = Integer.parseInt(targetUserIdString);
- readCrossProfilePackageInfoForTargetLPw(parser, userId, targetUserId);
- } else {
- String msg = "Unknown element under " + TAG_CROSS_PROFILE_PACKAGE_INFO + ": " +
- parser.getName();
- PackageManagerService.reportSettingsProblem(Log.WARN, msg);
- XmlUtils.skipCurrentTag(parser);
- }
- }
- }
-
- private void readCrossProfilePackageInfoForTargetLPw(
- XmlPullParser parser, int sourceUserId, int targetUserId)
- throws XmlPullParserException, IOException {
- int outerDepth = parser.getDepth();
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
- String tagName = parser.getName();
- if (tagName.equals(CROSS_PROFILE_PACKAGE_INFO_TAG_PACKAGE_NAME)) {
- String packageName = parser.getAttributeValue(
- null, CROSS_PROFILE_PACKAGE_INFO_ATTR_PACKAGE_NAME);
- if (packageName == null) {
- String msg = "Missing element under " + TAG +": "
- + CROSS_PROFILE_PACKAGE_INFO_TAG_PACKAGE_NAME + " at " +
- parser.getPositionDescription();
- PackageManagerService.reportSettingsProblem(Log.WARN, msg);
- continue;
- }
- addCrossProfilePackage(packageName, sourceUserId, targetUserId);
- } else {
- String msg = "Unknown element under " + TAG_ITEM + ": " +
- parser.getName();
- PackageManagerService.reportSettingsProblem(Log.WARN, msg);
- XmlUtils.skipCurrentTag(parser);
- }
- }
- }
-
void readPackageRestrictionsLPr(int userId) {
if (DEBUG_MU) {
Log.i(TAG, "Reading package restrictions for user=" + userId);
@@ -1271,8 +1165,6 @@
readPersistentPreferredActivitiesLPw(parser, userId);
} else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
readCrossProfileIntentFiltersLPw(parser, userId);
- } else if (tagName.equals(TAG_CROSS_PROFILE_PACKAGE_INFO)){
- readCrossProfilePackageInfoLPw(parser, userId);
} else {
Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
+ parser.getName());
@@ -1364,32 +1256,6 @@
serializer.endTag(null, TAG_CROSS_PROFILE_INTENT_FILTERS);
}
- void writeCrossProfilePackageInfoLPr(XmlSerializer serializer, int userId)
- throws IllegalArgumentException, IllegalStateException, IOException {
- SparseArray<ArrayList<String>> sourceForwardingInfo = mCrossProfilePackageInfo.get(userId);
- if (sourceForwardingInfo == null) {
- return;
- }
- serializer.startTag(null, TAG_CROSS_PROFILE_PACKAGE_INFO);
- int NI = sourceForwardingInfo.size();
- for (int i = 0; i < NI; i++) {
- int targetUserId = sourceForwardingInfo.keyAt(i);
- ArrayList<String> packageNames = sourceForwardingInfo.valueAt(i);
- serializer.startTag(null, TAG_ITEM);
- serializer.attribute(null, CROSS_PROFILE_PACKAGE_INFO_ATTR_TARGET_USER_ID,
- Integer.toString(targetUserId));
- int NJ = packageNames.size();
- for (int j = 0; j < NJ; j++) {
- serializer.startTag(null, CROSS_PROFILE_PACKAGE_INFO_TAG_PACKAGE_NAME);
- serializer.attribute(null, CROSS_PROFILE_PACKAGE_INFO_ATTR_PACKAGE_NAME,
- packageNames.get(j));
- serializer.endTag(null, CROSS_PROFILE_PACKAGE_INFO_TAG_PACKAGE_NAME);
- }
- serializer.endTag(null, TAG_ITEM);
- }
- serializer.endTag(null, TAG_CROSS_PROFILE_PACKAGE_INFO);
- }
-
void writePackageRestrictionsLPr(int userId) {
if (DEBUG_MU) {
Log.i(TAG, "Writing package restrictions for user=" + userId);
@@ -1494,8 +1360,6 @@
writeCrossProfileIntentFiltersLPr(serializer, userId);
- writeCrossProfilePackageInfoLPr(serializer, userId);
-
serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
serializer.endDocument();
@@ -3180,7 +3044,6 @@
file = getUserPackagesStateBackupFile(userId);
file.delete();
removeCrossProfileIntentFiltersLPw(userId);
- removeCrossProfilePackagesLPw(userId);
}
void removeCrossProfileIntentFiltersLPw(int userId) {
@@ -3211,27 +3074,6 @@
}
}
- public void removeCrossProfilePackagesLPw(int userId) {
- synchronized(mCrossProfilePackageInfo) {
- // userId is the source user
- if (mCrossProfilePackageInfo.get(userId) != null) {
- mCrossProfilePackageInfo.remove(userId);
- writePackageRestrictionsLPr(userId);
- }
- // userId is the target user
- int count = mCrossProfilePackageInfo.size();
- for (int i = 0; i < count; i++) {
- int sourceUserId = mCrossProfilePackageInfo.keyAt(i);
- SparseArray<ArrayList<String>> sourceForwardingInfo =
- mCrossProfilePackageInfo.valueAt(i);
- if (sourceForwardingInfo.get(userId) != null) {
- sourceForwardingInfo.remove(userId);
- writePackageRestrictionsLPr(sourceUserId);
- }
- }
- }
- }
-
// This should be called (at least) whenever an application is removed
private void setFirstAvailableUid(int uid) {
if (uid > mFirstAvailableUid) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 4a2cece..26e0db3 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -21,7 +21,6 @@
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
-import android.app.ActivityThread;
import android.app.IStopUserCallback;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -34,6 +33,7 @@
import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.Bundle;
+import android.os.Debug;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
@@ -92,6 +92,7 @@
private static final String ATTR_SERIAL_NO = "serialNumber";
private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
private static final String ATTR_PARTIAL = "partial";
+ private static final String ATTR_GUEST_TO_REMOVE = "guestToRemove";
private static final String ATTR_USER_VERSION = "version";
private static final String ATTR_PROFILE_GROUP_ID = "profileGroupId";
private static final String TAG_GUEST_RESTRICTIONS = "guestRestrictions";
@@ -228,7 +229,7 @@
ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
for (int i = 0; i < mUsers.size(); i++) {
UserInfo ui = mUsers.valueAt(i);
- if (ui.partial && i != 0) {
+ if ((ui.partial || ui.guestToRemove) && i != 0) {
partials.add(ui);
}
}
@@ -480,6 +481,14 @@
}
@Override
+ public boolean hasUserRestriction(String restrictionKey, int userId) {
+ synchronized (mPackagesLock) {
+ Bundle restrictions = mUserRestrictions.get(userId);
+ return restrictions != null ? restrictions.getBoolean(restrictionKey) : false;
+ }
+ }
+
+ @Override
public Bundle getUserRestrictions(int userId) {
// checkManageUsersPermission("getUserRestrictions");
@@ -759,6 +768,9 @@
if (userInfo.partial) {
serializer.attribute(null, ATTR_PARTIAL, "true");
}
+ if (userInfo.guestToRemove) {
+ serializer.attribute(null, ATTR_GUEST_TO_REMOVE, "true");
+ }
if (userInfo.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) {
serializer.attribute(null, ATTR_PROFILE_GROUP_ID,
Integer.toString(userInfo.profileGroupId));
@@ -806,7 +818,7 @@
serializer.attribute(null, ATTR_NEXT_SERIAL_NO, Integer.toString(mNextSerialNumber));
serializer.attribute(null, ATTR_USER_VERSION, Integer.toString(mUserVersion));
- serializer.startTag(null, TAG_GUEST_RESTRICTIONS);
+ serializer.startTag(null, TAG_GUEST_RESTRICTIONS);
writeRestrictionsLocked(serializer, mGuestRestrictions);
serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
for (int i = 0; i < mUsers.size(); i++) {
@@ -855,6 +867,8 @@
writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_CALLS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_SMS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_CREATE_WINDOWS);
+ writeBoolean(serializer, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
+ writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_BEAM);
serializer.endTag(null, TAG_RESTRICTIONS);
}
@@ -871,6 +885,7 @@
int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
long lastAttemptTime = 0L;
boolean partial = false;
+ boolean guestToRemove = false;
Bundle restrictions = new Bundle();
FileInputStream fis = null;
@@ -918,6 +933,10 @@
if ("true".equals(valueString)) {
partial = true;
}
+ valueString = parser.getAttributeValue(null, ATTR_GUEST_TO_REMOVE);
+ if ("true".equals(valueString)) {
+ guestToRemove = true;
+ }
int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -942,6 +961,7 @@
userInfo.creationTime = creationTime;
userInfo.lastLoggedInTime = lastLoggedInTime;
userInfo.partial = partial;
+ userInfo.guestToRemove = guestToRemove;
userInfo.profileGroupId = profileGroupId;
mUserRestrictions.append(id, restrictions);
if (salt != 0L) {
@@ -999,6 +1019,8 @@
readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_CALLS);
readBoolean(parser, restrictions, UserManager.DISALLOW_SMS);
readBoolean(parser, restrictions, UserManager.DISALLOW_CREATE_WINDOWS);
+ readBoolean(parser, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
+ readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_BEAM);
}
private void readBoolean(XmlPullParser parser, Bundle restrictions,
@@ -1119,7 +1141,7 @@
return null;
}
// If we're adding a guest and there already exists one, bail.
- if (isGuest && numberOfUsersOfTypeLocked(UserInfo.FLAG_GUEST, true) > 0) {
+ if (isGuest && findCurrentGuestUserLocked() != null) {
return null;
}
// Limit number of managed profiles that can be created
@@ -1180,6 +1202,23 @@
}
/**
+ * Find the current guest user. If the Guest user is partial,
+ * then do not include it in the results as it is about to die.
+ * This is different than {@link #numberOfUsersOfTypeLocked(int, boolean)} due to
+ * the special handling of Guests being removed.
+ */
+ private UserInfo findCurrentGuestUserLocked() {
+ final int size = mUsers.size();
+ for (int i = 0; i < size; i++) {
+ final UserInfo user = mUsers.valueAt(i);
+ if (user.isGuest() && !user.guestToRemove && !mRemovingUserIds.get(user.id)) {
+ return user;
+ }
+ }
+ return null;
+ }
+
+ /**
* Mark this guest user for deletion to allow us to create another guest
* and switch to that user before actually removing this guest.
* @param userHandle the userid of the current guest
@@ -1204,14 +1243,15 @@
if (!user.isGuest()) {
return false;
}
- // Set this to a partially created user, so that the user will be purged
- // on next startup, in case the runtime stops now before stopping and
- // removing the user completely.
- user.partial = true;
+ // We set this to a guest user that is to be removed. This is a temporary state
+ // where we are allowed to add new Guest users, even if this one is still not
+ // removed. This user will still show up in getUserInfo() calls.
+ // If we don't get around to removing this Guest user, it will be purged on next
+ // startup.
+ user.guestToRemove = true;
// Mark it as disabled, so that it isn't returned any more when
// profiles are queried.
user.flags |= UserInfo.FLAG_DISABLED;
- user.flags &= ~UserInfo.FLAG_GUEST;
writeUserLocked(user);
}
} finally {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 5f97a00..7808800 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -91,8 +91,6 @@
private static final int MSG_SANDMAN = 2;
// Message: Sent when the screen on blocker is released.
private static final int MSG_SCREEN_ON_BLOCKER_RELEASED = 3;
- // Message: Sent to poll whether the boot animation has terminated.
- private static final int MSG_CHECK_IF_BOOT_ANIMATION_FINISHED = 4;
// Dirty bit: mWakeLocks changed
private static final int DIRTY_WAKE_LOCKS = 1 << 0;
@@ -154,12 +152,6 @@
// provider populates the actual default value (R.integer.def_screen_off_timeout).
private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15 * 1000;
- // The name of the boot animation service in init.rc.
- private static final String BOOT_ANIMATION_SERVICE = "bootanim";
-
- // Poll interval in milliseconds for watching boot animation finished.
- private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
-
// Power hints defined in hardware/libhardware/include/hardware/power.h.
private static final int POWER_HINT_INTERACTION = 2;
private static final int POWER_HINT_LOW_POWER = 5;
@@ -478,14 +470,15 @@
@Override
public void onBootPhase(int phase) {
- if (phase == PHASE_BOOT_COMPLETED) {
- // This is our early signal that the system thinks it has finished booting.
- // However, the boot animation may still be running for a few more seconds
- // since it is ultimately in charge of when it terminates.
- // Defer transitioning into the boot completed state until the animation exits.
- // We do this so that the screen does not start to dim prematurely before
- // the user has actually had a chance to interact with the device.
- startWatchingForBootAnimationFinished();
+ synchronized (mLock) {
+ if (phase == PHASE_BOOT_COMPLETED) {
+ final long now = SystemClock.uptimeMillis();
+ mBootCompleted = true;
+ mDirty |= DIRTY_BOOT_COMPLETED;
+ userActivityNoUpdateLocked(
+ now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
+ updatePowerStateLocked();
+ }
}
}
@@ -2076,38 +2069,6 @@
updatePowerStateLocked();
}
- private void startWatchingForBootAnimationFinished() {
- mHandler.sendEmptyMessage(MSG_CHECK_IF_BOOT_ANIMATION_FINISHED);
- }
-
- private void checkIfBootAnimationFinished() {
- if (DEBUG) {
- Slog.d(TAG, "Check if boot animation finished...");
- }
-
- if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) {
- mHandler.sendEmptyMessageDelayed(MSG_CHECK_IF_BOOT_ANIMATION_FINISHED,
- BOOT_ANIMATION_POLL_INTERVAL);
- return;
- }
-
- synchronized (mLock) {
- if (!mBootCompleted) {
- Slog.i(TAG, "Boot animation finished.");
- handleBootCompletedLocked();
- }
- }
- }
-
- private void handleBootCompletedLocked() {
- final long now = SystemClock.uptimeMillis();
- mBootCompleted = true;
- mDirty |= DIRTY_BOOT_COMPLETED;
- userActivityNoUpdateLocked(
- now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
- updatePowerStateLocked();
- }
-
private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm,
final String reason, boolean wait) {
if (mHandler == null || !mSystemReady) {
@@ -2528,9 +2489,6 @@
case MSG_SCREEN_ON_BLOCKER_RELEASED:
handleScreenOnBlockerReleased();
break;
- case MSG_CHECK_IF_BOOT_ANIMATION_FINISHED:
- checkIfBootAnimationFinished();
- break;
}
}
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index c8b5b3e..fefbe0a 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -33,6 +33,7 @@
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.ResolveInfo;
import android.content.pm.UserInfo;
@@ -48,6 +49,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.service.trust.TrustAgentService;
import android.util.ArraySet;
import android.util.AttributeSet;
@@ -97,6 +99,7 @@
private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray();
/* package */ final TrustArchive mArchive = new TrustArchive();
private final Context mContext;
+ private final LockPatternUtils mLockPatternUtils;
private UserManager mUserManager;
@@ -104,6 +107,7 @@
super(context);
mContext = context;
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mLockPatternUtils = new LockPatternUtils(context);
}
@Override
@@ -116,6 +120,7 @@
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) {
mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
mReceiver.register(mContext);
+ maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_OWNER);
refreshAgentList(UserHandle.USER_ALL);
}
}
@@ -159,6 +164,11 @@
void refreshAgentList(int userId) {
if (DEBUG) Slog.d(TAG, "refreshAgentList()");
+ if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) {
+ Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle,"
+ + " must be USER_ALL or a specific user.", new Throwable("here"));
+ userId = UserHandle.USER_ALL;
+ }
PackageManager pm = mContext.getPackageManager();
List<UserInfo> userInfos;
@@ -168,12 +178,13 @@
userInfos = new ArrayList<>();
userInfos.add(mUserManager.getUserInfo(userId));
}
- LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
+ LockPatternUtils lockPatternUtils = mLockPatternUtils;
ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>();
obsoleteAgents.addAll(mActiveAgents);
for (UserInfo userInfo : userInfos) {
+ if (!userInfo.supportsSwitchTo()) continue;
if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id)
== DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue;
if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue;
@@ -186,22 +197,11 @@
if (enabledAgents == null) {
continue;
}
- List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
- PackageManager.GET_META_DATA, userInfo.id);
+ List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userInfo.id);
for (ResolveInfo resolveInfo : resolveInfos) {
- if (resolveInfo.serviceInfo == null) continue;
-
- String packageName = resolveInfo.serviceInfo.packageName;
- if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
- != PackageManager.PERMISSION_GRANTED) {
- Log.w(TAG, "Skipping agent because package " + packageName
- + " does not have permission " + PERMISSION_PROVIDE_AGENT + ".");
- continue;
- }
-
ComponentName name = getComponentName(resolveInfo);
- if (!enabledAgents.contains(name)) continue;
+ if (!enabledAgents.contains(name)) continue;
if (disableTrustAgents) {
List<String> features =
dpm.getTrustAgentFeaturesEnabled(null /* admin */, name);
@@ -228,11 +228,13 @@
boolean trustMayHaveChanged = false;
for (int i = 0; i < obsoleteAgents.size(); i++) {
AgentInfo info = obsoleteAgents.valueAt(i);
- if (info.agent.isManagingTrust()) {
- trustMayHaveChanged = true;
+ if (userId == UserHandle.USER_ALL || userId == info.userId) {
+ if (info.agent.isManagingTrust()) {
+ trustMayHaveChanged = true;
+ }
+ info.agent.unbind();
+ mActiveAgents.remove(info);
}
- info.agent.unbind();
- mActiveAgents.remove(info);
}
if (trustMayHaveChanged) {
@@ -342,6 +344,54 @@
return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
}
+ private void maybeEnableFactoryTrustAgents(LockPatternUtils utils, int userId) {
+ if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
+ return;
+ }
+ PackageManager pm = mContext.getPackageManager();
+ List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId);
+ ArraySet<ComponentName> discoveredAgents = new ArraySet<>();
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ ComponentName componentName = getComponentName(resolveInfo);
+ int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags;
+ if ((applicationInfoFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+ Log.i(TAG, "Leaving agent " + componentName + " disabled because package "
+ + "is not a system package.");
+ continue;
+ }
+ discoveredAgents.add(componentName);
+ }
+
+ List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
+ if (previouslyEnabledAgents != null) {
+ discoveredAgents.addAll(previouslyEnabledAgents);
+ }
+ utils.setEnabledTrustAgents(discoveredAgents, userId);
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId);
+ }
+
+ private List<ResolveInfo> resolveAllowedTrustAgents(PackageManager pm, int userId) {
+ List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
+ 0 /* flags */, userId);
+ ArrayList<ResolveInfo> allowedAgents = new ArrayList<>(resolveInfos.size());
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ if (resolveInfo.serviceInfo == null) continue;
+ if (resolveInfo.serviceInfo.applicationInfo == null) continue;
+ String packageName = resolveInfo.serviceInfo.packageName;
+ if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
+ != PackageManager.PERMISSION_GRANTED) {
+ ComponentName name = getComponentName(resolveInfo);
+ Log.w(TAG, "Skipping agent " + name + " because package does not have"
+ + " permission " + PERMISSION_PROVIDE_AGENT + ".");
+ continue;
+ }
+ allowedAgents.add(resolveInfo);
+ }
+ return allowedAgents;
+ }
+
// Agent dispatch and aggregation
private boolean aggregateIsTrusted(int userId) {
@@ -414,6 +464,7 @@
}
}
mTrustListeners.add(listener);
+ updateTrustAll();
}
private void removeListener(ITrustListener listener) {
@@ -616,12 +667,19 @@
@Override
public void onReceive(Context context, Intent intent) {
- if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(
- intent.getAction())) {
+ String action = intent.getAction();
+ if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
refreshAgentList(getSendingUserId());
updateDevicePolicyFeatures();
- } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
+ } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
updateUserHasAuthenticated(getSendingUserId());
+ } else if (Intent.ACTION_USER_ADDED.equals(action)) {
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -100);
+ if (userId > 0) {
+ maybeEnableFactoryTrustAgents(mLockPatternUtils, userId);
+ } else {
+ Log.wtf(TAG, "EXTRA_USER_HANDLE missing or invalid, value=" + userId);
+ }
}
}
@@ -629,6 +687,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
filter.addAction(Intent.ACTION_USER_PRESENT);
+ filter.addAction(Intent.ACTION_USER_ADDED);
context.registerReceiverAsUser(this,
UserHandle.ALL,
filter,
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 3380f71..adae84fd 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -85,6 +85,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -139,7 +140,7 @@
registerBroadcastReceivers();
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
synchronized (mLock) {
- buildTvInputListLocked(mCurrentUserId);
+ buildTvInputListLocked(mCurrentUserId, null);
buildTvContentRatingSystemListLocked(mCurrentUserId);
}
}
@@ -148,19 +149,64 @@
private void registerBroadcastReceivers() {
PackageMonitor monitor = new PackageMonitor() {
+ private void buildTvInputList(String[] packages) {
+ synchronized (mLock) {
+ buildTvInputListLocked(getChangingUserId(), packages);
+ buildTvContentRatingSystemListLocked(getChangingUserId());
+ }
+ }
+
+ @Override
+ public void onPackageUpdateFinished(String packageName, int uid) {
+ if (DEBUG) Slog.d(TAG, "onPackageUpdateFinished(packageName=" + packageName + ")");
+ // This callback is invoked when the TV input is reinstalled.
+ // In this case, isReplacing() always returns true.
+ buildTvInputList(new String[] { packageName });
+ }
+
+ @Override
+ public void onPackagesAvailable(String[] packages) {
+ if (DEBUG) {
+ Slog.d(TAG, "onPackagesAvailable(packages=" + Arrays.toString(packages) + ")");
+ }
+ // This callback is invoked when the media on which some packages exist become
+ // available.
+ if (isReplacing()) {
+ buildTvInputList(packages);
+ }
+ }
+
+ @Override
+ public void onPackagesUnavailable(String[] packages) {
+ // This callback is invoked when the media on which some packages exist become
+ // unavailable.
+ if (DEBUG) {
+ Slog.d(TAG, "onPackagesUnavailable(packages=" + Arrays.toString(packages)
+ + ")");
+ }
+ if (isReplacing()) {
+ buildTvInputList(packages);
+ }
+ }
+
@Override
public void onSomePackagesChanged() {
+ // TODO: Use finer-grained methods(e.g. onPackageAdded, onPackageRemoved) to manage
+ // the TV inputs.
if (DEBUG) Slog.d(TAG, "onSomePackagesChanged()");
- synchronized (mLock) {
- buildTvInputListLocked(mCurrentUserId);
- buildTvContentRatingSystemListLocked(mCurrentUserId);
+ if (isReplacing()) {
+ if (DEBUG) Slog.d(TAG, "Skipped building TV input list due to replacing");
+ // When the package is updated, buildTvInputListLocked is called in other
+ // methods instead.
+ return;
}
+ buildTvInputList(null);
}
@Override
public void onPackageRemoved(String packageName, int uid) {
synchronized (mLock) {
- UserState userState = getUserStateLocked(mCurrentUserId);
+ UserState userState = getUserStateLocked(getChangingUserId());
if (!userState.packageSet.contains(packageName)) {
// Not a TV input package.
return;
@@ -218,13 +264,11 @@
component.getPackageName()) == PackageManager.PERMISSION_GRANTED;
}
- private void buildTvInputListLocked(int userId) {
+ private void buildTvInputListLocked(int userId, String[] updatedPackages) {
UserState userState = getUserStateLocked(userId);
userState.packageSet.clear();
- if (DEBUG) {
- Slog.d(TAG, "buildTvInputList");
- }
+ if (DEBUG) Slog.d(TAG, "buildTvInputList");
PackageManager pm = mContext.getPackageManager();
List<ResolveInfo> services = pm.queryIntentServices(
new Intent(TvInputService.SERVICE_INTERFACE),
@@ -278,6 +322,15 @@
for (String inputId : inputMap.keySet()) {
if (!userState.inputMap.containsKey(inputId)) {
notifyInputAddedLocked(userState, inputId);
+ } else if (updatedPackages != null) {
+ // Notify the package updates
+ TvInputState inputState = inputMap.get(inputId);
+ for (String updatedPackage : updatedPackages) {
+ if (inputState.info.getComponent().getPackageName().equals(updatedPackage)) {
+ notifyInputUpdatedLocked(userState, inputId);
+ break;
+ }
+ }
}
}
@@ -337,7 +390,7 @@
userState = new UserState(mContext, userId);
}
mUserStates.put(userId, userState);
- buildTvInputListLocked(userId);
+ buildTvInputListLocked(userId, null);
buildTvContentRatingSystemListLocked(userId);
}
}
@@ -649,6 +702,19 @@
}
}
+ private void notifyInputUpdatedLocked(UserState userState, String inputId) {
+ if (DEBUG) {
+ Slog.d(TAG, "notifyInputUpdatedLocked(inputId=" + inputId + ")");
+ }
+ for (ITvInputManagerCallback callback : userState.callbackSet) {
+ try {
+ callback.onInputUpdated(inputId);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "failed to report updated input to callback", e);
+ }
+ }
+ }
+
private void notifyInputStateChangedLocked(UserState userState, String inputId,
int state, ITvInputManagerCallback targetCallback) {
if (DEBUG) {
@@ -1813,7 +1879,7 @@
private void addTvInputLocked(TvInputInfo inputInfo) {
ServiceState serviceState = getServiceStateLocked(mComponent, mUserId);
serviceState.inputList.add(inputInfo);
- buildTvInputListLocked(mUserId);
+ buildTvInputListLocked(mUserId, null);
}
@Override
@@ -1851,7 +1917,7 @@
}
}
if (removed) {
- buildTvInputListLocked(mUserId);
+ buildTvInputListLocked(mUserId, null);
mTvInputHardwareManager.removeTvInput(inputId);
} else {
Slog.e(TAG, "failed to remove input " + inputId);
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 802df95..a8245e7 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -42,6 +42,7 @@
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Point;
+import android.graphics.Rect;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
@@ -206,6 +207,8 @@
int width = -1;
int height = -1;
+ final Rect padding = new Rect(0, 0, 0, 0);
+
WallpaperData(int userId) {
this.userId = userId;
wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
@@ -222,6 +225,7 @@
IRemoteCallback mReply;
boolean mDimensionsChanged = false;
+ boolean mPaddingChanged = false;
public WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper) {
mInfo = info;
@@ -283,6 +287,14 @@
}
mDimensionsChanged = false;
}
+ if (mPaddingChanged) {
+ try {
+ mEngine.setDisplayPadding(mWallpaper.padding);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to set wallpaper padding", e);
+ }
+ mPaddingChanged = false;
+ }
}
}
@@ -719,6 +731,40 @@
}
}
+ public void setDisplayPadding(Rect padding) {
+ checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
+ synchronized (mLock) {
+ int userId = UserHandle.getCallingUserId();
+ WallpaperData wallpaper = mWallpaperMap.get(userId);
+ if (wallpaper == null) {
+ throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
+ }
+ if (padding.left < 0 || padding.top < 0 || padding.right < 0 || padding.bottom < 0) {
+ throw new IllegalArgumentException("padding must be positive: " + padding);
+ }
+
+ if (!padding.equals(wallpaper.padding)) {
+ wallpaper.padding.set(padding);
+ saveSettingsLocked(wallpaper);
+ if (mCurrentUserId != userId) return; // Don't change the properties now
+ if (wallpaper.connection != null) {
+ if (wallpaper.connection.mEngine != null) {
+ try {
+ wallpaper.connection.mEngine.setDisplayPadding(padding);
+ } catch (RemoteException e) {
+ }
+ notifyCallbacksLocked(wallpaper);
+ } else if (wallpaper.connection.mService != null) {
+ // We've attached to the service but the engine hasn't attached back to us
+ // yet. This means it will be created with the previous dimensions, so we
+ // need to update it to the new dimensions once it attaches.
+ wallpaper.connection.mPaddingChanged = true;
+ }
+ }
+ }
+ }
+ }
+
public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
Bundle outParams) {
synchronized (mLock) {
@@ -797,7 +843,7 @@
}
File file = new File(dir, WALLPAPER);
ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
- MODE_CREATE|MODE_READ_WRITE);
+ MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
if (!SELinux.restorecon(file)) {
return null;
}
@@ -1006,7 +1052,7 @@
try {
conn.mService.attach(conn, conn.mToken,
WindowManager.LayoutParams.TYPE_WALLPAPER, false,
- wallpaper.width, wallpaper.height);
+ wallpaper.width, wallpaper.height, wallpaper.padding);
} catch (RemoteException e) {
Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
if (!wallpaper.wallpaperUpdating) {
@@ -1055,6 +1101,18 @@
out.startTag(null, "wp");
out.attribute(null, "width", Integer.toString(wallpaper.width));
out.attribute(null, "height", Integer.toString(wallpaper.height));
+ if (wallpaper.padding.left != 0) {
+ out.attribute(null, "paddingLeft", Integer.toString(wallpaper.padding.left));
+ }
+ if (wallpaper.padding.top != 0) {
+ out.attribute(null, "paddingTop", Integer.toString(wallpaper.padding.top));
+ }
+ if (wallpaper.padding.right != 0) {
+ out.attribute(null, "paddingRight", Integer.toString(wallpaper.padding.right));
+ }
+ if (wallpaper.padding.bottom != 0) {
+ out.attribute(null, "paddingBottom", Integer.toString(wallpaper.padding.bottom));
+ }
out.attribute(null, "name", wallpaper.name);
if (wallpaper.wallpaperComponent != null
&& !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
@@ -1091,6 +1149,14 @@
}
}
+ private int getAttributeInt(XmlPullParser parser, String name, int defValue) {
+ String value = parser.getAttributeValue(null, name);
+ if (value == null) {
+ return defValue;
+ }
+ return Integer.parseInt(value);
+ }
+
private void loadSettingsLocked(int userId) {
if (DEBUG) Slog.v(TAG, "loadSettingsLocked");
@@ -1121,6 +1187,10 @@
wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width"));
wallpaper.height = Integer.parseInt(parser
.getAttributeValue(null, "height"));
+ wallpaper.padding.left = getAttributeInt(parser, "paddingLeft", 0);
+ wallpaper.padding.top = getAttributeInt(parser, "paddingTop", 0);
+ wallpaper.padding.right = getAttributeInt(parser, "paddingRight", 0);
+ wallpaper.padding.bottom = getAttributeInt(parser, "paddingBottom", 0);
wallpaper.name = parser.getAttributeValue(null, "name");
String comp = parser.getAttributeValue(null, "component");
wallpaper.nextWallpaperComponent = comp != null
@@ -1167,6 +1237,7 @@
if (!success) {
wallpaper.width = -1;
wallpaper.height = -1;
+ wallpaper.padding.set(0, 0, 0, 0);
wallpaper.name = "";
}
@@ -1330,13 +1401,12 @@
WallpaperData wallpaper = mWallpaperMap.valueAt(i);
pw.println(" User " + wallpaper.userId + ":");
pw.print(" mWidth=");
- pw.print(wallpaper.width);
- pw.print(" mHeight=");
- pw.println(wallpaper.height);
- pw.print(" mName=");
- pw.println(wallpaper.name);
- pw.print(" mWallpaperComponent=");
- pw.println(wallpaper.wallpaperComponent);
+ pw.print(wallpaper.width);
+ pw.print(" mHeight=");
+ pw.println(wallpaper.height);
+ pw.print(" mPadding="); pw.println(wallpaper.padding);
+ pw.print(" mName="); pw.println(wallpaper.name);
+ pw.print(" mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent);
if (wallpaper.connection != null) {
WallpaperConnection conn = wallpaper.connection;
pw.print(" Wallpaper connection ");
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index aabb8f7..bfc7659 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -569,9 +569,9 @@
int appWidth, int appHeight, int orientation, int transit, Rect containingFrame,
Rect contentInsets, boolean isFullScreen) {
Animation a;
- final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
+ final int thumbWidthI = mNextAppTransitionStartWidth;
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
- final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
+ final int thumbHeightI = mNextAppTransitionStartHeight;
final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
// Used for the ENTER_SCALE_UP and EXIT_SCALE_DOWN transitions
@@ -993,7 +993,7 @@
}
void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, int startY,
- IRemoteCallback startedCallback, boolean scaleUp) {
+ int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp) {
if (isTransitionSet()) {
mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
: NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
@@ -1002,6 +1002,8 @@
mNextAppTransitionScaleUp = scaleUp;
mNextAppTransitionStartX = startX;
mNextAppTransitionStartY = startY;
+ mNextAppTransitionStartWidth = targetWidth;
+ mNextAppTransitionStartHeight = targetHeight;
postAnimationCallback();
mNextAppTransitionCallback = startedCallback;
} else {
@@ -1138,6 +1140,10 @@
pw.print(mNextAppTransitionStartX);
pw.print(" mNextAppTransitionStartY=");
pw.println(mNextAppTransitionStartY);
+ pw.print(" mNextAppTransitionStartWidth=");
+ pw.print(mNextAppTransitionStartWidth);
+ pw.print(" mNextAppTransitionStartHeight=");
+ pw.println(mNextAppTransitionStartHeight);
pw.print(" mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp);
break;
}
diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java
index 64b852b..a7d41fa 100644
--- a/services/core/java/com/android/server/wm/CircularDisplayMask.java
+++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java
@@ -63,8 +63,14 @@
SurfaceControl ctrl = null;
try {
- ctrl = new SurfaceControl(session, "CircularDisplayMask",
- mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+ if (WindowManagerService.DEBUG_SURFACE_TRACE) {
+ ctrl = new WindowStateAnimator.SurfaceTrace(session, "CircularDisplayMask",
+ mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT,
+ SurfaceControl.HIDDEN);
+ } else {
+ ctrl = new SurfaceControl(session, "CircularDisplayMask", mScreenSize.x,
+ mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+ }
ctrl.setLayerStack(display.getLayerStack());
ctrl.setLayer(zOrder);
ctrl.setPosition(0, 0);
diff --git a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
new file mode 100644
index 0000000..62f2b48
--- /dev/null
+++ b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
@@ -0,0 +1,127 @@
+/*
+ * 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.wm;
+
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.Slog;
+import android.view.Display;
+import android.view.Surface;
+import android.view.Surface.OutOfResourcesException;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+class EmulatorDisplayOverlay {
+ private static final String TAG = "EmulatorDisplayOverlay";
+
+ // Display dimensions
+ private Point mScreenSize;
+
+ private final SurfaceControl mSurfaceControl;
+ private final Surface mSurface = new Surface();
+ private int mLastDW;
+ private int mLastDH;
+ private boolean mDrawNeeded;
+ private Drawable mOverlay;
+ private int mRotation;
+ private boolean mVisible;
+
+ public EmulatorDisplayOverlay(Context context, Display display, SurfaceSession session,
+ int zOrder) {
+ mScreenSize = new Point();
+ display.getSize(mScreenSize);
+
+ SurfaceControl ctrl = null;
+ try {
+ if (WindowManagerService.DEBUG_SURFACE_TRACE) {
+ ctrl = new WindowStateAnimator.SurfaceTrace(session, "EmulatorDisplayOverlay",
+ mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT,
+ SurfaceControl.HIDDEN);
+ } else {
+ ctrl = new SurfaceControl(session, "EmulatorDisplayOverlay", mScreenSize.x,
+ mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+ }
+ ctrl.setLayerStack(display.getLayerStack());
+ ctrl.setLayer(zOrder);
+ ctrl.setPosition(0, 0);
+ ctrl.show();
+ mSurface.copyFrom(ctrl);
+ } catch (OutOfResourcesException e) {
+ }
+ mSurfaceControl = ctrl;
+ mDrawNeeded = true;
+ mOverlay = context.getDrawable(
+ com.android.internal.R.drawable.emulator_circular_window_overlay);
+ }
+
+ private void drawIfNeeded() {
+ if (!mDrawNeeded || !mVisible) {
+ return;
+ }
+ mDrawNeeded = false;
+
+ Rect dirty = new Rect(0, 0, mScreenSize.x, mScreenSize.y);
+ Canvas c = null;
+ try {
+ c = mSurface.lockCanvas(dirty);
+ } catch (IllegalArgumentException e) {
+ } catch (OutOfResourcesException e) {
+ }
+ if (c == null) {
+ return;
+ }
+ c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC);
+ mSurfaceControl.setPosition(0, 0);
+ mOverlay.setBounds(0, 0, mScreenSize.x, mScreenSize.y);
+ mOverlay.draw(c);
+ mSurface.unlockCanvasAndPost(c);
+ }
+
+ // Note: caller responsible for being inside
+ // Surface.openTransaction() / closeTransaction()
+ public void setVisibility(boolean on) {
+ if (mSurfaceControl == null) {
+ return;
+ }
+ mVisible = on;
+ drawIfNeeded();
+ if (on) {
+ mSurfaceControl.show();
+ } else {
+ mSurfaceControl.hide();
+ }
+ }
+
+ void positionSurface(int dw, int dh, int rotation) {
+ if (mLastDW == dw && mLastDH == dh && mRotation == rotation) {
+ return;
+ }
+ mLastDW = dw;
+ mLastDH = dh;
+ mDrawNeeded = true;
+ mRotation = rotation;
+ drawIfNeeded();
+ }
+
+}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index f2703ad..d737e7f 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -415,6 +415,18 @@
mService.wallpaperOffsetsComplete(window);
}
+ public void setWallpaperDisplayOffset(IBinder window, int x, int y) {
+ synchronized(mService.mWindowMap) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ mService.setWindowWallpaperDisplayOffsetLocked(
+ mService.windowForClientLocked(this, window, true), x, y);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
int z, Bundle extras, boolean sync) {
synchronized(mService.mWindowMap) {
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 81cd602..50e417b 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -568,6 +568,15 @@
mBulkUpdateParams |= SET_UPDATE_ROTATION;
screenRotationAnimation.kill();
displayAnimator.mScreenRotationAnimation = null;
+
+ //TODO (multidisplay): Accessibility supported only for the default display.
+ if (mService.mAccessibilityController != null
+ && displayId == Display.DEFAULT_DISPLAY) {
+ // We just finished rotation animation which means we did not
+ // anounce the rotation and waited for it to end, announce now.
+ mService.mAccessibilityController.onRotationChangedLocked(
+ mService.getDefaultDisplayContentLocked(), mService.mRotation);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a1afe29..b7e56cbf 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -20,6 +20,8 @@
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import android.app.AppOpsManager;
+import android.os.Build;
+import android.os.SystemService;
import android.util.ArraySet;
import android.util.TimeUtils;
import android.view.IWindowId;
@@ -271,6 +273,12 @@
// Default input dispatching timeout in nanoseconds.
static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
+ // Poll interval in milliseconds for watching boot animation finished.
+ private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
+
+ // The name of the boot animation service in init.rc.
+ private static final String BOOT_ANIMATION_SERVICE = "bootanim";
+
/** Minimum value for attachStack and resizeStack weight value */
public static final float STACK_WEIGHT_MIN = 0.2f;
@@ -295,6 +303,8 @@
private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
+
final private KeyguardDisableHandler mKeyguardDisableHandler;
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -441,6 +451,7 @@
Watermark mWatermark;
StrictModeFlash mStrictModeFlash;
CircularDisplayMask mCircularDisplayMask;
+ EmulatorDisplayOverlay mEmulatorDisplayOverlay;
FocusedStackFrame mFocusedStackFrame;
int mFocusedStackLayer;
@@ -454,6 +465,7 @@
boolean mSystemBooted = false;
boolean mForceDisplayEnabled = false;
boolean mShowingBootMessages = false;
+ boolean mBootAnimationStopped = false;
String mLastANRState;
@@ -572,6 +584,8 @@
float mLastWallpaperY = -1;
float mLastWallpaperXStep = -1;
float mLastWallpaperYStep = -1;
+ int mLastWallpaperDisplayOffsetX = Integer.MIN_VALUE;
+ int mLastWallpaperDisplayOffsetY = Integer.MIN_VALUE;
// This is set when we are waiting for a wallpaper to tell us it is done
// changing its scroll position.
WindowState mWaitingOnWallpaper;
@@ -879,6 +893,7 @@
}
showCircularDisplayMaskIfNeeded();
+ showEmulatorDisplayOverlayIfNeeded();
}
public InputMonitor getInputMonitor() {
@@ -1892,6 +1907,12 @@
mLastWallpaperY = mWallpaperTarget.mWallpaperY;
mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
}
+ if (mWallpaperTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetX = mWallpaperTarget.mWallpaperDisplayOffsetX;
+ }
+ if (mWallpaperTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetY = mWallpaperTarget.mWallpaperDisplayOffsetY;
+ }
}
// Start stepping backwards from here, ensuring that our wallpaper windows
@@ -2030,6 +2051,9 @@
float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
+ if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+ offset += mLastWallpaperDisplayOffsetX;
+ }
changed = wallpaperWin.mXOffset != offset;
if (changed) {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
@@ -2046,6 +2070,9 @@
float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
+ if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ offset += mLastWallpaperDisplayOffsetY;
+ }
if (wallpaperWin.mYOffset != offset) {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
+ wallpaperWin + " y: " + offset);
@@ -2130,6 +2157,16 @@
} else if (changingTarget.mWallpaperY >= 0) {
mLastWallpaperY = changingTarget.mWallpaperY;
}
+ if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX;
+ } else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetX = changingTarget.mWallpaperDisplayOffsetX;
+ }
+ if (target.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetY = target.mWallpaperDisplayOffsetY;
+ } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY;
+ }
}
int curTokenIndex = mWallpaperTokens.size();
@@ -2826,6 +2863,14 @@
}
}
+ public void setWindowWallpaperDisplayOffsetLocked(WindowState window, int x, int y) {
+ if (window.mWallpaperDisplayOffsetX != x || window.mWallpaperDisplayOffsetY != y) {
+ window.mWallpaperDisplayOffsetX = x;
+ window.mWallpaperDisplayOffsetY = y;
+ updateWallpaperOffsetLocked(window, true);
+ }
+ }
+
public Bundle sendWindowWallpaperCommandLocked(WindowState window,
String action, int x, int y, int z, Bundle extras, boolean sync) {
if (window == mWallpaperTarget || window == mLowerWallpaperTarget
@@ -4031,10 +4076,11 @@
@Override
public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
- int startY, IRemoteCallback startedCallback, boolean scaleUp) {
+ int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
+ boolean scaleUp) {
synchronized(mWindowMap) {
mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX,
- startY, startedCallback, scaleUp);
+ startY, targetWidth, targetHeight, startedCallback, scaleUp);
}
}
@@ -4303,20 +4349,28 @@
}
public void setAppFullscreen(IBinder token, boolean toOpaque) {
- AppWindowToken atoken = findAppWindowToken(token);
- if (atoken != null) {
- atoken.appFullscreen = toOpaque;
- setWindowOpaque(token, toOpaque);
- requestTraversal();
+ synchronized (mWindowMap) {
+ AppWindowToken atoken = findAppWindowToken(token);
+ if (atoken != null) {
+ atoken.appFullscreen = toOpaque;
+ setWindowOpaqueLocked(token, toOpaque);
+ requestTraversalLocked();
+ }
}
}
public void setWindowOpaque(IBinder token, boolean isOpaque) {
+ synchronized (mWindowMap) {
+ setWindowOpaqueLocked(token, isOpaque);
+ }
+ }
+
+ public void setWindowOpaqueLocked(IBinder token, boolean isOpaque) {
AppWindowToken wtoken = findAppWindowToken(token);
if (wtoken != null) {
WindowState win = wtoken.findMainWindow();
if (win != null) {
- win.mWinAnimator.setOpaque(isOpaque);
+ win.mWinAnimator.setOpaqueLocked(isOpaque);
}
}
}
@@ -5561,17 +5615,70 @@
performEnableScreen();
}
+ private boolean checkWaitingForWindowsLocked() {
+
+ boolean haveBootMsg = false;
+ boolean haveApp = false;
+ // if the wallpaper service is disabled on the device, we're never going to have
+ // wallpaper, don't bother waiting for it
+ boolean haveWallpaper = false;
+ boolean wallpaperEnabled = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableWallpaperService)
+ && !mOnlyCore;
+ boolean haveKeyguard = true;
+ // TODO(multidisplay): Expand to all displays?
+ final WindowList windows = getDefaultWindowListLocked();
+ final int N = windows.size();
+ for (int i=0; i<N; i++) {
+ WindowState w = windows.get(i);
+ if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
+ return true;
+ }
+ if (w.isDrawnLw()) {
+ if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
+ haveBootMsg = true;
+ } else if (w.mAttrs.type == TYPE_APPLICATION) {
+ haveApp = true;
+ } else if (w.mAttrs.type == TYPE_WALLPAPER) {
+ haveWallpaper = true;
+ } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
+ haveKeyguard = mPolicy.isKeyguardDrawnLw();
+ }
+ }
+ }
+
+ if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
+ Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
+ + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
+ + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
+ + " haveKeyguard=" + haveKeyguard);
+ }
+
+ // If we are turning on the screen to show the boot message,
+ // don't do it until the boot message is actually displayed.
+ if (!mSystemBooted && !haveBootMsg) {
+ return true;
+ }
+
+ // If we are turning on the screen after the boot is completed
+ // normally, don't do so until we have the application and
+ // wallpaper.
+ if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
+ (wallpaperEnabled && !haveWallpaper))) {
+ return true;
+ }
+
+ return false;
+ }
+
public void performEnableScreen() {
synchronized(mWindowMap) {
- if (DEBUG_BOOT) {
- RuntimeException here = new RuntimeException("here");
- here.fillInStackTrace();
- Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
- + " mForceDisplayEnabled=" + mForceDisplayEnabled
- + " mShowingBootMessages=" + mShowingBootMessages
- + " mSystemBooted=" + mSystemBooted
- + " mOnlyCore=" + mOnlyCore, here);
- }
+ if (DEBUG_BOOT) Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
+ + " mForceDisplayEnabled=" + mForceDisplayEnabled
+ + " mShowingBootMessages=" + mShowingBootMessages
+ + " mSystemBooted=" + mSystemBooted
+ + " mOnlyCore=" + mOnlyCore,
+ new RuntimeException("here").fillInStackTrace());
if (mDisplayEnabled) {
return;
}
@@ -5579,94 +5686,64 @@
return;
}
- if (!mForceDisplayEnabled) {
- // Don't enable the screen until all existing windows
- // have been drawn.
- boolean haveBootMsg = false;
- boolean haveApp = false;
- // if the wallpaper service is disabled on the device, we're never going to have
- // wallpaper, don't bother waiting for it
- boolean haveWallpaper = false;
- boolean wallpaperEnabled = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_enableWallpaperService)
- && !mOnlyCore;
- boolean haveKeyguard = true;
- // TODO(multidisplay): Expand to all displays?
- final WindowList windows = getDefaultWindowListLocked();
- final int N = windows.size();
- for (int i=0; i<N; i++) {
- WindowState w = windows.get(i);
- if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
- return;
+ // Don't enable the screen until all existing windows have been drawn.
+ if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) {
+ return;
+ }
+
+ if (!mBootAnimationStopped) {
+ // Do this one time.
+ try {
+ IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
+ if (surfaceFlinger != null) {
+ //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken("android.ui.ISurfaceComposer");
+ surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
+ data, null, 0);
+ data.recycle();
}
- if (w.isDrawnLw()) {
- if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
- haveBootMsg = true;
- } else if (w.mAttrs.type == TYPE_APPLICATION) {
- haveApp = true;
- } else if (w.mAttrs.type == TYPE_WALLPAPER) {
- haveWallpaper = true;
- } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
- haveKeyguard = mPolicy.isKeyguardDrawnLw();
- }
- }
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
}
+ mBootAnimationStopped = true;
+ }
- if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
- Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
- + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
- + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
- + " haveKeyguard=" + haveKeyguard);
- }
-
- // If we are turning on the screen to show the boot message,
- // don't do it until the boot message is actually displayed.
- if (!mSystemBooted && !haveBootMsg) {
- return;
- }
-
- // If we are turning on the screen after the boot is completed
- // normally, don't do so until we have the application and
- // wallpaper.
- if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
- (wallpaperEnabled && !haveWallpaper))) {
- return;
- }
+ if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
+ if (DEBUG_BOOT) Slog.i(TAG, "performEnableScreen: Waiting for anim complete");
+ return;
}
mDisplayEnabled = true;
if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
- if (false) {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new FastPrintWriter(sw, false, 1024);
- this.dump(null, pw, null);
- pw.flush();
- Slog.i(TAG, sw.toString());
- }
- try {
- IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
- if (surfaceFlinger != null) {
- //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken("android.ui.ISurfaceComposer");
- surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
- data, null, 0);
- data.recycle();
- }
- } catch (RemoteException ex) {
- Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
- }
// Enable input dispatch.
mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
}
+ try {
+ mActivityManager.bootAnimationComplete();
+ } catch (RemoteException e) {
+ }
+
mPolicy.enableScreenAfterBoot();
// Make sure the last requested orientation has been applied.
updateRotationUnchecked(false, false);
}
+ private boolean checkBootAnimationCompleteLocked() {
+ if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) {
+ mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED);
+ mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED,
+ BOOT_ANIMATION_POLL_INTERVAL);
+ if (DEBUG_BOOT) Slog.i(TAG, "checkBootAnimationComplete: Waiting for anim complete");
+ return false;
+ }
+ if (DEBUG_BOOT) Slog.i(TAG, "checkBootAnimationComplete: Animation complete!");
+ return true;
+ }
+
public void showBootMessage(final CharSequence msg, final boolean always) {
boolean first = false;
synchronized(mWindowMap) {
@@ -5726,7 +5803,16 @@
com.android.internal.R.bool.config_windowIsRound)
&& mContext.getResources().getBoolean(
com.android.internal.R.bool.config_windowShowCircularMask)) {
- mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK));
+ mH.sendMessage(mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK));
+ }
+ }
+
+ public void showEmulatorDisplayOverlayIfNeeded() {
+ if (mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay)
+ && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false)
+ && Build.HARDWARE.contains("goldfish")) {
+ mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY));
}
}
@@ -5734,12 +5820,12 @@
synchronized(mWindowMap) {
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- ">>> OPEN TRANSACTION showDisplayMask");
+ ">>> OPEN TRANSACTION showCircularMask");
SurfaceControl.openTransaction();
try {
// TODO(multi-display): support multiple displays
if (mCircularDisplayMask == null) {
- int screenOffset = (int) mContext.getResources().getDimensionPixelSize(
+ int screenOffset = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.circular_display_mask_offset);
mCircularDisplayMask = new CircularDisplayMask(
@@ -5753,7 +5839,32 @@
} finally {
SurfaceControl.closeTransaction();
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- "<<< CLOSE TRANSACTION showDisplayMask");
+ "<<< CLOSE TRANSACTION showCircularMask");
+ }
+ }
+ }
+
+ public void showEmulatorDisplayOverlay() {
+ synchronized(mWindowMap) {
+
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+ ">>> OPEN TRANSACTION showEmulatorDisplayOverlay");
+ SurfaceControl.openTransaction();
+ try {
+ if (mEmulatorDisplayOverlay == null) {
+ mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(
+ mContext,
+ getDefaultDisplayContentLocked().getDisplay(),
+ mFxSession,
+ mPolicy.windowTypeToLayerLw(
+ WindowManager.LayoutParams.TYPE_POINTER)
+ * TYPE_LAYER_MULTIPLIER + 10);
+ }
+ mEmulatorDisplayOverlay.setVisibility(true);
+ } finally {
+ SurfaceControl.closeTransaction();
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+ "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay");
}
}
}
@@ -5851,7 +5962,7 @@
@Override
public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
int height, boolean force565) {
- if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
+ if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
"screenshotApplications()")) {
throw new SecurityException("Requires READ_FRAME_BUFFER permission");
}
@@ -5871,7 +5982,7 @@
return null;
}
- Bitmap rawss = null;
+ Bitmap bm = null;
int maxLayer = 0;
final Rect frame = new Rect();
@@ -6012,10 +6123,8 @@
// The screenshot API does not apply the current screen rotation.
rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
+
if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
- final int tmp = width;
- width = height;
- height = tmp;
rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
}
@@ -6041,9 +6150,9 @@
if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG,
"Taking screenshot while rotating");
- rawss = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
- inRotation);
- if (rawss == null) {
+ bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
+ inRotation, rot);
+ if (bm == null) {
Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
+ ") to layer " + maxLayer);
return null;
@@ -6053,17 +6162,6 @@
break;
}
- Bitmap bm = Bitmap.createBitmap(width, height, force565 ?
- Config.RGB_565 : rawss.getConfig());
- if (DEBUG_SCREENSHOT) {
- bm.eraseColor(0xFF000000);
- }
- Matrix matrix = new Matrix();
- ScreenRotationAnimation.createRotationMatrix(rot, width, height, matrix);
- Canvas canvas = new Canvas(bm);
- canvas.drawBitmap(rawss, matrix, null);
- canvas.setBitmap(null);
-
if (DEBUG_SCREENSHOT) {
// TEST IF IT's ALL BLACK
int[] buffer = new int[bm.getWidth() * bm.getHeight()];
@@ -6084,9 +6182,12 @@
}
}
- rawss.recycle();
-
- return bm;
+ // Copy the screenshot bitmap to another buffer so that the gralloc backed
+ // bitmap will not have a long lifetime. Gralloc memory can be pinned or
+ // duplicated and might have a higher cost than a skia backed buffer.
+ Bitmap ret = bm.copy(bm.getConfig(),true);
+ bm.recycle();
+ return ret;
}
/**
@@ -6341,9 +6442,12 @@
}
//TODO (multidisplay): Magnification is supported only for the default display.
- if (mAccessibilityController != null
+ // Announce rotation only if we will not animate as we already have the
+ // windows in final state. Otherwise, we make this call at the rotation end.
+ if (screenRotationAnimation == null && mAccessibilityController != null
&& displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
- mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation);
+ mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(),
+ rotation);
}
return true;
@@ -7384,7 +7488,10 @@
public static final int NEW_ANIMATOR_SCALE = 34;
- public static final int SHOW_DISPLAY_MASK = 35;
+ public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35;
+ public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36;
+
+ public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37;
@Override
public void handleMessage(Message msg) {
@@ -7780,11 +7887,16 @@
break;
}
- case SHOW_DISPLAY_MASK: {
+ case SHOW_CIRCULAR_DISPLAY_MASK: {
showCircularMask();
break;
}
+ case SHOW_EMULATOR_DISPLAY_OVERLAY: {
+ showEmulatorDisplayOverlay();
+ break;
+ }
+
case DO_ANIMATION_CALLBACK: {
try {
((IRemoteCallback)msg.obj).sendResult(null);
@@ -7865,6 +7977,17 @@
}
}
break;
+ case CHECK_IF_BOOT_ANIMATION_FINISHED: {
+ final boolean bootAnimationComplete;
+ synchronized (mWindowMap) {
+ if (DEBUG_BOOT) Slog.i(TAG, "CHECK_IF_BOOT_ANIMATION_FINISHED:");
+ bootAnimationComplete = checkBootAnimationCompleteLocked();
+ }
+ if (bootAnimationComplete) {
+ performEnableScreen();
+ }
+ }
+ break;
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG, "handleMessage: exit");
@@ -9354,6 +9477,9 @@
if (mCircularDisplayMask != null) {
mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation);
}
+ if (mEmulatorDisplayOverlay != null) {
+ mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh, mRotation);
+ }
boolean focusDisplayed = false;
@@ -10880,6 +11006,12 @@
}
pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX);
pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
+ if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE
+ || mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ pw.print(" mLastWallpaperDisplayOffsetX="); pw.print(mLastWallpaperDisplayOffsetX);
+ pw.print(" mLastWallpaperDisplayOffsetY=");
+ pw.println(mLastWallpaperDisplayOffsetY);
+ }
if (mInputMethodAnimLayerAdjustment != 0 ||
mWallpaperAnimLayerAdjustment != 0) {
pw.print(" mInputMethodAnimLayerAdjustment=");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e74de38..0baa2be 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -247,6 +247,11 @@
float mWallpaperXStep = -1;
float mWallpaperYStep = -1;
+ // If a window showing a wallpaper: a raw pixel offset to forcibly apply
+ // to its window; if a wallpaper window: not used.
+ int mWallpaperDisplayOffsetX = Integer.MIN_VALUE;
+ int mWallpaperDisplayOffsetY = Integer.MIN_VALUE;
+
// Wallpaper windows: pixels offset based on above variables.
int mXOffset;
int mYOffset;
@@ -1584,6 +1589,13 @@
pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
}
+ if (mWallpaperDisplayOffsetX != Integer.MIN_VALUE
+ || mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ pw.print(prefix); pw.print("mWallpaperDisplayOffsetX=");
+ pw.print(mWallpaperDisplayOffsetX);
+ pw.print(" mWallpaperDisplayOffsetY=");
+ pw.println(mWallpaperDisplayOffsetY);
+ }
}
String makeInputChannelName() {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 3d4be12..dd611ce 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1526,8 +1526,9 @@
}
void setWallpaperOffset(RectF shownFrame) {
- final int left = (int) shownFrame.left;
- final int top = (int) shownFrame.top;
+ final LayoutParams attrs = mWin.getAttrs();
+ final int left = ((int) shownFrame.left) - attrs.surfaceInsets.left;
+ final int top = ((int) shownFrame.top) - attrs.surfaceInsets.top;
if (mSurfaceX != left || mSurfaceY != top) {
mSurfaceX = left;
mSurfaceY = top;
@@ -1556,11 +1557,11 @@
}
}
- void setOpaque(boolean isOpaque) {
+ void setOpaqueLocked(boolean isOpaque) {
if (mSurfaceControl == null) {
return;
}
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaque");
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaqueLocked");
SurfaceControl.openTransaction();
try {
if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "isOpaque=" + isOpaque,
@@ -1568,7 +1569,7 @@
mSurfaceControl.setOpaque(isOpaque);
} finally {
SurfaceControl.closeTransaction();
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaque");
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaqueLocked");
}
}
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 1f377c7..d81cdd9 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -11,7 +11,6 @@
$(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \
$(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
$(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiCecController.cpp \
- $(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiMhlController.cpp \
$(LOCAL_REL_DIR)/com_android_server_input_InputApplicationHandle.cpp \
$(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp \
$(LOCAL_REL_DIR)/com_android_server_input_InputWindowHandle.cpp \
diff --git a/services/core/jni/com_android_server_UsbHostManager.cpp b/services/core/jni/com_android_server_UsbHostManager.cpp
index bc866d3..65a28c0 100644
--- a/services/core/jni/com_android_server_UsbHostManager.cpp
+++ b/services/core/jni/com_android_server_UsbHostManager.cpp
@@ -21,7 +21,6 @@
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/Log.h"
-#include "utils/Vector.h"
#include <usbhost/usbhost.h>
@@ -68,8 +67,6 @@
JNIEnv* env = AndroidRuntime::getJNIEnv();
jobject thiz = (jobject)client_data;
- Vector<int> interfaceValues;
- Vector<int> endpointValues;
const usb_device_descriptor* deviceDesc = usb_device_get_device_descriptor(device);
char *manufacturer = usb_device_get_manufacturer_name(device);
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 39b70a8..7b2e408 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -38,7 +38,6 @@
int register_android_server_location_FlpHardwareProvider(JNIEnv* env);
int register_android_server_connectivity_Vpn(JNIEnv* env);
int register_android_server_hdmi_HdmiCecController(JNIEnv* env);
-int register_android_server_hdmi_HdmiMhlController(JNIEnv* env);
int register_android_server_tv_TvInputHal(JNIEnv* env);
int register_android_server_PersistentDataBlockService(JNIEnv* env);
int register_android_server_fingerprint_FingerprintService(JNIEnv* env);
@@ -76,7 +75,6 @@
register_android_server_ConsumerIrService(env);
register_android_server_BatteryStatsService(env);
register_android_server_hdmi_HdmiCecController(env);
- register_android_server_hdmi_HdmiMhlController(env);
register_android_server_tv_TvInputHal(env);
register_android_server_PersistentDataBlockService(env);
register_android_server_fingerprint_FingerprintService(env);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 09584f4..8e82e2a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -44,13 +44,13 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
+import android.database.ContentObserver;
+import android.hardware.usb.UsbManager;
import android.media.AudioManager;
import android.media.IAudioService;
import android.net.ConnectivityManager;
-import android.net.Uri;
-import android.database.ContentObserver;
-import android.hardware.usb.UsbManager;
import android.net.ProxyInfo;
+import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
@@ -69,6 +69,7 @@
import android.os.UserManager;
import android.provider.Settings;
import android.security.Credentials;
+import android.security.IKeyChainService;
import android.security.KeyChain;
import android.security.KeyChain.KeyChainConnection;
import android.util.Log;
@@ -110,6 +111,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
+import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
@@ -166,12 +168,17 @@
}
private static final Set<String> SECURE_SETTINGS_WHITELIST;
+ private static final Set<String> SECURE_SETTINGS_DEVICEOWNER_WHITELIST;
private static final Set<String> GLOBAL_SETTINGS_WHITELIST;
static {
SECURE_SETTINGS_WHITELIST = new HashSet();
SECURE_SETTINGS_WHITELIST.add(Settings.Secure.DEFAULT_INPUT_METHOD);
SECURE_SETTINGS_WHITELIST.add(Settings.Secure.SKIP_FIRST_USE_HINTS);
+ SECURE_SETTINGS_DEVICEOWNER_WHITELIST = new HashSet();
+ SECURE_SETTINGS_DEVICEOWNER_WHITELIST.addAll(SECURE_SETTINGS_WHITELIST);
+ SECURE_SETTINGS_DEVICEOWNER_WHITELIST.add(Settings.Secure.LOCATION_MODE);
+
GLOBAL_SETTINGS_WHITELIST = new HashSet();
GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.ADB_ENABLED);
GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.AUTO_TIME);
@@ -2824,6 +2831,35 @@
}
}
+ @Override
+ public boolean installKeyPair(ComponentName who, byte[] privKey, byte[] cert, String alias) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ synchronized (this) {
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ }
+ final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
+ final long id = Binder.clearCallingIdentity();
+ try {
+ final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle);
+ try {
+ IKeyChainService keyChain = keyChainConnection.getService();
+ return keyChain.installKeyPair(privKey, cert, alias);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Installing certificate", e);
+ } finally {
+ keyChainConnection.close();
+ }
+ } catch (InterruptedException e) {
+ Log.w(LOG_TAG, "Interrupted while installing certificate", e);
+ Thread.currentThread().interrupt();
+ } finally {
+ Binder.restoreCallingIdentity(id);
+ }
+ return false;
+ }
+
void wipeDataLocked(int flags) {
// If the SD card is encrypted and non-removable, we have to force a wipe.
boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted();
@@ -4608,7 +4644,8 @@
@Override
public void setUserRestriction(ComponentName who, String key, boolean enabled) {
- final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
+ final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
+ final int userHandle = user.getIdentifier();
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -4619,7 +4656,7 @@
if (!isDeviceOwner && DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) {
throw new SecurityException("Profile owners cannot set user restriction " + key);
}
- boolean alreadyRestricted = mUserManager.hasUserRestriction(key, userHandle);
+ boolean alreadyRestricted = mUserManager.hasUserRestriction(key, user);
IAudioService iAudioService = null;
if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)
@@ -4645,7 +4682,7 @@
if (UserManager.DISALLOW_CONFIG_WIFI.equals(key)) {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0,
- userHandle.getIdentifier());
+ userHandle);
} else if (UserManager.DISALLOW_USB_FILE_TRANSFER.equals(key)) {
UsbManager manager =
(UsbManager) mContext.getSystemService(Context.USB_SERVICE);
@@ -4653,27 +4690,30 @@
} else if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF,
- userHandle.getIdentifier());
+ userHandle);
Settings.Secure.putStringForUser(mContext.getContentResolver(),
Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "",
- userHandle.getIdentifier());
+ userHandle);
} else if (UserManager.DISALLOW_DEBUGGING_FEATURES.equals(key)) {
- Settings.Global.putStringForUser(mContext.getContentResolver(),
- Settings.Global.ADB_ENABLED, "0", userHandle.getIdentifier());
+ // Only disable adb if changing for primary user, since it is global
+ if (userHandle == UserHandle.USER_OWNER) {
+ Settings.Global.putStringForUser(mContext.getContentResolver(),
+ Settings.Global.ADB_ENABLED, "0", userHandle);
+ }
} else if (UserManager.ENSURE_VERIFY_APPS.equals(key)) {
Settings.Global.putStringForUser(mContext.getContentResolver(),
Settings.Global.PACKAGE_VERIFIER_ENABLE, "1",
- userHandle.getIdentifier());
+ userHandle);
Settings.Global.putStringForUser(mContext.getContentResolver(),
Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, "1",
- userHandle.getIdentifier());
+ userHandle);
} else if (UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES.equals(key)) {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.INSTALL_NON_MARKET_APPS, 0,
- userHandle.getIdentifier());
+ userHandle);
}
}
- mUserManager.setUserRestriction(key, enabled, userHandle);
+ mUserManager.setUserRestriction(key, enabled, user);
} finally {
restoreCallingIdentity(id);
}
@@ -5109,11 +5149,17 @@
if (who == null) {
throw new NullPointerException("ComponentName is null");
}
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin activeAdmin =
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- if (!SECURE_SETTINGS_WHITELIST.contains(setting)) {
+ if (isDeviceOwner(activeAdmin.info.getPackageName())) {
+ if (!SECURE_SETTINGS_DEVICEOWNER_WHITELIST.contains(setting)) {
+ throw new SecurityException(String.format(
+ "Permission denial: Device owners cannot update %1$s", setting));
+ }
+ } else if (!SECURE_SETTINGS_WHITELIST.contains(setting)) {
throw new SecurityException(String.format(
- "Permission denial: profile/device owners cannot update %1$s", setting));
+ "Permission denial: Profile owners cannot update %1$s", setting));
}
long id = Binder.clearCallingIdentity();
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 2dcdcc4..92117c3 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -33,6 +33,7 @@
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.os.Binder;
+import android.os.Debug;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
index 376230b..ad38b22 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
@@ -67,7 +67,7 @@
final ModuleProperties moduleProperties;
/** The properties for the DSP module */
- private final SoundTriggerModule mModule;
+ private SoundTriggerModule mModule;
private final Object mLock = new Object();
private final Context mContext;
private final TelephonyManager mTelephonyManager;
@@ -105,7 +105,6 @@
} else {
// TODO: Figure out how to determine which module corresponds to the DSP hardware.
moduleProperties = modules.get(0);
- mModule = SoundTrigger.attachModule(moduleProperties.id, this, null);
}
}
@@ -155,10 +154,17 @@
mIsPowerSaveMode = mPowerManager.isPowerSaveMode();
}
- if (moduleProperties == null || mModule == null) {
+ if (moduleProperties == null) {
Slog.w(TAG, "Attempting startRecognition without the capability");
return STATUS_ERROR;
}
+ if (mModule == null) {
+ mModule = SoundTrigger.attachModule(moduleProperties.id, this, null);
+ if (mModule == null) {
+ Slog.w(TAG, "startRecognition cannot attach to sound trigger module");
+ return STATUS_ERROR;
+ }
+ }
if (mCurrentSoundModelHandle != INVALID_VALUE
&& !soundModel.uuid.equals(mCurrentSoundModelUuid)) {
@@ -446,6 +452,10 @@
Slog.w(TAG, "RemoteException in onError", e);
} finally {
internalClearStateLocked();
+ if (mModule != null) {
+ mModule.detach();
+ mModule = null;
+ }
}
}
diff --git a/telecomm/java/android/telecomm/AudioState.java b/telecomm/java/android/telecomm/AudioState.java
index a5fda79..314704b 100644
--- a/telecomm/java/android/telecomm/AudioState.java
+++ b/telecomm/java/android/telecomm/AudioState.java
@@ -34,7 +34,7 @@
/** Direct the audio stream through a wired headset. */
public static final int ROUTE_WIRED_HEADSET = 0x00000004;
- /** Direct the audio stream through the device's spakerphone. */
+ /** Direct the audio stream through the device's speakerphone. */
public static final int ROUTE_SPEAKER = 0x00000008;
/**
@@ -43,7 +43,10 @@
*/
public static final int ROUTE_WIRED_OR_EARPIECE = ROUTE_EARPIECE | ROUTE_WIRED_HEADSET;
- /** Bit mask of all possible audio routes. */
+ /** Bit mask of all possible audio routes.
+ *
+ * @hide
+ */
public static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
ROUTE_SPEAKER;
diff --git a/telecomm/java/android/telecomm/Call.java b/telecomm/java/android/telecomm/Call.java
index c3aa2a0..7ada9b1 100644
--- a/telecomm/java/android/telecomm/Call.java
+++ b/telecomm/java/android/telecomm/Call.java
@@ -108,7 +108,7 @@
/**
* @return The presentation requirements for the handle. See
- * {@link PropertyPresentation} for valid values.
+ * {@link TelecommManager} for valid values.
*/
public int getHandlePresentation() {
return mHandlePresentation;
@@ -123,7 +123,7 @@
/**
* @return The presentation requirements for the caller display name. See
- * {@link PropertyPresentation} for valid values.
+ * {@link TelecommManager} for valid values.
*/
public int getCallerDisplayNamePresentation() {
return mCallerDisplayNamePresentation;
@@ -482,13 +482,6 @@
}
/**
- * Notifies this {@code Call} that the phone account user interface element was touched.
- */
- public void phoneAccountClicked() {
- mInCallAdapter.phoneAccountClicked(mTelecommCallId);
- }
-
- /**
* Notifies this {@code Call} that an account has been selected and to proceed with placing
* an outgoing call.
*/
diff --git a/telecomm/java/android/telecomm/Conference.java b/telecomm/java/android/telecomm/Conference.java
index c838b48..a4f9c2c 100644
--- a/telecomm/java/android/telecomm/Conference.java
+++ b/telecomm/java/android/telecomm/Conference.java
@@ -50,22 +50,47 @@
private int mCapabilities;
private String mDisconnectMessage;
+ /**
+ * Constructs a new Conference with a mandatory {@link PhoneAccountHandle}
+ *
+ * @param phoneAccount The {@code PhoneAccountHandle} associated with the conference.
+ */
public Conference(PhoneAccountHandle phoneAccount) {
mPhoneAccount = phoneAccount;
}
- public final PhoneAccountHandle getPhoneAccount() {
+ /**
+ * Returns the {@link PhoneAccountHandle} the conference call is being placed through.
+ *
+ * @return A {@code PhoneAccountHandle} object representing the PhoneAccount of the conference.
+ */
+ public final PhoneAccountHandle getPhoneAccountHandle() {
return mPhoneAccount;
}
+ /**
+ * Returns the list of connections currently associated with the conference call.
+ *
+ * @return A list of {@code Connection} objects which represent the children of the conference.
+ */
public final List<Connection> getConnections() {
return mUnmodifiableChildConnections;
}
+ /**
+ * Gets the state of the conference call. See {@link Connection} for valid values.
+ *
+ * @return A constant representing the state the conference call is currently in.
+ */
public final int getState() {
return mState;
}
+ /**
+ * Returns the capabilities of a conference. See {@link PhoneCapabilities} for valid values.
+ *
+ * @return A bitmask of the {@code PhoneCapabilities} of the conference call.
+ */
public final int getCapabilities() {
return mCapabilities;
}
@@ -135,7 +160,9 @@
}
/**
- * Sets the capabilities of a conference.
+ * Sets the capabilities of a conference. See {@link PhoneCapabilities} for valid values.
+ *
+ * @param capabilities A bitmask of the {@code PhoneCapabilities} of the conference call.
*/
public final void setCapabilities(int capabilities) {
if (capabilities != mCapabilities) {
@@ -170,7 +197,6 @@
* Removes the specified connection as a child of this conference.
*
* @param connection The connection to remove.
- * @return True if the connection was successfully removed.
*/
public final void removeConnection(Connection connection) {
Log.d(this, "removing %s from %s", connection, mChildConnections);
@@ -183,7 +209,7 @@
}
/**
- * Tears down the conference object and any of it's current connections.
+ * Tears down the conference object and any of its current connections.
*/
public final void destroy() {
Log.d(this, "destroying conference : %s", this);
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index 6df117e..2f25dcf 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -68,13 +68,13 @@
/** @hide */
public abstract static class Listener {
public void onStateChanged(Connection c, int state) {}
- public void onHandleChanged(Connection c, Uri newHandle, int presentation) {}
+ public void onAddressChanged(Connection c, Uri newAddress, int presentation) {}
public void onCallerDisplayNameChanged(
Connection c, String callerDisplayName, int presentation) {}
public void onVideoStateChanged(Connection c, int videoState) {}
public void onDisconnected(Connection c, int cause, String message) {}
public void onPostDialWait(Connection c, String remaining) {}
- public void onRequestingRingback(Connection c, boolean ringback) {}
+ public void onRingbackRequested(Connection c, boolean ringback) {}
public void onDestroyed(Connection c) {}
public void onCallCapabilitiesChanged(Connection c, int callCapabilities) {}
public void onVideoProviderChanged(
@@ -139,7 +139,7 @@
*/
public static final int SESSION_MODIFY_REQUEST_INVALID = 3;
- private static final int MSG_SET_VIDEO_LISTENER = 1;
+ private static final int MSG_SET_VIDEO_CALLBACK = 1;
private static final int MSG_SET_CAMERA = 2;
private static final int MSG_SET_PREVIEW_SURFACE = 3;
private static final int MSG_SET_DISPLAY_SURFACE = 4;
@@ -154,7 +154,7 @@
private final VideoProvider.VideoProviderHandler
mMessageHandler = new VideoProvider.VideoProviderHandler();
private final VideoProvider.VideoProviderBinder mBinder;
- private IVideoCallback mVideoListener;
+ private IVideoCallback mVideoCallback;
/**
* Default handler used to consolidate binder method calls onto a single thread.
@@ -163,8 +163,8 @@
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MSG_SET_VIDEO_LISTENER:
- mVideoListener = IVideoCallback.Stub.asInterface((IBinder) msg.obj);
+ case MSG_SET_VIDEO_CALLBACK:
+ mVideoCallback = IVideoCallback.Stub.asInterface((IBinder) msg.obj);
break;
case MSG_SET_CAMERA:
onSetCamera((String) msg.obj);
@@ -206,9 +206,9 @@
* IVideoProvider stub implementation.
*/
private final class VideoProviderBinder extends IVideoProvider.Stub {
- public void setVideoListener(IBinder videoListenerBinder) {
+ public void setVideoCallback(IBinder videoCallbackBinder) {
mMessageHandler.obtainMessage(
- MSG_SET_VIDEO_LISTENER, videoListenerBinder).sendToTarget();
+ MSG_SET_VIDEO_CALLBACK, videoCallbackBinder).sendToTarget();
}
public void setCamera(String cameraId) {
@@ -350,9 +350,9 @@
* @param videoProfile The requested video call profile.
*/
public void receiveSessionModifyRequest(VideoProfile videoProfile) {
- if (mVideoListener != null) {
+ if (mVideoCallback != null) {
try {
- mVideoListener.receiveSessionModifyRequest(videoProfile);
+ mVideoCallback.receiveSessionModifyRequest(videoProfile);
} catch (RemoteException ignored) {
}
}
@@ -370,9 +370,9 @@
*/
public void receiveSessionModifyResponse(int status,
VideoProfile requestedProfile, VideoProfile responseProfile) {
- if (mVideoListener != null) {
+ if (mVideoCallback != null) {
try {
- mVideoListener.receiveSessionModifyResponse(
+ mVideoCallback.receiveSessionModifyResponse(
status, requestedProfile, responseProfile);
} catch (RemoteException ignored) {
}
@@ -390,9 +390,9 @@
* @param event The event.
*/
public void handleCallSessionEvent(int event) {
- if (mVideoListener != null) {
+ if (mVideoCallback != null) {
try {
- mVideoListener.handleCallSessionEvent(event);
+ mVideoCallback.handleCallSessionEvent(event);
} catch (RemoteException ignored) {
}
}
@@ -405,9 +405,9 @@
* @param height The updated peer video height.
*/
public void changePeerDimensions(int width, int height) {
- if (mVideoListener != null) {
+ if (mVideoCallback != null) {
try {
- mVideoListener.changePeerDimensions(width, height);
+ mVideoCallback.changePeerDimensions(width, height);
} catch (RemoteException ignored) {
}
}
@@ -419,9 +419,9 @@
* @param dataUsage The updated data usage.
*/
public void changeCallDataUsage(int dataUsage) {
- if (mVideoListener != null) {
+ if (mVideoCallback != null) {
try {
- mVideoListener.changeCallDataUsage(dataUsage);
+ mVideoCallback.changeCallDataUsage(dataUsage);
} catch (RemoteException ignored) {
}
}
@@ -433,9 +433,9 @@
* @param cameraCapabilities The changed camera capabilities.
*/
public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) {
- if (mVideoListener != null) {
+ if (mVideoCallback != null) {
try {
- mVideoListener.changeCameraCapabilities(cameraCapabilities);
+ mVideoCallback.changeCameraCapabilities(cameraCapabilities);
} catch (RemoteException ignored) {
}
}
@@ -464,11 +464,11 @@
private int mState = STATE_NEW;
private AudioState mAudioState;
- private Uri mHandle;
- private int mHandlePresentation;
+ private Uri mAddress;
+ private int mAddressPresentation;
private String mCallerDisplayName;
private int mCallerDisplayNamePresentation;
- private boolean mRequestingRingback = false;
+ private boolean mRingbackRequested = false;
private int mCallCapabilities;
private VideoProvider mVideoProvider;
private boolean mAudioModeIsVoip;
@@ -485,17 +485,18 @@
public Connection() {}
/**
- * @return The handle (e.g., phone number) to which this Connection is currently communicating.
+ * @return The address (e.g., phone number) to which this Connection is currently communicating.
*/
- public final Uri getHandle() {
- return mHandle;
+ public final Uri getAddress() {
+ return mAddress;
}
/**
- * @return The {@link PropertyPresentation} which controls how the handle is shown.
+ * @return The presentation requirements for the address.
+ * See {@link TelecommManager} for valid values.
*/
- public final int getHandlePresentation() {
- return mHandlePresentation;
+ public final int getAddressPresentation() {
+ return mAddressPresentation;
}
/**
@@ -506,8 +507,8 @@
}
/**
- * @return The {@link PropertyPresentation} which controls how the caller display name is
- * shown.
+ * @return The presentation requirements for the handle.
+ * See {@link TelecommManager} for valid values.
*/
public final int getCallerDisplayNamePresentation() {
return mCallerDisplayNamePresentation;
@@ -555,8 +556,8 @@
* Returns whether this connection is requesting that the system play a ringback tone
* on its behalf.
*/
- public final boolean isRequestingRingback() {
- return mRequestingRingback;
+ public final boolean isRingbackRequested() {
+ return mRingbackRequested;
}
/**
@@ -624,7 +625,7 @@
final void setAudioState(AudioState state) {
Log.d(this, "setAudioState %s", state);
mAudioState = state;
- onSetAudioState(state);
+ onAudioStateChanged(state);
}
/**
@@ -661,18 +662,18 @@
}
/**
- * Sets the value of the {@link #getHandle()} property.
+ * Sets the value of the {@link #getAddress()} property.
*
- * @param handle The new handle.
- * @param presentation The {@link PropertyPresentation} which controls how the handle is
- * shown.
+ * @param address The new address.
+ * @param presentation The presentation requirements for the address.
+ * See {@link TelecommManager} for valid values.
*/
- public final void setHandle(Uri handle, int presentation) {
- Log.d(this, "setHandle %s", handle);
- mHandle = handle;
- mHandlePresentation = presentation;
+ public final void setAddress(Uri address, int presentation) {
+ Log.d(this, "setAddress %s", address);
+ mAddress = address;
+ mAddressPresentation = presentation;
for (Listener l : mListeners) {
- l.onHandleChanged(this, handle, presentation);
+ l.onAddressChanged(this, address, presentation);
}
}
@@ -680,8 +681,8 @@
* Sets the caller display name (CNAP).
*
* @param callerDisplayName The new display name.
- * @param presentation The {@link PropertyPresentation} which controls how the name is
- * shown.
+ * @param presentation The presentation requirements for the handle.
+ * See {@link TelecommManager} for valid values.
*/
public final void setCallerDisplayName(String callerDisplayName, int presentation) {
Log.d(this, "setCallerDisplayName %s", callerDisplayName);
@@ -715,7 +716,7 @@
* communicate).
*/
public final void setActive() {
- setRequestingRingback(false);
+ setRingbackRequested(false);
setState(STATE_ACTIVE);
}
@@ -803,11 +804,11 @@
*
* @param ringback Whether the ringback tone is to be played.
*/
- public final void setRequestingRingback(boolean ringback) {
- if (mRequestingRingback != ringback) {
- mRequestingRingback = ringback;
+ public final void setRingbackRequested(boolean ringback) {
+ if (mRingbackRequested != ringback) {
+ mRingbackRequested = ringback;
for (Listener l : mListeners) {
- l.onRequestingRingback(this, ringback);
+ l.onRingbackRequested(this, ringback);
}
}
}
@@ -945,7 +946,7 @@
*
* @param state The new call audio state.
*/
- public void onSetAudioState(AudioState state) {}
+ public void onAudioStateChanged(AudioState state) {}
/**
* Notifies this Connection of an internal state change. This method is called after the
@@ -953,7 +954,7 @@
*
* @param state The new state, one of the {@code STATE_*} constants.
*/
- public void onSetState(int state) {}
+ public void onStateChanged(int state) {}
/**
* Notifies this Connection of a request to play a DTMF tone.
@@ -1021,11 +1022,6 @@
public void onPostDialContinue(boolean proceed) {}
/**
- * Called when the phone account UI was clicked.
- */
- public void onPhoneAccountClicked() {}
-
- /**
* Merge this connection and the specified connection into a conference call. Once the
* connections are merged, the calls should be added to the an existing or new
* {@code Conference} instance. For new {@code Conference} instances, use
@@ -1068,7 +1064,7 @@
if (mState != state) {
Log.d(this, "setState: %s", stateToString(state));
mState = state;
- onSetState(state);
+ onStateChanged(state);
for (Listener l : mListeners) {
l.onStateChanged(this, state);
}
diff --git a/telecomm/java/android/telecomm/ConnectionRequest.java b/telecomm/java/android/telecomm/ConnectionRequest.java
index 39ae59a..d5a6aa5 100644
--- a/telecomm/java/android/telecomm/ConnectionRequest.java
+++ b/telecomm/java/android/telecomm/ConnectionRequest.java
@@ -29,31 +29,25 @@
// TODO: Token to limit recursive invocations
private final PhoneAccountHandle mAccountHandle;
- private final Uri mHandle;
- private final int mHandlePresentation;
+ private final Uri mAddress;
private final Bundle mExtras;
private final int mVideoState;
/**
* @param accountHandle The accountHandle which should be used to place the call.
* @param handle The handle (e.g., phone number) to which the {@link Connection} is to connect.
- * @param handlePresentation The {@link PropertyPresentation} which controls how the handle
- * is shown.
* @param extras Application-specific extra data.
*/
public ConnectionRequest(
PhoneAccountHandle accountHandle,
Uri handle,
- int handlePresentation,
Bundle extras) {
- this(accountHandle, handle, handlePresentation, extras, VideoProfile.VideoState.AUDIO_ONLY);
+ this(accountHandle, handle, extras, VideoProfile.VideoState.AUDIO_ONLY);
}
/**
* @param accountHandle The accountHandle which should be used to place the call.
* @param handle The handle (e.g., phone number) to which the {@link Connection} is to connect.
- * @param handlePresentation The {@link PropertyPresentation} which controls how the handle
- * is shown.
* @param extras Application-specific extra data.
* @param videoState Determines the video state for the connection.
* @hide
@@ -61,20 +55,17 @@
public ConnectionRequest(
PhoneAccountHandle accountHandle,
Uri handle,
- int handlePresentation,
Bundle extras,
int videoState) {
mAccountHandle = accountHandle;
- mHandle = handle;
- mHandlePresentation = handlePresentation;
+ mAddress = handle;
mExtras = extras;
mVideoState = videoState;
}
private ConnectionRequest(Parcel in) {
mAccountHandle = in.readParcelable(getClass().getClassLoader());
- mHandle = in.readParcelable(getClass().getClassLoader());
- mHandlePresentation = in.readInt();
+ mAddress = in.readParcelable(getClass().getClassLoader());
mExtras = in.readParcelable(getClass().getClassLoader());
mVideoState = in.readInt();
}
@@ -87,12 +78,7 @@
/**
* The handle (e.g., phone number) to which the {@link Connection} is to connect.
*/
- public Uri getHandle() { return mHandle; }
-
- /**
- * The {@link PropertyPresentation} which controls how the handle is shown.
- */
- public int getHandlePresentation() { return mHandlePresentation; }
+ public Uri getAddress() { return mAddress; }
/**
* Application-specific extra data. Used for passing back information from an incoming
@@ -118,9 +104,9 @@
@Override
public String toString() {
return String.format("ConnectionRequest %s %s",
- mHandle == null
+ mAddress == null
? Uri.EMPTY
- : Connection.toLogSafePhoneNumber(mHandle.toString()),
+ : Connection.toLogSafePhoneNumber(mAddress.toString()),
mExtras == null ? "" : mExtras);
}
@@ -147,8 +133,7 @@
@Override
public void writeToParcel(Parcel destination, int flags) {
destination.writeParcelable(mAccountHandle, 0);
- destination.writeParcelable(mHandle, 0);
- destination.writeInt(mHandlePresentation);
+ destination.writeParcelable(mAddress, 0);
destination.writeParcelable(mExtras, 0);
destination.writeInt(mVideoState);
}
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 833aa26..036d397 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -69,7 +69,6 @@
private static final int MSG_CONFERENCE = 12;
private static final int MSG_SPLIT_FROM_CONFERENCE = 13;
private static final int MSG_ON_POST_DIAL_CONTINUE = 14;
- private static final int MSG_ON_PHONE_ACCOUNT_CLICKED = 15;
private static final int MSG_REMOVE_CONNECTION_SERVICE_ADAPTER = 16;
private static final int MSG_ANSWER_VIDEO = 17;
private static final int MSG_MERGE_CONFERENCE = 18;
@@ -200,11 +199,6 @@
args.argi1 = proceed ? 1 : 0;
mHandler.obtainMessage(MSG_ON_POST_DIAL_CONTINUE, args).sendToTarget();
}
-
- @Override
- public void onPhoneAccountClicked(String callId) {
- mHandler.obtainMessage(MSG_ON_PHONE_ACCOUNT_CLICKED, callId).sendToTarget();
- }
};
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -327,9 +321,6 @@
}
break;
}
- case MSG_ON_PHONE_ACCOUNT_CLICKED:
- onPhoneAccountHandleClicked((String) msg.obj);
- break;
default:
break;
}
@@ -423,9 +414,9 @@
}
@Override
- public void onHandleChanged(Connection c, Uri handle, int presentation) {
+ public void onAddressChanged(Connection c, Uri address, int presentation) {
String id = mIdByConnection.get(c);
- mAdapter.setHandle(id, handle, presentation);
+ mAdapter.setAddress(id, address, presentation);
}
@Override
@@ -448,10 +439,10 @@
}
@Override
- public void onRequestingRingback(Connection c, boolean ringback) {
+ public void onRingbackRequested(Connection c, boolean ringback) {
String id = mIdByConnection.get(c);
Log.d(this, "Adapter onRingback %b", ringback);
- mAdapter.setRequestingRingback(id, ringback);
+ mAdapter.setRingbackRequested(id, ringback);
}
@Override
@@ -471,7 +462,7 @@
@Override
public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {
String id = mIdByConnection.get(c);
- mAdapter.setAudioModeIsVoip(id, isVoip);
+ mAdapter.setIsVoipAudioMode(id, isVoip);
}
@Override
@@ -532,8 +523,8 @@
addConnection(callId, connection);
}
- Uri handle = connection.getHandle();
- String number = handle == null ? "null" : handle.getSchemeSpecificPart();
+ Uri address = connection.getAddress();
+ String number = address == null ? "null" : address.getSchemeSpecificPart();
Log.v(this, "createConnection, number: %s, state: %s, capabilities: %s",
Connection.toLogSafePhoneNumber(number),
Connection.stateToString(connection.getState()),
@@ -547,14 +538,14 @@
request.getAccountHandle(),
connection.getState(),
connection.getCallCapabilities(),
- connection.getHandle(),
- connection.getHandlePresentation(),
+ connection.getAddress(),
+ connection.getAddressPresentation(),
connection.getCallerDisplayName(),
connection.getCallerDisplayNamePresentation(),
connection.getVideoProvider() == null ?
null : connection.getVideoProvider().getInterface(),
connection.getVideoState(),
- connection.isRequestingRingback(),
+ connection.isRingbackRequested(),
connection.getAudioModeIsVoip(),
connection.getStatusHints(),
connection.getDisconnectCause(),
@@ -678,11 +669,6 @@
findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed);
}
- private void onPhoneAccountHandleClicked(String callId) {
- Log.d(this, "onPhoneAccountClicked %s", callId);
- findConnectionForAction(callId, "onPhoneAccountClicked").onPhoneAccountClicked();
- }
-
private void onAdapterAttached() {
if (mAreAccountsInitialized) {
// No need to query again if we already did it.
@@ -781,7 +767,7 @@
}
}
ParcelableConference parcelableConference = new ParcelableConference(
- conference.getPhoneAccount(),
+ conference.getPhoneAccountHandle(),
conference.getState(),
conference.getCapabilities(),
connectionIds);
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
index e3dc713..19f42d6 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
@@ -168,10 +168,10 @@
* @param callId The unique ID of the call whose ringback is being changed.
* @param ringback Whether Telecomm should start playing a ringback tone.
*/
- void setRequestingRingback(String callId, boolean ringback) {
+ void setRingbackRequested(String callId, boolean ringback) {
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
- adapter.setRequestingRingback(callId, ringback);
+ adapter.setRingbackRequested(callId, ringback);
} catch (RemoteException e) {
}
}
@@ -280,10 +280,10 @@
* @param callId The unique ID of the call to set with the given call video provider.
* @param isVoip True if the audio mode is VOIP.
*/
- void setAudioModeIsVoip(String callId, boolean isVoip) {
+ void setIsVoipAudioMode(String callId, boolean isVoip) {
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
- adapter.setAudioModeIsVoip(callId, isVoip);
+ adapter.setIsVoipAudioMode(callId, isVoip);
} catch (RemoteException e) {
}
}
@@ -298,10 +298,10 @@
}
}
- void setHandle(String callId, Uri handle, int presentation) {
+ void setAddress(String callId, Uri address, int presentation) {
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
- adapter.setHandle(callId, handle, presentation);
+ adapter.setAddress(callId, address, presentation);
} catch (RemoteException e) {
}
}
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
index 21e99db..2aac7fc 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
@@ -44,7 +44,7 @@
private static final int MSG_SET_DIALING = 4;
private static final int MSG_SET_DISCONNECTED = 5;
private static final int MSG_SET_ON_HOLD = 6;
- private static final int MSG_SET_REQUESTING_RINGBACK = 7;
+ private static final int MSG_SET_RINGBACK_REQUESTED = 7;
private static final int MSG_SET_CALL_CAPABILITIES = 8;
private static final int MSG_SET_IS_CONFERENCED = 9;
private static final int MSG_ADD_CONFERENCE_CALL = 10;
@@ -53,9 +53,9 @@
private static final int MSG_QUERY_REMOTE_CALL_SERVICES = 13;
private static final int MSG_SET_VIDEO_STATE = 14;
private static final int MSG_SET_VIDEO_CALL_PROVIDER = 15;
- private static final int MSG_SET_AUDIO_MODE_IS_VOIP = 16;
+ private static final int MSG_SET_IS_VOIP_AUDIO_MODE = 16;
private static final int MSG_SET_STATUS_HINTS = 17;
- private static final int MSG_SET_HANDLE = 18;
+ private static final int MSG_SET_ADDRESS = 18;
private static final int MSG_SET_CALLER_DISPLAY_NAME = 19;
private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 20;
@@ -107,8 +107,8 @@
case MSG_SET_ON_HOLD:
mDelegate.setOnHold((String) msg.obj);
break;
- case MSG_SET_REQUESTING_RINGBACK:
- mDelegate.setRequestingRingback((String) msg.obj, msg.arg1 == 1);
+ case MSG_SET_RINGBACK_REQUESTED:
+ mDelegate.setRingbackRequested((String) msg.obj, msg.arg1 == 1);
break;
case MSG_SET_CALL_CAPABILITIES:
mDelegate.setCallCapabilities((String) msg.obj, msg.arg1);
@@ -160,8 +160,8 @@
}
break;
}
- case MSG_SET_AUDIO_MODE_IS_VOIP:
- mDelegate.setAudioModeIsVoip((String) msg.obj, msg.arg1 == 1);
+ case MSG_SET_IS_VOIP_AUDIO_MODE:
+ mDelegate.setIsVoipAudioMode((String) msg.obj, msg.arg1 == 1);
break;
case MSG_SET_STATUS_HINTS: {
SomeArgs args = (SomeArgs) msg.obj;
@@ -172,10 +172,10 @@
}
break;
}
- case MSG_SET_HANDLE: {
+ case MSG_SET_ADDRESS: {
SomeArgs args = (SomeArgs) msg.obj;
try {
- mDelegate.setHandle((String) args.arg1, (Uri) args.arg2, args.argi1);
+ mDelegate.setAddress((String) args.arg1, (Uri) args.arg2, args.argi1);
} finally {
args.recycle();
}
@@ -249,8 +249,8 @@
}
@Override
- public void setRequestingRingback(String connectionId, boolean ringback) {
- mHandler.obtainMessage(MSG_SET_REQUESTING_RINGBACK, ringback ? 1 : 0, 0, connectionId)
+ public void setRingbackRequested(String connectionId, boolean ringback) {
+ mHandler.obtainMessage(MSG_SET_RINGBACK_REQUESTED, ringback ? 1 : 0, 0, connectionId)
.sendToTarget();
}
@@ -308,8 +308,8 @@
}
@Override
- public final void setAudioModeIsVoip(String connectionId, boolean isVoip) {
- mHandler.obtainMessage(MSG_SET_AUDIO_MODE_IS_VOIP, isVoip ? 1 : 0, 0,
+ public final void setIsVoipAudioMode(String connectionId, boolean isVoip) {
+ mHandler.obtainMessage(MSG_SET_IS_VOIP_AUDIO_MODE, isVoip ? 1 : 0, 0,
connectionId).sendToTarget();
}
@@ -322,12 +322,12 @@
}
@Override
- public final void setHandle(String connectionId, Uri handle, int presentation) {
+ public final void setAddress(String connectionId, Uri address, int presentation) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = connectionId;
- args.arg2 = handle;
+ args.arg2 = address;
args.argi1 = presentation;
- mHandler.obtainMessage(MSG_SET_HANDLE, args).sendToTarget();
+ mHandler.obtainMessage(MSG_SET_ADDRESS, args).sendToTarget();
}
@Override
diff --git a/telecomm/java/android/telecomm/GatewayInfo.java b/telecomm/java/android/telecomm/GatewayInfo.java
index b95e6b6..a720284 100644
--- a/telecomm/java/android/telecomm/GatewayInfo.java
+++ b/telecomm/java/android/telecomm/GatewayInfo.java
@@ -16,6 +16,7 @@
package android.telecomm;
+import android.annotation.SystemApi;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -33,14 +34,15 @@
public class GatewayInfo implements Parcelable {
private final String mGatewayProviderPackageName;
- private final Uri mGatewayHandle;
- private final Uri mOriginalHandle;
+ private final Uri mGatewayAddress;
+ private final Uri mOriginalAddress;
/** @hide */
- public GatewayInfo(String packageName, Uri gatewayUri, Uri originalHandle) {
+ @SystemApi
+ public GatewayInfo(String packageName, Uri gatewayUri, Uri originalAddress) {
mGatewayProviderPackageName = packageName;
- mGatewayHandle = gatewayUri;
- mOriginalHandle = originalHandle;
+ mGatewayAddress = gatewayUri;
+ mOriginalAddress = originalAddress;
}
/**
@@ -51,21 +53,21 @@
}
/**
- * Gateway provider handle to use when actually placing the call.
+ * Gateway provider address to use when actually placing the call.
*/
- public Uri getGatewayHandle() {
- return mGatewayHandle;
+ public Uri getGatewayAddress() {
+ return mGatewayAddress;
}
/**
- * The actual call handle that the user is trying to connect to via the gateway.
+ * The actual call address that the user is trying to connect to via the gateway.
*/
- public Uri getOriginalHandle() {
- return mOriginalHandle;
+ public Uri getOriginalAddress() {
+ return mOriginalAddress;
}
public boolean isEmpty() {
- return TextUtils.isEmpty(mGatewayProviderPackageName) || mGatewayHandle == null;
+ return TextUtils.isEmpty(mGatewayProviderPackageName) || mGatewayAddress == null;
}
/** Implement the Parcelable interface */
@@ -76,8 +78,8 @@
public GatewayInfo createFromParcel(Parcel source) {
String gatewayPackageName = source.readString();
Uri gatewayUri = Uri.CREATOR.createFromParcel(source);
- Uri originalHandle = Uri.CREATOR.createFromParcel(source);
- return new GatewayInfo(gatewayPackageName, gatewayUri, originalHandle);
+ Uri originalAddress = Uri.CREATOR.createFromParcel(source);
+ return new GatewayInfo(gatewayPackageName, gatewayUri, originalAddress);
}
@Override
@@ -100,7 +102,7 @@
@Override
public void writeToParcel(Parcel destination, int flags) {
destination.writeString(mGatewayProviderPackageName);
- mGatewayHandle.writeToParcel(destination, 0);
- mOriginalHandle.writeToParcel(destination, 0);
+ mGatewayAddress.writeToParcel(destination, 0);
+ mOriginalAddress.writeToParcel(destination, 0);
}
}
diff --git a/telecomm/java/android/telecomm/InCallAdapter.java b/telecomm/java/android/telecomm/InCallAdapter.java
index 96ea5a6..899f35e 100644
--- a/telecomm/java/android/telecomm/InCallAdapter.java
+++ b/telecomm/java/android/telecomm/InCallAdapter.java
@@ -189,18 +189,6 @@
}
/**
- * Instructs Telecomm that the phone account UI was clicked.
- *
- * @param callId The identifier of the call.
- */
- public void phoneAccountClicked(String callId) {
- try {
- mAdapter.phoneAccountClicked(callId);
- } catch (RemoteException e) {
- }
- }
-
- /**
* Instructs Telecomm to add a PhoneAccountHandle to the specified call
*
* @param callId The identifier of the call
diff --git a/telecomm/java/android/telecomm/ParcelableCall.java b/telecomm/java/android/telecomm/ParcelableCall.java
index a2aa192..f7fc125 100644
--- a/telecomm/java/android/telecomm/ParcelableCall.java
+++ b/telecomm/java/android/telecomm/ParcelableCall.java
@@ -153,7 +153,9 @@
return mHandle;
}
- /** The {@link PropertyPresentation} which controls how the handle is shown. */
+ /**
+ * The presentation requirements for the handle. See {@link TelecommManager} for valid values.
+ */
public int getHandlePresentation() {
return mHandlePresentation;
}
@@ -163,7 +165,10 @@
return mCallerDisplayName;
}
- /** The {@link PropertyPresentation} which controls how the caller display name is shown. */
+ /**
+ * The presentation requirements for the caller display name.
+ * See {@link TelecommManager} for valid values.
+ */
public int getCallerDisplayNamePresentation() {
return mCallerDisplayNamePresentation;
}
diff --git a/telecomm/java/android/telecomm/ParcelableConnection.java b/telecomm/java/android/telecomm/ParcelableConnection.java
index 2e21d37..cadcd85 100644
--- a/telecomm/java/android/telecomm/ParcelableConnection.java
+++ b/telecomm/java/android/telecomm/ParcelableConnection.java
@@ -35,14 +35,14 @@
private final PhoneAccountHandle mPhoneAccount;
private final int mState;
private final int mCapabilities;
- private final Uri mHandle;
- private final int mHandlePresentation;
+ private final Uri mAddress;
+ private final int mAddressPresentation;
private final String mCallerDisplayName;
private final int mCallerDisplayNamePresentation;
private final IVideoProvider mVideoProvider;
private final int mVideoState;
- private final boolean mRequestingRingback;
- private final boolean mAudioModeIsVoip;
+ private final boolean mRingbackRequested;
+ private final boolean mIsVoipAudioMode;
private final StatusHints mStatusHints;
private final int mDisconnectCause;
private final String mDisconnectMessage;
@@ -53,14 +53,14 @@
PhoneAccountHandle phoneAccount,
int state,
int capabilities,
- Uri handle,
- int handlePresentation,
+ Uri address,
+ int addressPresentation,
String callerDisplayName,
int callerDisplayNamePresentation,
IVideoProvider videoProvider,
int videoState,
- boolean requestingRingback,
- boolean audioModeIsVoip,
+ boolean ringbackRequested,
+ boolean isVoipAudioMode,
StatusHints statusHints,
int disconnectCause,
String disconnectMessage,
@@ -68,14 +68,14 @@
mPhoneAccount = phoneAccount;
mState = state;
mCapabilities = capabilities;
- mHandle = handle;
- mHandlePresentation = handlePresentation;
+ mAddress = address;
+ mAddressPresentation = addressPresentation;
mCallerDisplayName = callerDisplayName;
mCallerDisplayNamePresentation = callerDisplayNamePresentation;
mVideoProvider = videoProvider;
mVideoState = videoState;
- mRequestingRingback = requestingRingback;
- mAudioModeIsVoip = audioModeIsVoip;
+ mRingbackRequested = ringbackRequested;
+ mIsVoipAudioMode = isVoipAudioMode;
mStatusHints = statusHints;
mDisconnectCause = disconnectCause;
mDisconnectMessage = disconnectMessage;
@@ -96,11 +96,11 @@
}
public Uri getHandle() {
- return mHandle;
+ return mAddress;
}
public int getHandlePresentation() {
- return mHandlePresentation;
+ return mAddressPresentation;
}
public String getCallerDisplayName() {
@@ -119,12 +119,12 @@
return mVideoState;
}
- public boolean isRequestingRingback() {
- return mRequestingRingback;
+ public boolean isRingbackRequested() {
+ return mRingbackRequested;
}
- public boolean getAudioModeIsVoip() {
- return mAudioModeIsVoip;
+ public boolean getIsVoipAudioMode() {
+ return mIsVoipAudioMode;
}
public final StatusHints getStatusHints() {
@@ -164,14 +164,14 @@
PhoneAccountHandle phoneAccount = source.readParcelable(classLoader);
int state = source.readInt();
int capabilities = source.readInt();
- Uri handle = source.readParcelable(classLoader);
- int handlePresentation = source.readInt();
+ Uri address = source.readParcelable(classLoader);
+ int addressPresentation = source.readInt();
String callerDisplayName = source.readString();
int callerDisplayNamePresentation = source.readInt();
IVideoProvider videoCallProvider =
IVideoProvider.Stub.asInterface(source.readStrongBinder());
int videoState = source.readInt();
- boolean requestingRingback = source.readByte() == 1;
+ boolean ringbackRequested = source.readByte() == 1;
boolean audioModeIsVoip = source.readByte() == 1;
StatusHints statusHints = source.readParcelable(classLoader);
int disconnectCauseCode = source.readInt();
@@ -183,13 +183,13 @@
phoneAccount,
state,
capabilities,
- handle,
- handlePresentation,
+ address,
+ addressPresentation,
callerDisplayName,
callerDisplayNamePresentation,
videoCallProvider,
videoState,
- requestingRingback,
+ ringbackRequested,
audioModeIsVoip,
statusHints,
disconnectCauseCode,
@@ -215,15 +215,15 @@
destination.writeParcelable(mPhoneAccount, 0);
destination.writeInt(mState);
destination.writeInt(mCapabilities);
- destination.writeParcelable(mHandle, 0);
- destination.writeInt(mHandlePresentation);
+ destination.writeParcelable(mAddress, 0);
+ destination.writeInt(mAddressPresentation);
destination.writeString(mCallerDisplayName);
destination.writeInt(mCallerDisplayNamePresentation);
destination.writeStrongBinder(
mVideoProvider != null ? mVideoProvider.asBinder() : null);
destination.writeInt(mVideoState);
- destination.writeByte((byte) (mRequestingRingback ? 1 : 0));
- destination.writeByte((byte) (mAudioModeIsVoip ? 1 : 0));
+ destination.writeByte((byte) (mRingbackRequested ? 1 : 0));
+ destination.writeByte((byte) (mIsVoipAudioMode ? 1 : 0));
destination.writeParcelable(mStatusHints, 0);
destination.writeInt(mDisconnectCause);
destination.writeString(mDisconnectMessage);
diff --git a/telecomm/java/android/telecomm/PhoneAccount.java b/telecomm/java/android/telecomm/PhoneAccount.java
index 1d61a6e..b37c144 100644
--- a/telecomm/java/android/telecomm/PhoneAccount.java
+++ b/telecomm/java/android/telecomm/PhoneAccount.java
@@ -83,6 +83,25 @@
public static final int CAPABILITY_VIDEO_CALLING = 0x8;
/**
+ * Flag indicating that this {@code PhoneAccount} is capable of placing emergency calls.
+ * By default all PSTN {@code PhoneAccount}s are capable of placing emergency calls.
+ * <p>
+ * See {@link #getCapabilities}
+ */
+ public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 0x10;
+
+ /**
+ * Flag indicating that this {@code PhoneAccount} is always enabled and cannot be disabled by
+ * the user.
+ * This capability is reserved for important {@code PhoneAccount}s such as the emergency calling
+ * only {@code PhoneAccount}.
+ * <p>
+ * See {@link #getCapabilities}
+ * @hide
+ */
+ public static final int CAPABILITY_ALWAYS_ENABLED = 0x20;
+
+ /**
* URI scheme for telephone number URIs.
*/
public static final String SCHEME_TEL = "tel";
@@ -98,57 +117,70 @@
public static final String SCHEME_SIP = "sip";
private final PhoneAccountHandle mAccountHandle;
- private final Uri mHandle;
- private final String mSubscriptionNumber;
+ private final Uri mAddress;
+ private final Uri mSubscriptionAddress;
private final int mCapabilities;
private final int mIconResId;
private final CharSequence mLabel;
private final CharSequence mShortDescription;
private final List<String> mSupportedUriSchemes;
+ private final boolean mIsEnabled;
public static class Builder {
private PhoneAccountHandle mAccountHandle;
- private Uri mHandle;
- private String mSubscriptionNumber;
+ private Uri mAddress;
+ private Uri mSubscriptionAddress;
private int mCapabilities;
private int mIconResId;
private CharSequence mLabel;
private CharSequence mShortDescription;
private List<String> mSupportedUriSchemes = new ArrayList<String>();
+ private boolean mIsEnabled = false;
- public Builder() {}
+ public Builder(PhoneAccountHandle accountHandle, CharSequence label) {
+ this.mAccountHandle = accountHandle;
+ this.mLabel = label;
+ }
- public Builder withAccountHandle(PhoneAccountHandle value) {
- this.mAccountHandle = value;
+ /**
+ * Creates an instance of the {@link PhoneAccount.Builder} from an existing
+ * {@link PhoneAccount}.
+ *
+ * @param phoneAccount The {@link PhoneAccount} used to initialize the builder.
+ */
+ public Builder(PhoneAccount phoneAccount) {
+ mAccountHandle = phoneAccount.getAccountHandle();
+ mAddress = phoneAccount.getAddress();
+ mSubscriptionAddress = phoneAccount.getSubscriptionAddress();
+ mCapabilities = phoneAccount.getCapabilities();
+ mIconResId = phoneAccount.getIconResId();
+ mLabel = phoneAccount.getLabel();
+ mShortDescription = phoneAccount.getShortDescription();
+ mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes());
+ mIsEnabled = phoneAccount.isEnabled();
+ }
+
+ public Builder setAddress(Uri value) {
+ this.mAddress = value;
return this;
}
- public Builder withHandle(Uri value) {
- this.mHandle = value;
+ public Builder setSubscriptionAddress(Uri value) {
+ this.mSubscriptionAddress = value;
return this;
}
- public Builder withSubscriptionNumber(String value) {
- this.mSubscriptionNumber = value;
- return this;
- }
-
- public Builder withCapabilities(int value) {
+ public Builder setCapabilities(int value) {
this.mCapabilities = value;
return this;
}
- public Builder withIconResId(int value) {
+ public Builder setIconResId(int value) {
this.mIconResId = value;
return this;
}
- public Builder withLabel(CharSequence value) {
- this.mLabel = value;
- return this;
- }
-
- public Builder withShortDescription(CharSequence value) {
+ public Builder setShortDescription(CharSequence value) {
this.mShortDescription = value;
return this;
}
@@ -158,8 +190,9 @@
*
* @param uriScheme The URI scheme.
* @return The Builder.
+ * @hide
*/
- public Builder withSupportedUriScheme(String uriScheme) {
+ public Builder addSupportedUriScheme(String uriScheme) {
if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
this.mSupportedUriSchemes.add(uriScheme);
}
@@ -167,58 +200,93 @@
}
/**
- * Specifies additional URI schemes supported by the {@link PhoneAccount}.
+ * Specifies the URI schemes supported by the {@link PhoneAccount}.
*
* @param uriSchemes The URI schemes.
* @return The Builder.
*/
- public Builder withSupportedUriSchemes(List<String> uriSchemes) {
+ public Builder setSupportedUriSchemes(List<String> uriSchemes) {
+ mSupportedUriSchemes.clear();
+
if (uriSchemes != null && !uriSchemes.isEmpty()) {
for (String uriScheme : uriSchemes) {
- withSupportedUriScheme(uriScheme);
+ addSupportedUriScheme(uriScheme);
}
}
return this;
}
+ /**
+ * Specifies whether the {@link PhoneAccount} is enabled or not. {@link PhoneAccount}s are
+ * by default not enabled.
+ *
+ * @param value {@code True} if the {@link PhoneAccount} is enabled.
+ * @return The Builder.
+ * @hide
+ */
+ public Builder setEnabled(boolean value) {
+ this.mIsEnabled = value;
+ return this;
+ }
+
+ /**
+ * Creates an instance of a {@link PhoneAccount} based on the current builder settings.
+ *
+ * @return The {@link PhoneAccount}.
+ */
public PhoneAccount build() {
// If no supported URI schemes were defined, assume "tel" is supported.
if (mSupportedUriSchemes.isEmpty()) {
- withSupportedUriScheme(SCHEME_TEL);
+ addSupportedUriScheme(SCHEME_TEL);
}
return new PhoneAccount(
mAccountHandle,
- mHandle,
- mSubscriptionNumber,
+ mAddress,
+ mSubscriptionAddress,
mCapabilities,
mIconResId,
mLabel,
mShortDescription,
- mSupportedUriSchemes);
+ mSupportedUriSchemes,
+ mIsEnabled);
}
}
private PhoneAccount(
PhoneAccountHandle account,
- Uri handle,
- String subscriptionNumber,
+ Uri address,
+ Uri subscriptionAddress,
int capabilities,
int iconResId,
CharSequence label,
CharSequence shortDescription,
- List<String> supportedUriSchemes) {
+ List<String> supportedUriSchemes,
+ boolean enabled) {
mAccountHandle = account;
- mHandle = handle;
- mSubscriptionNumber = subscriptionNumber;
+ mAddress = address;
+ mSubscriptionAddress = subscriptionAddress;
mCapabilities = capabilities;
mIconResId = iconResId;
mLabel = label;
mShortDescription = shortDescription;
mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
+ mIsEnabled = enabled;
}
- public static Builder builder() { return new Builder(); }
+ public static Builder builder(
+ PhoneAccountHandle accountHandle,
+ CharSequence label) {
+ return new Builder(accountHandle, label);
+ }
+
+ /**
+ * Returns a builder initialized with the current {@link PhoneAccount} instance.
+ *
+ * @return The builder.
+ * @hide
+ */
+ public Builder toBuilder() { return new Builder(this); }
/**
* The unique identifier of this {@code PhoneAccount}.
@@ -230,32 +298,29 @@
}
/**
- * The handle (e.g., a phone number) associated with this {@code PhoneAccount}. This
+ * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This
* represents the destination from which outgoing calls using this {@code PhoneAccount}
* will appear to come, if applicable, and the destination to which incoming calls using this
* {@code PhoneAccount} may be addressed.
*
- * @return A handle expressed as a {@code Uri}, for example, a phone number.
+ * @return A address expressed as a {@code Uri}, for example, a phone number.
*/
- public Uri getHandle() {
- return mHandle;
+ public Uri getAddress() {
+ return mAddress;
}
/**
* The raw callback number used for this {@code PhoneAccount}, as distinct from
- * {@link #getHandle()}. For the majority of {@code PhoneAccount}s this should be registered
+ * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered
* as {@code null}. It is used by the system for SIM-based {@code PhoneAccount} registration
* where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)}
- * or {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(long, String, String)}
* has been used to alter the callback number.
* <p>
- * TODO: Should this also be a URI, for consistency? Should it be called the
- * "subscription handle"?
*
* @return The subscription number, suitable for display to the user.
*/
- public String getSubscriptionNumber() {
- return mSubscriptionNumber;
+ public Uri getSubscriptionAddress() {
+ return mSubscriptionAddress;
}
/**
@@ -268,6 +333,17 @@
}
/**
+ * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in
+ * bit mask.
+ *
+ * @param capability The capabilities to check.
+ * @return {@code True} if the phone account has the capability.
+ */
+ public boolean hasCapabilities(int capability) {
+ return (mCapabilities & capability) == capability;
+ }
+
+ /**
* A short label describing a {@code PhoneAccount}.
*
* @return A label for this {@code PhoneAccount}.
@@ -295,11 +371,11 @@
}
/**
- * Determines if the {@link PhoneAccount} supports calls to/from handles with a specified URI
+ * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
* scheme.
*
* @param uriScheme The URI scheme to check.
- * @return {@code True} if the {@code PhoneAccount} supports calls to/from handles with the
+ * @return {@code True} if the {@code PhoneAccount} supports calls to/from addresses with the
* specified URI scheme.
*/
public boolean supportsUriScheme(String uriScheme) {
@@ -316,6 +392,15 @@
}
/**
+ * Determines whether this {@code PhoneAccount} is enabled.
+ *
+ * @return {@code True} if this {@code PhoneAccount} is enabled..
+ */
+ public boolean isEnabled() {
+ return mIsEnabled;
+ }
+
+ /**
* The icon resource ID for the icon of this {@code PhoneAccount}.
*
* @return A resource ID.
@@ -363,13 +448,14 @@
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeParcelable(mAccountHandle, 0);
- out.writeParcelable(mHandle, 0);
- out.writeString(mSubscriptionNumber);
+ out.writeParcelable(mAddress, 0);
+ out.writeParcelable(mSubscriptionAddress, 0);
out.writeInt(mCapabilities);
out.writeInt(mIconResId);
out.writeCharSequence(mLabel);
out.writeCharSequence(mShortDescription);
out.writeList(mSupportedUriSchemes);
+ out.writeInt(mIsEnabled ? 1 : 0);
}
public static final Creator<PhoneAccount> CREATOR
@@ -389,8 +475,8 @@
ClassLoader classLoader = PhoneAccount.class.getClassLoader();
mAccountHandle = in.readParcelable(getClass().getClassLoader());
- mHandle = in.readParcelable(getClass().getClassLoader());
- mSubscriptionNumber = in.readString();
+ mAddress = in.readParcelable(getClass().getClassLoader());
+ mSubscriptionAddress = in.readParcelable(getClass().getClassLoader());
mCapabilities = in.readInt();
mIconResId = in.readInt();
mLabel = in.readCharSequence();
@@ -399,5 +485,6 @@
List<String> supportedUriSchemes = new ArrayList<>();
in.readList(supportedUriSchemes, classLoader);
mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
+ mIsEnabled = in.readInt() == 1;
}
}
diff --git a/telecomm/java/android/telecomm/PropertyPresentation.java b/telecomm/java/android/telecomm/PropertyPresentation.java
deleted file mode 100644
index fe97b3d..0000000
--- a/telecomm/java/android/telecomm/PropertyPresentation.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 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.telecomm;
-
-/**
- * Defines how properties such as phone numbers and names are displayed to the user.
- */
-public class PropertyPresentation {
- /** Property is displayed normally. */
- public static final int ALLOWED = 1;
-
- /** Property was blocked. */
- public static final int RESTRICTED = 2;
-
- /** Presentation was not specified or is unknown. */
- public static final int UNKNOWN = 3;
-
- /** Property should be displayed as a pay phone. */
- public static final int PAYPHONE = 4;
-}
diff --git a/telecomm/java/android/telecomm/RemoteConference.java b/telecomm/java/android/telecomm/RemoteConference.java
index b073827..dbff079 100644
--- a/telecomm/java/android/telecomm/RemoteConference.java
+++ b/telecomm/java/android/telecomm/RemoteConference.java
@@ -188,11 +188,11 @@
return mDisconnectMessage;
}
- public final void addCallback(Callback callback) {
+ public final void registerCallback(Callback callback) {
mCallbacks.add(callback);
}
- public final void removeCallback(Callback callback) {
+ public final void unregisterCallback(Callback callback) {
mCallbacks.remove(callback);
}
}
diff --git a/telecomm/java/android/telecomm/RemoteConnection.java b/telecomm/java/android/telecomm/RemoteConnection.java
index 31afb4b..f3a6085 100644
--- a/telecomm/java/android/telecomm/RemoteConnection.java
+++ b/telecomm/java/android/telecomm/RemoteConnection.java
@@ -17,15 +17,18 @@
package android.telecomm;
import com.android.internal.telecomm.IConnectionService;
+import com.android.internal.telecomm.IVideoCallback;
+import com.android.internal.telecomm.IVideoProvider;
import android.app.PendingIntent;
import android.net.Uri;
+import android.os.IBinder;
import android.os.RemoteException;
import android.telephony.DisconnectCause;
+import android.view.Surface;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -39,7 +42,7 @@
*/
public final class RemoteConnection {
- public static abstract class Listener {
+ public static abstract class Callback {
/**
* Invoked when the state of this {@code RemoteConnection} has changed. See
* {@link #getState()}.
@@ -50,25 +53,6 @@
public void onStateChanged(RemoteConnection connection, int state) {}
/**
- * Invoked when the parent of this {@code RemoteConnection} has changed. See
- * {@link #getParent()}.
- *
- * @param connection The {@code RemoteConnection} invoking this method.
- * @param parent The new parent of the {@code RemoteConnection}.
- */
- public void onParentChanged(RemoteConnection connection, RemoteConnection parent) {}
-
- /**
- * Invoked when the children of this {@code RemoteConnection} have changed. See
- * {@link #getChildren()}.
- *
- * @param connection The {@code RemoteConnection} invoking this method.
- * @param children The new children of the {@code RemoteConnection}.
- */
- public void onChildrenChanged(
- RemoteConnection connection, List<RemoteConnection> children) {}
-
- /**
* Invoked when this {@code RemoteConnection} is disconnected.
*
* @param connection The {@code RemoteConnection} invoking this method.
@@ -84,12 +68,12 @@
/**
* Invoked when this {@code RemoteConnection} is requesting ringback. See
- * {@link #isRequestingRingback()}.
+ * {@link #isRingbackRequested()}.
*
* @param connection The {@code RemoteConnection} invoking this method.
* @param ringback Whether the {@code RemoteConnection} is requesting ringback.
*/
- public void onRequestingRingback(RemoteConnection connection, boolean ringback) {}
+ public void onRingbackRequested(RemoteConnection connection, boolean ringback) {}
/**
* Indicates that the call capabilities of this {@code RemoteConnection} have changed.
@@ -113,12 +97,12 @@
/**
* Indicates that the VOIP audio status of this {@code RemoteConnection} has changed.
- * See {@link #getAudioModeIsVoip()}.
+ * See {@link #isVoipAudioMode()}.
*
* @param connection The {@code RemoteConnection} invoking this method.
* @param isVoip Whether the new audio state of the {@code RemoteConnection} is VOIP.
*/
- public void onAudioModeIsVoipChanged(RemoteConnection connection, boolean isVoip) {}
+ public void onVoipAudioChanged(RemoteConnection connection, boolean isVoip) {}
/**
* Indicates that the status hints of this {@code RemoteConnection} have changed. See
@@ -130,15 +114,15 @@
public void onStatusHintsChanged(RemoteConnection connection, StatusHints statusHints) {}
/**
- * Indicates that the handle (e.g., phone number) of this {@code RemoteConnection} has
- * changed. See {@link #getHandle()} and {@link #getHandlePresentation()}.
+ * Indicates that the address (e.g., phone number) of this {@code RemoteConnection} has
+ * changed. See {@link #getAddress()} and {@link #getAddressPresentation()}.
*
* @param connection The {@code RemoteConnection} invoking this method.
- * @param handle The new handle of the {@code RemoteConnection}.
- * @param presentation The {@link PropertyPresentation} which controls how the
- * handle is shown.
+ * @param address The new address of the {@code RemoteConnection}.
+ * @param presentation The presentation requirements for the address.
+ * See {@link TelecommManager} for valid values.
*/
- public void onHandleChanged(RemoteConnection connection, Uri handle, int presentation) {}
+ public void onAddressChanged(RemoteConnection connection, Uri address, int presentation) {}
/**
* Indicates that the caller display name of this {@code RemoteConnection} has changed.
@@ -146,8 +130,8 @@
*
* @param connection The {@code RemoteConnection} invoking this method.
* @param callerDisplayName The new caller display name of the {@code RemoteConnection}.
- * @param presentation The {@link PropertyPresentation} which controls how the
- * caller display name is shown.
+ * @param presentation The presentation requirements for the handle.
+ * See {@link TelecommManager} for valid values.
*/
public void onCallerDisplayNameChanged(
RemoteConnection connection, String callerDisplayName, int presentation) {}
@@ -183,6 +167,18 @@
List<RemoteConnection> conferenceableConnections) {}
/**
+ * Indicates that the {@code VideoProvider} associated with this {@code RemoteConnection}
+ * has changed.
+ *
+ * @param connection The {@code RemoteConnection} invoking this method.
+ * @param videoProvider The new {@code VideoProvider} associated with this
+ * {@code RemoteConnection}.
+ * @hide
+ */
+ public void onVideoProviderChanged(
+ RemoteConnection connection, VideoProvider videoProvider) {}
+
+ /**
* Indicates that the {@code RemoteConference} that this {@code RemoteConnection} is a part
* of has changed.
*
@@ -195,6 +191,185 @@
RemoteConference conference) {}
}
+ /** {@hide} */
+ public static class VideoProvider {
+
+ public abstract static class Listener {
+ public void onReceiveSessionModifyRequest(
+ VideoProvider videoProvider,
+ VideoProfile videoProfile) {}
+
+ public void onReceiveSessionModifyResponse(
+ VideoProvider videoProvider,
+ int status,
+ VideoProfile requestedProfile,
+ VideoProfile responseProfile) {}
+
+ public void onHandleCallSessionEvent(VideoProvider videoProvider, int event) {}
+
+ public void onPeerDimensionsChanged(VideoProvider videoProvider, int width, int height) {}
+
+ public void onCallDataUsageChanged(VideoProvider videoProvider, int dataUsage) {}
+
+ public void onCameraCapabilitiesChanged(
+ VideoProvider videoProvider,
+ CameraCapabilities cameraCapabilities) {}
+ }
+
+ private final IVideoCallback mVideoCallbackDelegate = new IVideoCallback() {
+ @Override
+ public void receiveSessionModifyRequest(VideoProfile videoProfile) {
+ for (Listener l : mListeners) {
+ l.onReceiveSessionModifyRequest(VideoProvider.this, videoProfile);
+ }
+ }
+
+ @Override
+ public void receiveSessionModifyResponse(int status, VideoProfile requestedProfile,
+ VideoProfile responseProfile) {
+ for (Listener l : mListeners) {
+ l.onReceiveSessionModifyResponse(
+ VideoProvider.this,
+ status,
+ requestedProfile,
+ responseProfile);
+ }
+ }
+
+ @Override
+ public void handleCallSessionEvent(int event) {
+ for (Listener l : mListeners) {
+ l.onHandleCallSessionEvent(VideoProvider.this, event);
+ }
+ }
+
+ @Override
+ public void changePeerDimensions(int width, int height) {
+ for (Listener l : mListeners) {
+ l.onPeerDimensionsChanged(VideoProvider.this, width, height);
+ }
+ }
+
+ @Override
+ public void changeCallDataUsage(int dataUsage) {
+ for (Listener l : mListeners) {
+ l.onCallDataUsageChanged(VideoProvider.this, dataUsage);
+ }
+ }
+
+ @Override
+ public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) {
+ for (Listener l : mListeners) {
+ l.onCameraCapabilitiesChanged(VideoProvider.this, cameraCapabilities);
+ }
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return null;
+ }
+ };
+
+ private final VideoCallbackServant mVideoCallbackServant =
+ new VideoCallbackServant(mVideoCallbackDelegate);
+
+ private final IVideoProvider mVideoProviderBinder;
+
+ /**
+ * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
+ * load factor before resizing, 1 means we only expect a single thread to
+ * access the map so make only a single shard
+ */
+ private final Set<Listener> mListeners = Collections.newSetFromMap(
+ new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1));
+
+ public VideoProvider(IVideoProvider videoProviderBinder) {
+ mVideoProviderBinder = videoProviderBinder;
+ try {
+ mVideoProviderBinder.setVideoCallback(mVideoCallbackServant.getStub().asBinder());
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void addListener(Listener l) {
+ mListeners.add(l);
+ }
+
+ public void removeListener(Listener l) {
+ mListeners.remove(l);
+ }
+
+ public void setCamera(String cameraId) {
+ try {
+ mVideoProviderBinder.setCamera(cameraId);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void setPreviewSurface(Surface surface) {
+ try {
+ mVideoProviderBinder.setPreviewSurface(surface);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void setDisplaySurface(Surface surface) {
+ try {
+ mVideoProviderBinder.setDisplaySurface(surface);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void setDeviceOrientation(int rotation) {
+ try {
+ mVideoProviderBinder.setDeviceOrientation(rotation);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void setZoom(float value) {
+ try {
+ mVideoProviderBinder.setZoom(value);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void sendSessionModifyRequest(VideoProfile reqProfile) {
+ try {
+ mVideoProviderBinder.sendSessionModifyRequest(reqProfile);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void sendSessionModifyResponse(VideoProfile responseProfile) {
+ try {
+ mVideoProviderBinder.sendSessionModifyResponse(responseProfile);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void requestCameraCapabilities() {
+ try {
+ mVideoProviderBinder.requestCameraCapabilities();
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void requestCallDataUsage() {
+ try {
+ mVideoProviderBinder.requestCallDataUsage();
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void setPauseImage(String uri) {
+ try {
+ mVideoProviderBinder.setPauseImage(uri);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
private IConnectionService mConnectionService;
private final String mConnectionId;
/**
@@ -202,8 +377,8 @@
* load factor before resizing, 1 means we only expect a single thread to
* access the map so make only a single shard
*/
- private final Set<Listener> mListeners = Collections.newSetFromMap(
- new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1));
+ private final Set<Callback> mCallbacks = Collections.newSetFromMap(
+ new ConcurrentHashMap<Callback, Boolean>(8, 0.9f, 1));
private final List<RemoteConnection> mConferenceableConnections = new ArrayList<>();
private final List<RemoteConnection> mUnmodifiableconferenceableConnections =
Collections.unmodifiableList(mConferenceableConnections);
@@ -211,14 +386,15 @@
private int mState = Connection.STATE_NEW;
private int mDisconnectCauseCode = DisconnectCause.NOT_VALID;
private String mDisconnectCauseMessage;
- private boolean mRequestingRingback;
+ private boolean mRingbackRequested;
private boolean mConnected;
private int mCallCapabilities;
private int mVideoState;
- private boolean mAudioModeIsVoip;
+ private VideoProvider mVideoProvider;
+ private boolean mIsVoipAudioMode;
private StatusHints mStatusHints;
- private Uri mHandle;
- private int mHandlePresentation;
+ private Uri mAddress;
+ private int mAddressPresentation;
private String mCallerDisplayName;
private int mCallerDisplayNamePresentation;
private int mFailureCode;
@@ -255,42 +431,26 @@
}
/**
- * Adds a listener to this {@code RemoteConnection}.
+ * Adds a callback to this {@code RemoteConnection}.
*
- * @param listener A {@code Listener}.
+ * @param callback A {@code Callback}.
*/
- public void addListener(Listener listener) {
- mListeners.add(listener);
+ public void registerCallback(Callback callback) {
+ mCallbacks.add(callback);
}
/**
- * Removes a listener from this {@code RemoteConnection}.
+ * Removes a callback from this {@code RemoteConnection}.
*
- * @param listener A {@code Listener}.
+ * @param callback A {@code Callback}.
*/
- public void removeListener(Listener listener) {
- if (listener != null) {
- mListeners.remove(listener);
+ public void unregisterCallback(Callback callback) {
+ if (callback != null) {
+ mCallbacks.remove(callback);
}
}
/**
- * Obtains the parent of this {@code RemoteConnection} in a conference, if any.
- *
- * @return The parent {@code RemoteConnection}, or {@code null} if this {@code RemoteConnection}
- * is not a child of any conference {@code RemoteConnection}s.
- */
- public RemoteConnection getParent() { return null; }
-
- /**
- * Obtains the children of this conference {@code RemoteConnection}, if any.
- *
- * @return The children of this {@code RemoteConnection} if this {@code RemoteConnection} is
- * a conference, or an empty {@code List} otherwise.
- */
- public List<RemoteConnection> getChildren() { return new ArrayList<>(); }
-
- /**
* Obtains the state of this {@code RemoteConnection}.
*
* @return A state value, chosen from the {@code STATE_*} constants.
@@ -327,8 +487,8 @@
/**
* @return {@code true} if the {@code RemoteConnection}'s current audio mode is VOIP.
*/
- public boolean getAudioModeIsVoip() {
- return mAudioModeIsVoip;
+ public boolean isVoipAudioMode() {
+ return mIsVoipAudioMode;
}
/**
@@ -340,31 +500,31 @@
}
/**
- * @return The handle (e.g., phone number) to which the {@code RemoteConnection} is currently
+ * @return The address (e.g., phone number) to which the {@code RemoteConnection} is currently
* connected.
*/
- public Uri getHandle() {
- return mHandle;
+ public Uri getAddress() {
+ return mAddress;
}
/**
- * @return The presentation requirements for the handle. See
- * {@link PropertyPresentation} for valid values.
+ * @return The presentation requirements for the address. See {@link TelecommManager} for valid
+ * values.
*/
- public int getHandlePresentation() {
- return mHandlePresentation;
+ public int getAddressPresentation() {
+ return mAddressPresentation;
}
/**
* @return The display name for the caller.
*/
- public String getCallerDisplayName() {
+ public CharSequence getCallerDisplayName() {
return mCallerDisplayName;
}
/**
* @return The presentation requirements for the caller display name. See
- * {@link PropertyPresentation} for valid values.
+ * {@link TelecommManager} for valid values.
*/
public int getCallerDisplayNamePresentation() {
return mCallerDisplayNamePresentation;
@@ -380,6 +540,14 @@
}
/**
+ * @return The video provider associated with this {@code RemoteConnection}.
+ * @hide
+ */
+ public final VideoProvider getVideoProvider() {
+ return mVideoProvider;
+ }
+
+ /**
* @return The failure code ({@see DisconnectCause}) associated with this failed
* {@code RemoteConnection}.
*/
@@ -398,7 +566,7 @@
* @return Whether the {@code RemoteConnection} is requesting that the framework play a
* ringback tone on its behalf.
*/
- public boolean isRequestingRingback() {
+ public boolean isRingbackRequested() {
return false;
}
@@ -535,8 +703,8 @@
* of time.
*
* If the DTMF string contains a {@link TelecommManager#DTMF_CHARACTER_WAIT} symbol, this
- * {@code RemoteConnection} will pause playing the tones and notify listeners via
- * {@link Listener#onPostDialWait(RemoteConnection, String)}. At this point, the in-call app
+ * {@code RemoteConnection} will pause playing the tones and notify callbackss via
+ * {@link Callback#onPostDialWait(RemoteConnection, String)}. At this point, the in-call app
* should display to the user an indication of this state and an affordance to continue
* the postdial sequence. When the user decides to continue the postdial sequence, the in-call
* app should invoke the {@link #postDialContinue(boolean)} method.
@@ -603,8 +771,8 @@
void setState(int state) {
if (mState != state) {
mState = state;
- for (Listener l: mListeners) {
- l.onStateChanged(this, state);
+ for (Callback c: mCallbacks) {
+ c.onStateChanged(this, state);
}
}
}
@@ -618,8 +786,8 @@
mDisconnectCauseCode = cause;
mDisconnectCauseMessage = message;
- for (Listener l : mListeners) {
- l.onDisconnected(this, cause, message);
+ for (Callback c : mCallbacks) {
+ c.onDisconnected(this, cause, message);
}
}
}
@@ -627,11 +795,11 @@
/**
* @hide
*/
- void setRequestingRingback(boolean ringback) {
- if (mRequestingRingback != ringback) {
- mRequestingRingback = ringback;
- for (Listener l : mListeners) {
- l.onRequestingRingback(this, ringback);
+ void setRingbackRequested(boolean ringback) {
+ if (mRingbackRequested != ringback) {
+ mRingbackRequested = ringback;
+ for (Callback c : mCallbacks) {
+ c.onRingbackRequested(this, ringback);
}
}
}
@@ -641,8 +809,8 @@
*/
void setCallCapabilities(int callCapabilities) {
mCallCapabilities = callCapabilities;
- for (Listener l : mListeners) {
- l.onCallCapabilitiesChanged(this, callCapabilities);
+ for (Callback c : mCallbacks) {
+ c.onCallCapabilitiesChanged(this, callCapabilities);
}
}
@@ -650,16 +818,16 @@
* @hide
*/
void setDestroyed() {
- if (!mListeners.isEmpty()) {
- // Make sure that the listeners are notified that the call is destroyed first.
+ if (!mCallbacks.isEmpty()) {
+ // Make sure that the callbacks are notified that the call is destroyed first.
if (mState != Connection.STATE_DISCONNECTED) {
setDisconnected(DisconnectCause.ERROR_UNSPECIFIED, "Connection destroyed.");
}
- for (Listener l : mListeners) {
- l.onDestroyed(this);
+ for (Callback c : mCallbacks) {
+ c.onDestroyed(this);
}
- mListeners.clear();
+ mCallbacks.clear();
mConnected = false;
}
@@ -669,8 +837,8 @@
* @hide
*/
void setPostDialWait(String remainingDigits) {
- for (Listener l : mListeners) {
- l.onPostDialWait(this, remainingDigits);
+ for (Callback c : mCallbacks) {
+ c.onPostDialWait(this, remainingDigits);
}
}
@@ -679,33 +847,43 @@
*/
void setVideoState(int videoState) {
mVideoState = videoState;
- for (Listener l : mListeners) {
- l.onVideoStateChanged(this, videoState);
+ for (Callback c : mCallbacks) {
+ c.onVideoStateChanged(this, videoState);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ void setVideoProvider(VideoProvider videoProvider) {
+ mVideoProvider = videoProvider;
+ for (Callback c : mCallbacks) {
+ c.onVideoProviderChanged(this, videoProvider);
}
}
/** @hide */
- void setAudioModeIsVoip(boolean isVoip) {
- mAudioModeIsVoip = isVoip;
- for (Listener l : mListeners) {
- l.onAudioModeIsVoipChanged(this, isVoip);
+ void setIsVoipAudioMode(boolean isVoip) {
+ mIsVoipAudioMode = isVoip;
+ for (Callback c : mCallbacks) {
+ c.onVoipAudioChanged(this, isVoip);
}
}
/** @hide */
void setStatusHints(StatusHints statusHints) {
mStatusHints = statusHints;
- for (Listener l : mListeners) {
- l.onStatusHintsChanged(this, statusHints);
+ for (Callback c : mCallbacks) {
+ c.onStatusHintsChanged(this, statusHints);
}
}
/** @hide */
- void setHandle(Uri handle, int presentation) {
- mHandle = handle;
- mHandlePresentation = presentation;
- for (Listener l : mListeners) {
- l.onHandleChanged(this, handle, presentation);
+ void setAddress(Uri address, int presentation) {
+ mAddress = address;
+ mAddressPresentation = presentation;
+ for (Callback c : mCallbacks) {
+ c.onAddressChanged(this, address, presentation);
}
}
@@ -713,8 +891,8 @@
void setCallerDisplayName(String callerDisplayName, int presentation) {
mCallerDisplayName = callerDisplayName;
mCallerDisplayNamePresentation = presentation;
- for (Listener l : mListeners) {
- l.onCallerDisplayNameChanged(this, callerDisplayName, presentation);
+ for (Callback c : mCallbacks) {
+ c.onCallerDisplayNameChanged(this, callerDisplayName, presentation);
}
}
@@ -722,8 +900,8 @@
void setConferenceableConnections(List<RemoteConnection> conferenceableConnections) {
mConferenceableConnections.clear();
mConferenceableConnections.addAll(conferenceableConnections);
- for (Listener l : mListeners) {
- l.onConferenceableConnectionsChanged(this, mUnmodifiableconferenceableConnections);
+ for (Callback c : mCallbacks) {
+ c.onConferenceableConnectionsChanged(this, mUnmodifiableconferenceableConnections);
}
}
@@ -731,8 +909,8 @@
void setConference(RemoteConference conference) {
if (mConference != conference) {
mConference = conference;
- for (Listener l : mListeners) {
- l.onConferenceChanged(this, conference);
+ for (Callback c : mCallbacks) {
+ c.onConferenceChanged(this, conference);
}
}
}
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index 79193c2..d4dd9af 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -60,13 +60,14 @@
if (connection != NULL_CONNECTION && mPendingConnections.contains(connection)) {
mPendingConnections.remove(connection);
// Unconditionally initialize the connection ...
- connection.setState(parcel.getState());
connection.setCallCapabilities(parcel.getCapabilities());
- connection.setHandle(
+ connection.setAddress(
parcel.getHandle(), parcel.getHandlePresentation());
connection.setCallerDisplayName(
parcel.getCallerDisplayName(),
parcel.getCallerDisplayNamePresentation());
+ // Set state after handle so that the client can identify the connection.
+ connection.setState(parcel.getState());
List<RemoteConnection> conferenceable = new ArrayList<>();
for (String confId : parcel.getConferenceableConnectionIds()) {
if (mConnectionById.containsKey(confId)) {
@@ -74,7 +75,7 @@
}
}
connection.setConferenceableConnections(conferenceable);
- // TODO: Do we need to support video providers for remote connections?
+ connection.setVideoState(parcel.getVideoState());
if (connection.getState() == Connection.STATE_DISCONNECTED) {
// ... then, if it was created in a disconnected state, that indicates
// failure on the providing end, so immediately mark it destroyed
@@ -130,9 +131,9 @@
}
@Override
- public void setRequestingRingback(String callId, boolean ringing) {
- findConnectionForAction(callId, "setRequestingRingback")
- .setRequestingRingback(ringing);
+ public void setRingbackRequested(String callId, boolean ringing) {
+ findConnectionForAction(callId, "setRingbackRequested")
+ .setRingbackRequested(ringing);
}
@Override
@@ -191,7 +192,7 @@
conference.setState(parcel.getState());
conference.setCallCapabilities(parcel.getCapabilities());
mConferenceById.put(callId, conference);
- conference.addCallback(new RemoteConference.Callback() {
+ conference.registerCallback(new RemoteConference.Callback() {
@Override
public void onDestroyed(RemoteConference c) {
mConferenceById.remove(callId);
@@ -226,7 +227,8 @@
@Override
public void setVideoProvider(String callId, IVideoProvider videoProvider) {
- // not supported for remote connections.
+ findConnectionForAction(callId, "setVideoProvider")
+ .setVideoProvider(new RemoteConnection.VideoProvider(videoProvider));
}
@Override
@@ -236,9 +238,9 @@
}
@Override
- public void setAudioModeIsVoip(String callId, boolean isVoip) {
- findConnectionForAction(callId, "setAudioModeIsVoip")
- .setAudioModeIsVoip(isVoip);
+ public void setIsVoipAudioMode(String callId, boolean isVoip) {
+ findConnectionForAction(callId, "setIsVoipAudioMode")
+ .setIsVoipAudioMode(isVoip);
}
@Override
@@ -248,9 +250,9 @@
}
@Override
- public void setHandle(String callId, Uri handle, int presentation) {
- findConnectionForAction(callId, "setHandle")
- .setHandle(handle, presentation);
+ public void setAddress(String callId, Uri address, int presentation) {
+ findConnectionForAction(callId, "setAddress")
+ .setAddress(address, presentation);
}
@Override
@@ -325,8 +327,7 @@
final String id = UUID.randomUUID().toString();
final ConnectionRequest newRequest = new ConnectionRequest(
request.getAccountHandle(),
- request.getHandle(),
- request.getHandlePresentation(),
+ request.getAddress(),
request.getExtras(),
request.getVideoState());
try {
@@ -342,7 +343,7 @@
id,
newRequest,
isIncoming);
- connection.addListener(new RemoteConnection.Listener() {
+ connection.registerCallback(new RemoteConnection.Callback() {
@Override
public void onDestroyed(RemoteConnection connection) {
mConnectionById.remove(id);
diff --git a/telecomm/java/android/telecomm/Response.java b/telecomm/java/android/telecomm/Response.java
index f879756..ad78ebd 100644
--- a/telecomm/java/android/telecomm/Response.java
+++ b/telecomm/java/android/telecomm/Response.java
@@ -17,10 +17,7 @@
package android.telecomm;
/**
- * <strong>OBSOLETE</strong> Used to inform a client of asynchronously returned results.
- * <p>
- * <strong>TODO:</strong> Remove onCreateConferenceConnection() async method
- * then delete this interface.
+ * @hide
*/
public interface Response<IN, OUT> {
diff --git a/telecomm/java/android/telecomm/StatusHints.java b/telecomm/java/android/telecomm/StatusHints.java
index f7c4f2f..ff96a5b 100644
--- a/telecomm/java/android/telecomm/StatusHints.java
+++ b/telecomm/java/android/telecomm/StatusHints.java
@@ -32,23 +32,24 @@
*/
public final class StatusHints implements Parcelable {
- private final ComponentName mComponentName;
+ private final ComponentName mPackageName;
private final CharSequence mLabel;
private final int mIconResId;
private final Bundle mExtras;
- public StatusHints(ComponentName componentName, CharSequence label, int iconResId, Bundle extras) {
- mComponentName = componentName;
+ public StatusHints(ComponentName packageName, CharSequence label, int iconResId,
+ Bundle extras) {
+ mPackageName = packageName;
mLabel = label;
mIconResId = iconResId;
mExtras = extras;
}
/**
- * @return A component used to load the icon.
+ * @return A package used to load the icon.
*/
- public ComponentName getComponentName() {
- return mComponentName;
+ public ComponentName getPackageName() {
+ return mPackageName;
}
/**
@@ -88,7 +89,7 @@
@Override
public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(mComponentName, flags);
+ out.writeParcelable(mPackageName, flags);
out.writeCharSequence(mLabel);
out.writeInt(mIconResId);
out.writeParcelable(mExtras, 0);
@@ -106,7 +107,7 @@
};
private StatusHints(Parcel in) {
- mComponentName = in.readParcelable(getClass().getClassLoader());
+ mPackageName = in.readParcelable(getClass().getClassLoader());
mLabel = in.readCharSequence();
mIconResId = in.readInt();
mExtras = in.readParcelable(getClass().getClassLoader());
@@ -115,16 +116,16 @@
private Drawable getIcon(Context context, int resId) {
Context packageContext;
try {
- packageContext = context.createPackageContext(mComponentName.getPackageName(), 0);
+ packageContext = context.createPackageContext(mPackageName.getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
- Log.e(this, e, "Cannot find package %s", mComponentName.getPackageName());
+ Log.e(this, e, "Cannot find package %s", mPackageName.getPackageName());
return null;
}
try {
return packageContext.getDrawable(resId);
} catch (MissingResourceException e) {
Log.e(this, e, "Cannot find icon %d in package %s",
- resId, mComponentName.getPackageName());
+ resId, mPackageName.getPackageName());
return null;
}
}
@@ -133,7 +134,7 @@
public boolean equals(Object other) {
if (other != null && other instanceof StatusHints) {
StatusHints otherHints = (StatusHints) other;
- return Objects.equals(otherHints.getComponentName(), getComponentName()) &&
+ return Objects.equals(otherHints.getPackageName(), getPackageName()) &&
Objects.equals(otherHints.getLabel(), getLabel()) &&
otherHints.getIconResId() == getIconResId() &&
Objects.equals(otherHints.getExtras(), getExtras());
@@ -143,7 +144,7 @@
@Override
public int hashCode() {
- return Objects.hashCode(mComponentName) + Objects.hashCode(mLabel) + mIconResId +
+ return Objects.hashCode(mPackageName) + Objects.hashCode(mLabel) + mIconResId +
Objects.hashCode(mExtras);
}
}
diff --git a/telecomm/java/android/telecomm/TelecommManager.java b/telecomm/java/android/telecomm/TelecommManager.java
index 5e9e6d0..a19f51b 100644
--- a/telecomm/java/android/telecomm/TelecommManager.java
+++ b/telecomm/java/android/telecomm/TelecommManager.java
@@ -25,6 +25,7 @@
import com.android.internal.telecomm.ITelecommService;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -141,6 +142,30 @@
"android.telecomm.extra.CONNECTION_SERVICE";
/**
+ * An optional {@link android.content.Intent#ACTION_CALL} intent extra denoting the
+ * package name of the app specifying an alternative gateway for the call.
+ * The value is a string.
+ *
+ * (The following comment corresponds to the all GATEWAY_* extras)
+ * An app which sends the {@link android.content.Intent#ACTION_CALL} intent can specify an
+ * alternative address to dial which is different from the one specified and displayed to
+ * the user. This alternative address is referred to as the gateway address.
+ */
+ public static final String GATEWAY_PROVIDER_PACKAGE =
+ "android.telecomm.extra.GATEWAY_PROVIDER_PACKAGE";
+
+ /**
+ * An optional {@link android.content.Intent#ACTION_CALL} intent extra corresponding to the
+ * original address to dial for the call. This is used when an alternative gateway address is
+ * provided to recall the original address.
+ * The value is a {@link android.net.Uri}.
+ *
+ * (See {@link #GATEWAY_PROVIDER_PACKAGE} for details)
+ */
+ public static final String GATEWAY_ORIGINAL_ADDRESS =
+ "android.telecomm.extra.GATEWAY_ORIGINAL_ADDRESS";
+
+ /**
* The number which the party on the other side of the line will see (and use to return the
* call).
* <p>
@@ -238,6 +263,23 @@
public static final String EXTRA_TTY_PREFERRED_MODE =
"android.telecomm.intent.extra.TTY_PREFERRED";
+ /**
+ * The following 4 constants define how properties such as phone numbers and names are
+ * displayed to the user.
+ */
+
+ /** Property is displayed normally. */
+ public static final int PRESENTATION_ALLOWED = 1;
+
+ /** Property was blocked. */
+ public static final int PRESENTATION_RESTRICTED = 2;
+
+ /** Presentation was not specified or is unknown. */
+ public static final int PRESENTATION_UNKNOWN = 3;
+
+ /** Property should be displayed as a pay phone. */
+ public static final int PRESENTATION_PAYPHONE = 4;
+
private static final String TAG = "TelecommManager";
private static final String TELECOMM_SERVICE_NAME = "telecomm";
@@ -270,7 +312,7 @@
* <p>
* Apps must be prepared for this method to return {@code null}, indicating that there currently
* exists no user-chosen default {@code PhoneAccount}. In this case, apps wishing to initiate a
- * phone call must either create their {@link android.content .Intent#ACTION_CALL} or
+ * phone call must either create their {@link android.content.Intent#ACTION_CALL} or
* {@link android.content.Intent#ACTION_DIAL} {@code Intent} with no
* {@link TelecommManager#EXTRA_PHONE_ACCOUNT_HANDLE}, or present the user with an affordance to
* select one of the elements of {@link #getEnabledPhoneAccounts()}.
@@ -330,8 +372,8 @@
}
/**
- * Return a list of {@link PhoneAccountHandle}s which can be used to make and receive phone
- * calls.
+ * Return a list of enabled {@link PhoneAccountHandle}s which can be used to make and receive
+ * phone calls.
*
* @see #EXTRA_PHONE_ACCOUNT_HANDLE
* @return A list of {@code PhoneAccountHandle} objects.
@@ -339,10 +381,10 @@
public List<PhoneAccountHandle> getEnabledPhoneAccounts() {
try {
if (isServiceConnected()) {
- return getTelecommService().getOutgoingPhoneAccounts();
+ return getTelecommService().getEnabledPhoneAccounts();
}
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelecommService#getOutgoingPhoneAccounts", e);
+ Log.e(TAG, "Error calling ITelecommService#getEnabledPhoneAccounts", e);
}
return new ArrayList<>();
}
@@ -408,8 +450,8 @@
}
/**
- * Returns a list of {@link PhoneAccountHandle}s which can be used to make and receive phone
- * calls which support the specified URI scheme.
+ * Returns a list of the enabled {@link PhoneAccountHandle}s which can be used to make and
+ * receive phone calls which support the specified URI scheme.
* <P>
* For example, invoking with {@code "tel"} will find all {@link PhoneAccountHandle}s which
* support telephone calls (e.g. URIs such as {@code tel:555-555-1212}). Invoking with
@@ -459,6 +501,78 @@
}
/**
+ * Returns a count of enabled and disabled {@link PhoneAccount}s.
+ *
+ * @return The count of enabled and disabled {@link PhoneAccount}s.
+ * @hide
+ */
+ @SystemApi
+ public int getAllPhoneAccountsCount() {
+ try {
+ if (isServiceConnected()) {
+ return getTelecommService().getAllPhoneAccountsCount();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecommService#getAllPhoneAccountsCount", e);
+ }
+ return 0;
+ }
+
+ /**
+ * Returns a list of all {@link PhoneAccount}s.
+ *
+ * @return All {@link PhoneAccount}s.
+ * @hide
+ */
+ @SystemApi
+ public List<PhoneAccount> getAllPhoneAccounts() {
+ try {
+ if (isServiceConnected()) {
+ return getTelecommService().getAllPhoneAccounts();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecommService#getAllPhoneAccounts", e);
+ }
+ return Collections.EMPTY_LIST;
+ }
+
+ /**
+ * Returns a list of all {@link PhoneAccountHandle}s.
+ *
+ * @return All {@link PhoneAccountHandle}s.
+ * @hide
+ */
+ @SystemApi
+ public List<PhoneAccountHandle> getAllPhoneAccountHandles() {
+ try {
+ if (isServiceConnected()) {
+ return getTelecommService().getAllPhoneAccountHandles();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecommService#getAllPhoneAccountHandles", e);
+ }
+ return Collections.EMPTY_LIST;
+ }
+
+ /**
+ * Enables or disables a {@link PhoneAccount}.
+ *
+ * @param account The {@link PhoneAccountHandle} to enable or disable.
+ * @param isEnabled {@code True} if the phone account should be enabled.
+ * @hide
+ */
+ @SystemApi
+ public void setPhoneAccountEnabled(PhoneAccountHandle account, boolean isEnabled) {
+ try {
+ if (isServiceConnected()) {
+ getTelecommService().setPhoneAccountEnabled(account, isEnabled);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecommService#setPhoneAccountEnabled", e);
+ }
+ }
+
+ /**
* Register a {@link PhoneAccount} for use by the system.
*
* @param account The complete {@link PhoneAccount}.
@@ -489,15 +603,13 @@
}
/**
- * Remove all Accounts for a given package from the system.
- *
- * @param packageName A package name that may have registered Accounts.
+ * Remove all Accounts that belong to the calling package from the system.
*/
@SystemApi
- public void clearAccounts(String packageName) {
+ public void clearAccounts() {
try {
if (isServiceConnected()) {
- getTelecommService().clearAccounts(packageName);
+ getTelecommService().clearAccounts(mContext.getPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecommService#clearAccounts", e);
diff --git a/telecomm/java/android/telecomm/VideoCallImpl.java b/telecomm/java/android/telecomm/VideoCallImpl.java
index c10865f..d33a351 100644
--- a/telecomm/java/android/telecomm/VideoCallImpl.java
+++ b/telecomm/java/android/telecomm/VideoCallImpl.java
@@ -157,7 +157,7 @@
mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
mBinder = new VideoCallListenerBinder();
- mVideoProvider.setVideoListener(mBinder);
+ mVideoProvider.setVideoCallback(mBinder);
}
/** {@inheritDoc} */
diff --git a/telecomm/java/android/telecomm/VideoCallbackServant.java b/telecomm/java/android/telecomm/VideoCallbackServant.java
new file mode 100644
index 0000000..060b8a9
--- /dev/null
+++ b/telecomm/java/android/telecomm/VideoCallbackServant.java
@@ -0,0 +1,160 @@
+/*
+ * 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
+ R* limitations under the License.
+ */
+
+package android.telecomm;
+
+import com.android.internal.os.SomeArgs;
+import com.android.internal.telecomm.IVideoCallback;
+
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+
+/**
+ * A component that provides an RPC servant implementation of {@link IVideoCallback},
+ * posting incoming messages on the main thread on a client-supplied delegate object.
+ *
+ * TODO: Generate this and similar classes using a compiler starting from AIDL interfaces.
+ *
+ * @hide
+ */
+final class VideoCallbackServant {
+ private static final int MSG_RECEIVE_SESSION_MODIFY_REQUEST = 0;
+ private static final int MSG_RECEIVE_SESSION_MODIFY_RESPONSE = 1;
+ private static final int MSG_HANDLE_CALL_SESSION_EVENT = 2;
+ private static final int MSG_CHANGE_PEER_DIMENSIONS = 3;
+ private static final int MSG_CHANGE_CALL_DATA_USAGE = 4;
+ private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 5;
+
+ private final IVideoCallback mDelegate;
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ try {
+ internalHandleMessage(msg);
+ } catch (RemoteException e) {
+ }
+ }
+
+ // Internal method defined to centralize handling of RemoteException
+ private void internalHandleMessage(Message msg) throws RemoteException {
+ switch (msg.what) {
+ case MSG_RECEIVE_SESSION_MODIFY_REQUEST: {
+ mDelegate.receiveSessionModifyRequest((VideoProfile) msg.obj);
+ break;
+ }
+ case MSG_RECEIVE_SESSION_MODIFY_RESPONSE: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ mDelegate.receiveSessionModifyResponse(
+ args.argi1,
+ (VideoProfile) args.arg1,
+ (VideoProfile) args.arg2);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
+ case MSG_HANDLE_CALL_SESSION_EVENT: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ mDelegate.handleCallSessionEvent(args.argi1);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
+ case MSG_CHANGE_PEER_DIMENSIONS: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ mDelegate.changePeerDimensions(args.argi1, args.argi2);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
+ case MSG_CHANGE_CALL_DATA_USAGE: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ mDelegate.changeCallDataUsage(args.argi1);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
+ case MSG_CHANGE_CAMERA_CAPABILITIES: {
+ mDelegate.changeCameraCapabilities((CameraCapabilities) msg.obj);
+ break;
+ }
+ }
+ }
+ };
+
+ private final IVideoCallback mStub = new IVideoCallback.Stub() {
+ @Override
+ public void receiveSessionModifyRequest(VideoProfile videoProfile) throws RemoteException {
+ mHandler.obtainMessage(MSG_RECEIVE_SESSION_MODIFY_REQUEST, videoProfile).sendToTarget();
+ }
+
+ @Override
+ public void receiveSessionModifyResponse(int status, VideoProfile requestedProfile,
+ VideoProfile responseProfile) throws RemoteException {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = status;
+ args.arg1 = requestedProfile;
+ args.arg2 = responseProfile;
+ mHandler.obtainMessage(MSG_RECEIVE_SESSION_MODIFY_RESPONSE, args).sendToTarget();
+ }
+
+ @Override
+ public void handleCallSessionEvent(int event) throws RemoteException {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = event;
+ mHandler.obtainMessage(MSG_HANDLE_CALL_SESSION_EVENT, args).sendToTarget();
+ }
+
+ @Override
+ public void changePeerDimensions(int width, int height) throws RemoteException {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = width;
+ args.argi2 = height;
+ mHandler.obtainMessage(MSG_CHANGE_PEER_DIMENSIONS, args).sendToTarget();
+ }
+
+ @Override
+ public void changeCallDataUsage(int dataUsage) throws RemoteException {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = dataUsage;
+ mHandler.obtainMessage(MSG_CHANGE_CALL_DATA_USAGE, args).sendToTarget();
+ }
+
+ @Override
+ public void changeCameraCapabilities(CameraCapabilities cameraCapabilities)
+ throws RemoteException {
+ mHandler.obtainMessage(MSG_CHANGE_CAMERA_CAPABILITIES, cameraCapabilities)
+ .sendToTarget();
+ }
+ };
+
+ public VideoCallbackServant(IVideoCallback delegate) {
+ mDelegate = delegate;
+ }
+
+ public IVideoCallback getStub() {
+ return mStub;
+ }
+}
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
index a673733..3af4ed3 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
@@ -70,6 +70,4 @@
void swapConference(String conferenceCallId);
void onPostDialContinue(String callId, boolean proceed);
-
- void onPhoneAccountClicked(String callId);
}
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
index 610178e..4b636d1 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
@@ -49,7 +49,7 @@
void setOnHold(String callId);
- void setRequestingRingback(String callId, boolean ringing);
+ void setRingbackRequested(String callId, boolean ringing);
void setCallCapabilities(String callId, int callCapabilities);
@@ -67,11 +67,11 @@
void setVideoState(String callId, int videoState);
- void setAudioModeIsVoip(String callId, boolean isVoip);
+ void setIsVoipAudioMode(String callId, boolean isVoip);
void setStatusHints(String callId, in StatusHints statusHints);
- void setHandle(String callId, in Uri handle, int presentation);
+ void setAddress(String callId, in Uri address, int presentation);
void setCallerDisplayName(String callId, String callerDisplayName, int presentation);
diff --git a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
index 626bb91..808a410 100644
--- a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
@@ -46,8 +46,6 @@
void postDialContinue(String callId, boolean proceed);
- void phoneAccountClicked(String callId);
-
void phoneAccountSelected(String callId, in PhoneAccountHandle accountHandle);
void conference(String callId, String otherCallId);
diff --git a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
index 6ab78c4..30f2801 100644
--- a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
@@ -50,9 +50,9 @@
void setUserSelectedOutgoingPhoneAccount(in PhoneAccountHandle account);
/**
- * @see TelecommServiceImpl#getOutgoingPhoneAccounts
+ * @see TelecommServiceImpl#getEnabledPhoneAccounts
*/
- List<PhoneAccountHandle> getOutgoingPhoneAccounts();
+ List<PhoneAccountHandle> getEnabledPhoneAccounts();
/**
* @see TelecommManager#getPhoneAccountsSupportingScheme
@@ -65,6 +65,21 @@
PhoneAccount getPhoneAccount(in PhoneAccountHandle account);
/**
+ * @see TelecommManager#getAllPhoneAccountsCount
+ */
+ int getAllPhoneAccountsCount();
+
+ /**
+ * @see TelecommManager#getAllPhoneAccounts
+ */
+ List<PhoneAccount> getAllPhoneAccounts();
+
+ /**
+ * @see TelecommManager#getAllPhoneAccountHandles
+ */
+ List<PhoneAccountHandle> getAllPhoneAccountHandles();
+
+ /**
* @see TelecommServiceImpl#getSimCallManager
*/
PhoneAccountHandle getSimCallManager();
@@ -80,6 +95,11 @@
List<PhoneAccountHandle> getSimCallManagers();
/**
+ * @see TelecommServiceImpl#setPhoneAccountEnabled
+ */
+ void setPhoneAccountEnabled(in PhoneAccountHandle account, in boolean isEnabled);
+
+ /**
* @see TelecommServiceImpl#registerPhoneAccount
*/
void registerPhoneAccount(in PhoneAccount metadata);
diff --git a/telecomm/java/com/android/internal/telecomm/IVideoProvider.aidl b/telecomm/java/com/android/internal/telecomm/IVideoProvider.aidl
index 9d3ad7f..b0aa988 100644
--- a/telecomm/java/com/android/internal/telecomm/IVideoProvider.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IVideoProvider.aidl
@@ -25,7 +25,7 @@
* @hide
*/
oneway interface IVideoProvider {
- void setVideoListener(IBinder videoListenerBinder);
+ void setVideoCallback(IBinder videoCallbackBinder);
void setCamera(String cameraId);
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 1d9e6a9..30799f8 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -2316,8 +2316,9 @@
/**
* This function checks if the passed in string conforms to the NANP format
* i.e. NXX-NXX-XXXX, N is any digit 2-9 and X is any digit 0-9
+ * @hide
*/
- private static boolean isNanp (String dialStr) {
+ public static boolean isNanp (String dialStr) {
boolean retVal = false;
if (dialStr != null) {
if (dialStr.length() == NANP_LENGTH) {
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 58d30f1..fe68263 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -265,9 +265,9 @@
* @return SubInfoRecord, maybe null
* @hide - to be unhidden
*/
- public static SubInfoRecord getSubInfoUsingSubId(long subId) {
+ public static SubInfoRecord getSubInfoForSubscriber(long subId) {
if (!isValidSubId(subId)) {
- logd("[getSubInfoUsingSubIdx]- invalid subId");
+ logd("[getSubInfoForSubscriberx]- invalid subId");
return null;
}
@@ -276,7 +276,7 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- subInfo = iSub.getSubInfoUsingSubId(subId);
+ subInfo = iSub.getSubInfoForSubscriber(subId);
}
} catch (RemoteException ex) {
// ignore it
@@ -783,7 +783,7 @@
/** @hide */
public static SubInfoRecord getDefaultVoiceSubInfo() {
- return getSubInfoUsingSubId(getDefaultVoiceSubId());
+ return getSubInfoForSubscriber(getDefaultVoiceSubId());
}
/** @hide */
@@ -826,7 +826,7 @@
/** @hide */
public static SubInfoRecord getDefaultSmsSubInfo() {
- return getSubInfoUsingSubId(getDefaultSmsSubId());
+ return getSubInfoForSubscriber(getDefaultSmsSubId());
}
/** @hide */
@@ -866,7 +866,7 @@
/** @hide */
public static SubInfoRecord getDefaultDataSubInfo() {
- return getSubInfoUsingSubId(getDefaultDataSubId());
+ return getSubInfoForSubscriber(getDefaultDataSubId());
}
/** @hide */
@@ -930,13 +930,20 @@
/** @hide */
public static boolean isValidSlotId(int slotId) {
- return slotId > INVALID_SLOT_ID && slotId < TelephonyManager.getDefault().getSimCount();
+ // We are testing INVALID_SLOT_ID and slotId >= 0 independently because we should
+ // not assume that INVALID_SLOT_ID will always be a negative value. Any negative
+ // value is invalid.
+ return slotId != INVALID_SLOT_ID && slotId >= 0 &&
+ slotId < TelephonyManager.getDefault().getSimCount();
}
/** @hide */
public static boolean isValidPhoneId(int phoneId) {
- return phoneId > INVALID_PHONE_ID
- && phoneId < TelephonyManager.getDefault().getPhoneCount();
+ // We are testing INVALID_PHONE_ID and phoneId >= 0 independently because we should
+ // not assume that INVALID_PHONE_ID will always be a negative value. Any negative
+ // value is invalid.
+ return phoneId != INVALID_PHONE_ID && phoneId >= 0 &&
+ phoneId < TelephonyManager.getDefault().getPhoneCount();
}
/** @hide */
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 93c49ba..9f94040 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -608,7 +608,7 @@
public String getDeviceId(int slotId) {
long[] subId = SubscriptionManager.getSubId(slotId);
try {
- return getSubscriberInfo().getDeviceIdUsingSubId(subId[0]);
+ return getSubscriberInfo().getDeviceIdForSubscriber(subId[0]);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -639,7 +639,7 @@
public String getImei(int slotId) {
long[] subId = SubscriptionManager.getSubId(slotId);
try {
- return getSubscriberInfo().getImeiUsingSubId(subId[0]);
+ return getSubscriberInfo().getImeiForSubscriber(subId[0]);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -703,7 +703,7 @@
/** @hide */
public void enableLocationUpdates(long subId) {
try {
- getITelephony().enableLocationUpdatesUsingSubId(subId);
+ getITelephony().enableLocationUpdatesForSubscriber(subId);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -725,7 +725,7 @@
/** @hide */
public void disableLocationUpdates(long subId) {
try {
- getITelephony().disableLocationUpdatesUsingSubId(subId);
+ getITelephony().disableLocationUpdatesForSubscriber(subId);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -772,6 +772,7 @@
*
* {@hide}
*/
+ @SystemApi
public int getCurrentPhoneType() {
return getCurrentPhoneType(getDefaultSubscription());
}
@@ -786,12 +787,13 @@
* @param subId for which phone type is returned
*/
/** {@hide} */
+ @SystemApi
public int getCurrentPhoneType(long subId) {
try{
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getActivePhoneTypeUsingSubId(subId);
+ return telephony.getActivePhoneTypeForSubscriber(subId);
} else {
// This can happen when the ITelephony interface is not up yet.
return getPhoneTypeFromProperty(subId);
@@ -1157,7 +1159,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getNetworkTypeUsingSubId(subId);
+ return telephony.getNetworkTypeForSubscriber(subId);
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -1211,7 +1213,7 @@
try{
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getDataNetworkTypeUsingSubId(subId);
+ return telephony.getDataNetworkTypeForSubscriber(subId);
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -1243,7 +1245,7 @@
try{
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getVoiceNetworkTypeUsingSubId(subId);
+ return telephony.getVoiceNetworkTypeForSubscriber(subId);
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -1570,7 +1572,7 @@
/** {@hide} */
public String getSimSerialNumber(long subId) {
try {
- return getSubscriberInfo().getIccSerialNumberUsingSubId(subId);
+ return getSubscriberInfo().getIccSerialNumberForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1606,7 +1608,7 @@
/** {@hide} */
public int getLteOnCdmaMode(long subId) {
try {
- return getITelephony().getLteOnCdmaModeUsingSubId(subId);
+ return getITelephony().getLteOnCdmaModeForSubscriber(subId);
} catch (RemoteException ex) {
// Assume no ICC card if remote exception which shouldn't happen
return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
@@ -1646,7 +1648,7 @@
/** {@hide} */
public String getSubscriberId(long subId) {
try {
- return getSubscriberInfo().getSubscriberIdUsingSubId(subId);
+ return getSubscriberInfo().getSubscriberIdForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1685,7 +1687,7 @@
/** {@hide} */
public String getGroupIdLevel1(long subId) {
try {
- return getSubscriberInfo().getGroupIdLevel1UsingSubId(subId);
+ return getSubscriberInfo().getGroupIdLevel1ForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1702,7 +1704,7 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
public String getLine1Number() {
- return getLine1Number(getDefaultSubscription());
+ return getLine1NumberForSubscriber(getDefaultSubscription());
}
/**
@@ -1715,7 +1717,7 @@
* @param subId whose phone number for line 1 is returned
*/
/** {@hide} */
- public String getLine1Number(long subId) {
+ public String getLine1NumberForSubscriber(long subId) {
String number = null;
try {
number = getITelephony().getLine1NumberForDisplay(subId);
@@ -1726,7 +1728,7 @@
return number;
}
try {
- return getSubscriberInfo().getLine1NumberUsingSubId(subId);
+ return getSubscriberInfo().getLine1NumberForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1736,10 +1738,10 @@
}
/**
- * Set the phone number string and its alphatag for line 1 for display
- * purpose only, for example, displayed in Phone Status. It won't change
- * the actual MSISDN/MDN. This setting won't be persisted during power cycle
- * and it should be set again after reboot.
+ * Set the line 1 phone number string and its alphatag for the current ICCID
+ * for display purpose only, for example, displayed in Phone Status. It won't
+ * change the actual MSISDN/MDN. To unset alphatag or number, pass in a null
+ * value.
* <p>
* Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
@@ -1749,14 +1751,14 @@
* @param number The dialing number
*/
public void setLine1NumberForDisplay(String alphaTag, String number) {
- setLine1NumberForDisplay(getDefaultSubscription(), alphaTag, number);
+ setLine1NumberForDisplayForSubscriber(getDefaultSubscription(), alphaTag, number);
}
/**
- * Set the phone number string and its alphatag for line 1 for display
- * purpose only, for example, displayed in Phone Status. It won't change
- * the actual MSISDN/MDN. This setting won't be persisted during power cycle
- * and it should be set again after reboot.
+ * Set the line 1 phone number string and its alphatag for the current ICCID
+ * for display purpose only, for example, displayed in Phone Status. It won't
+ * change the actual MSISDN/MDN. To unset alphatag or number, pass in a null
+ * value.
* <p>
* Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
@@ -1765,10 +1767,11 @@
* @param subId the subscriber that the alphatag and dialing number belongs to.
* @param alphaTag alpha-tagging of the dailing nubmer
* @param number The dialing number
+ * @hide
*/
- public void setLine1NumberForDisplay(long subId, String alphaTag, String number) {
+ public void setLine1NumberForDisplayForSubscriber(long subId, String alphaTag, String number) {
try {
- getITelephony().setLine1NumberForDisplay(subId, alphaTag, number);
+ getITelephony().setLine1NumberForDisplayForSubscriber(subId, alphaTag, number);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -1784,7 +1787,7 @@
* nobody seems to call this.
*/
public String getLine1AlphaTag() {
- return getLine1AlphaTag(getDefaultSubscription());
+ return getLine1AlphaTagForSubscriber(getDefaultSubscription());
}
/**
@@ -1798,7 +1801,7 @@
* nobody seems to call this.
*/
/** {@hide} */
- public String getLine1AlphaTag(long subId) {
+ public String getLine1AlphaTagForSubscriber(long subId) {
String alphaTag = null;
try {
alphaTag = getITelephony().getLine1AlphaTagForDisplay(subId);
@@ -1809,7 +1812,7 @@
return alphaTag;
}
try {
- return getSubscriberInfo().getLine1AlphaTagUsingSubId(subId);
+ return getSubscriberInfo().getLine1AlphaTagForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1843,7 +1846,7 @@
/** {@hide} */
public String getMsisdn(long subId) {
try {
- return getSubscriberInfo().getMsisdnUsingSubId(subId);
+ return getSubscriberInfo().getMsisdnForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1873,7 +1876,7 @@
/** {@hide} */
public String getVoiceMailNumber(long subId) {
try {
- return getSubscriberInfo().getVoiceMailNumberUsingSubId(subId);
+ return getSubscriberInfo().getVoiceMailNumberForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1905,7 +1908,7 @@
/** {@hide} */
public String getCompleteVoiceMailNumber(long subId) {
try {
- return getSubscriberInfo().getCompleteVoiceMailNumberUsingSubId(subId);
+ return getSubscriberInfo().getCompleteVoiceMailNumberForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1935,7 +1938,7 @@
/** {@hide} */
public int getVoiceMessageCount(long subId) {
try {
- return getITelephony().getVoiceMessageCountUsingSubId(subId);
+ return getITelephony().getVoiceMessageCountForSubscriber(subId);
} catch (RemoteException ex) {
return 0;
} catch (NullPointerException ex) {
@@ -1967,7 +1970,7 @@
/** {@hide} */
public String getVoiceMailAlphaTag(long subId) {
try {
- return getSubscriberInfo().getVoiceMailAlphaTagUsingSubId(subId);
+ return getSubscriberInfo().getVoiceMailAlphaTagForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -2057,7 +2060,7 @@
/** {@hide} */
public int getCallState(long subId) {
try {
- return getITelephony().getCallStateUsingSubId(subId);
+ return getITelephony().getCallStateForSubscriber(subId);
} catch (RemoteException ex) {
// the phone process is restarting.
return CALL_STATE_IDLE;
@@ -2179,7 +2182,7 @@
String pkgForDebug = mContext != null ? mContext.getPackageName() : "<unknown>";
try {
Boolean notifyNow = (getITelephony() != null);
- sRegistry.listenUsingSubId(listener.mSubId, pkgForDebug, listener.callback, events, notifyNow);
+ sRegistry.listenForSubscriber(listener.mSubId, pkgForDebug, listener.callback, events, notifyNow);
} catch (RemoteException ex) {
// system process dead
} catch (NullPointerException ex) {
@@ -2202,7 +2205,7 @@
/** {@hide} */
public int getCdmaEriIconIndex(long subId) {
try {
- return getITelephony().getCdmaEriIconIndexUsingSubId(subId);
+ return getITelephony().getCdmaEriIconIndexForSubscriber(subId);
} catch (RemoteException ex) {
// the phone process is restarting.
return -1;
@@ -2230,7 +2233,7 @@
/** {@hide} */
public int getCdmaEriIconMode(long subId) {
try {
- return getITelephony().getCdmaEriIconModeUsingSubId(subId);
+ return getITelephony().getCdmaEriIconModeForSubscriber(subId);
} catch (RemoteException ex) {
// the phone process is restarting.
return -1;
@@ -2255,7 +2258,7 @@
/** {@hide} */
public String getCdmaEriText(long subId) {
try {
- return getITelephony().getCdmaEriTextUsingSubId(subId);
+ return getITelephony().getCdmaEriTextForSubscriber(subId);
} catch (RemoteException ex) {
// the phone process is restarting.
return null;
@@ -3356,8 +3359,8 @@
}
/**
- * Set whether Android should display a simplified Mobile Network Settings UI.
- * The setting won't be persisted during power cycle.
+ * Set whether Android should display a simplified Mobile Network Settings UI
+ * for the current ICCID.
* <p>
* Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
@@ -3367,12 +3370,12 @@
* @hide
*/
public void enableSimplifiedNetworkSettings(boolean enable) {
- enableSimplifiedNetworkSettings(getDefaultSubscription(), enable);
+ enableSimplifiedNetworkSettingsForSubscriber(getDefaultSubscription(), enable);
}
/**
- * Set whether Android should display a simplified Mobile Network Settings UI.
- * The setting won't be persisted during power cycle.
+ * Set whether Android should display a simplified Mobile Network Settings UI
+ * for the current ICCID.
* <p>
* Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
@@ -3382,16 +3385,17 @@
* @param enable true means enabling the simplified UI.
* @hide
*/
- public void enableSimplifiedNetworkSettings(long subId, boolean enable) {
+ public void enableSimplifiedNetworkSettingsForSubscriber(long subId, boolean enable) {
try {
- getITelephony().enableSimplifiedNetworkSettings(subId, enable);
+ getITelephony().enableSimplifiedNetworkSettingsForSubscriber(subId, enable);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
}
/**
- * Get whether a simplified Mobile Network Settings UI is enabled.
+ * Get whether a simplified Mobile Network Settings UI is enabled for the
+ * current ICCID.
* <p>
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -3400,11 +3404,12 @@
* @hide
*/
public boolean getSimplifiedNetworkSettingsEnabled() {
- return getSimplifiedNetworkSettingsEnabled(getDefaultSubscription());
+ return getSimplifiedNetworkSettingsEnabledForSubscriber(getDefaultSubscription());
}
/**
- * Get whether a simplified Mobile Network Settings UI is enabled.
+ * Get whether a simplified Mobile Network Settings UI is enabled for the
+ * current ICCID.
* <p>
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -3413,9 +3418,9 @@
* @return true if the simplified UI is enabled.
* @hide
*/
- public boolean getSimplifiedNetworkSettingsEnabled(long subId) {
+ public boolean getSimplifiedNetworkSettingsEnabledForSubscriber(long subId) {
try {
- return getITelephony().getSimplifiedNetworkSettingsEnabled(subId);
+ return getITelephony().getSimplifiedNetworkSettingsEnabledForSubscriber(subId);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index 552abaf..c203442 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -31,12 +31,12 @@
* Retrieves the unique device ID of a subId for the device, e.g., IMEI
* for GSM phones.
*/
- String getDeviceIdUsingSubId(long subId);
+ String getDeviceIdForSubscriber(long subId);
/**
* Retrieves the IMEI.
*/
- String getImeiUsingSubId(long subId);
+ String getImeiForSubscriber(long subId);
/**
* Retrieves the software version number for the device, e.g., IMEI/SV
@@ -52,7 +52,7 @@
/**
* Retrieves the unique subscriber ID of a given subId, e.g., IMSI for GSM phones.
*/
- String getSubscriberIdUsingSubId(long subId);
+ String getSubscriberIdForSubscriber(long subId);
/**
* Retrieves the Group Identifier Level1 for GSM phones.
@@ -62,7 +62,7 @@
/**
* Retrieves the Group Identifier Level1 for GSM phones of a subId.
*/
- String getGroupIdLevel1UsingSubId(long subId);
+ String getGroupIdLevel1ForSubscriber(long subId);
/**
* Retrieves the serial number of the ICC, if applicable.
@@ -72,7 +72,7 @@
/**
* Retrieves the serial number of a given subId.
*/
- String getIccSerialNumberUsingSubId(long subId);
+ String getIccSerialNumberForSubscriber(long subId);
/**
* Retrieves the phone number string for line 1.
@@ -82,7 +82,7 @@
/**
* Retrieves the phone number string for line 1 of a subcription.
*/
- String getLine1NumberUsingSubId(long subId);
+ String getLine1NumberForSubscriber(long subId);
/**
@@ -93,7 +93,7 @@
/**
* Retrieves the alpha identifier for line 1 of a subId.
*/
- String getLine1AlphaTagUsingSubId(long subId);
+ String getLine1AlphaTagForSubscriber(long subId);
/**
@@ -104,7 +104,7 @@
/**
* Retrieves the Msisdn of a subId.
*/
- String getMsisdnUsingSubId(long subId);
+ String getMsisdnForSubscriber(long subId);
/**
* Retrieves the voice mail number.
@@ -114,7 +114,7 @@
/**
* Retrieves the voice mail number of a given subId.
*/
- String getVoiceMailNumberUsingSubId(long subId);
+ String getVoiceMailNumberForSubscriber(long subId);
/**
* Retrieves the complete voice mail number.
@@ -124,7 +124,7 @@
/**
* Retrieves the complete voice mail number for particular subId
*/
- String getCompleteVoiceMailNumberUsingSubId(long subId);
+ String getCompleteVoiceMailNumberForSubscriber(long subId);
/**
* Retrieves the alpha identifier associated with the voice mail number.
@@ -135,7 +135,7 @@
* Retrieves the alpha identifier associated with the voice mail number
* of a subId.
*/
- String getVoiceMailAlphaTagUsingSubId(long subId);
+ String getVoiceMailAlphaTagForSubscriber(long subId);
/**
* Returns the IMS private user identity (IMPI) that was loaded from the ISIM.
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index abbdc4a..32bb8b4 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -47,7 +47,7 @@
* @param subId the subId id.
* @return list of SmsRawData of all sms on ICC
*/
- List<SmsRawData> getAllMessagesFromIccEfUsingSubId(in long subId, String callingPkg);
+ List<SmsRawData> getAllMessagesFromIccEfForSubscriber(in long subId, String callingPkg);
/**
* Update the specified message on the ICC.
@@ -75,7 +75,7 @@
* @return success or not
*
*/
- boolean updateMessageOnIccEfUsingSubId(in long subId, String callingPkg,
+ boolean updateMessageOnIccEfForSubscriber(in long subId, String callingPkg,
int messageIndex, int newStatus, in byte[] pdu);
/**
@@ -99,7 +99,7 @@
* @return success or not
*
*/
- boolean copyMessageToIccEfUsingSubId(in long subId, String callingPkg, int status,
+ boolean copyMessageToIccEfForSubscriber(in long subId, String callingPkg, int status,
in byte[] pdu, in byte[] smsc);
/**
@@ -152,7 +152,7 @@
* raw pdu of the status report is in the extended data ("pdu").
* @param subId the subId id.
*/
- void sendDataUsingSubId(long subId, String callingPkg, in String destAddr,
+ void sendDataForSubscriber(long subId, String callingPkg, in String destAddr,
in String scAddr, in int destPort, in byte[] data, in PendingIntent sentIntent,
in PendingIntent deliveryIntent);
@@ -206,7 +206,7 @@
* raw pdu of the status report is in the extended data ("pdu").
* @param subId the subId on which the SMS has to be sent.
*/
- void sendTextUsingSubId(in long subId, String callingPkg, in String destAddr,
+ void sendTextForSubscriber(in long subId, String callingPkg, in String destAddr,
in String scAddr, in String text, in PendingIntent sentIntent,
in PendingIntent deliveryIntent);
@@ -283,7 +283,7 @@
* extended data ("pdu").
* @param subId the subId on which the SMS has to be sent.
*/
- void sendMultipartTextUsingSubId(in long subId, String callingPkg,
+ void sendMultipartTextForSubscriber(in long subId, String callingPkg,
in String destinationAddress, in String scAddress,
in List<String> parts, in List<PendingIntent> sentIntents,
in List<PendingIntent> deliveryIntents);
@@ -315,7 +315,7 @@
*
* @see #disableCellBroadcast(int)
*/
- boolean enableCellBroadcastUsingSubId(in long subId, int messageIdentifier);
+ boolean enableCellBroadcastForSubscriber(in long subId, int messageIdentifier);
/**
* Disable reception of cell broadcast (SMS-CB) messages with the given
@@ -344,7 +344,7 @@
*
* @see #enableCellBroadcast(int)
*/
- boolean disableCellBroadcastUsingSubId(in long subId, int messageIdentifier);
+ boolean disableCellBroadcastForSubscriber(in long subId, int messageIdentifier);
/*
* Enable reception of cell broadcast (SMS-CB) messages with the given
@@ -377,7 +377,7 @@
*
* @see #disableCellBroadcastRange(int, int)
*/
- boolean enableCellBroadcastRangeUsingSubId(long subId, int startMessageId, int endMessageId);
+ boolean enableCellBroadcastRangeForSubscriber(long subId, int startMessageId, int endMessageId);
/**
* Disable reception of cell broadcast (SMS-CB) messages with the given
@@ -410,7 +410,7 @@
*
* @see #enableCellBroadcastRange(int, int, int)
*/
- boolean disableCellBroadcastRangeUsingSubId(long subId, int startMessageId,
+ boolean disableCellBroadcastRangeForSubscriber(long subId, int startMessageId,
int endMessageId);
/**
@@ -423,7 +423,7 @@
* Returns the premium SMS send permission for the specified package.
* Requires system permission.
*/
- int getPremiumSmsPermissionUsingSubId(long subId, String packageName);
+ int getPremiumSmsPermissionForSubscriber(long subId, String packageName);
/**
* Set the SMS send permission for the specified package.
@@ -439,7 +439,7 @@
* Set the SMS send permission for the specified package.
* Requires system permission.
*/
- void setPremiumSmsPermissionUsingSubId(long subId, String packageName, int permission);
+ void setPremiumSmsPermissionForSubscriber(long subId, String packageName, int permission);
/**
* SMS over IMS is supported if IMS is registered and SMS is supported
@@ -459,7 +459,7 @@
*
* @see #getImsSmsFormat()
*/
- boolean isImsSmsSupportedUsingSubId(long subId);
+ boolean isImsSmsSupportedForSubscriber(long subId);
/*
* get user prefered SMS subId
@@ -489,7 +489,7 @@
*
* @see #isImsSmsSupported()
*/
- String getImsSmsFormatUsingSubId(long subId);
+ String getImsSmsFormatForSubscriber(long subId);
/*
* Get SMS prompt property, enabled or not
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 46d0660..b87365e 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -25,7 +25,7 @@
* @param subId The unique SubInfoRecord index in database
* @return SubInfoRecord, maybe null
*/
- SubInfoRecord getSubInfoUsingSubId(long subId);
+ SubInfoRecord getSubInfoForSubscriber(long subId);
/**
* Get the SubInfoRecord according to an IccId
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 79c72b88..0868f41 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -59,7 +59,7 @@
* @param subId user preferred subId.
* @return whether it hung up
*/
- boolean endCallUsingSubId(long subId);
+ boolean endCallForSubscriber(long subId);
/**
* Answer the currently-ringing call.
@@ -103,7 +103,7 @@
* @param subId user preferred subId.
* @return true if the phone state is OFFHOOK.
*/
- boolean isOffhookUsingSubId(long subId);
+ boolean isOffhookForSubscriber(long subId);
/**
* Check if an incoming phone call is ringing or call waiting
@@ -112,7 +112,7 @@
* @param subId user preferred subId.
* @return true if the phone state is RINGING.
*/
- boolean isRingingUsingSubId(long subId);
+ boolean isRingingForSubscriber(long subId);
/**
* Check if an incoming phone call is ringing or call waiting.
@@ -132,7 +132,7 @@
* @param subId user preferred subId.
* @return true if the phone state is IDLE.
*/
- boolean isIdleUsingSubId(long subId);
+ boolean isIdleForSubscriber(long subId);
/**
* Check to see if the radio is on or not.
@@ -145,7 +145,7 @@
* @param subId user preferred subId.
* @return returns true if the radio is on.
*/
- boolean isRadioOnUsingSubId(long subId);
+ boolean isRadioOnForSubscriber(long subId);
/**
* Check if the SIM pin lock is enabled.
@@ -167,7 +167,7 @@
* @param subId user preferred subId.
* @return whether the operation was a success.
*/
- boolean supplyPinUsingSubId(long subId, String pin);
+ boolean supplyPinForSubscriber(long subId, String pin);
/**
* Supply puk to unlock the SIM and set SIM pin to new pin.
@@ -186,7 +186,7 @@
* @param subId user preferred subId.
* @return whether the operation was a success.
*/
- boolean supplyPukUsingSubId(long subId, String puk, String pin);
+ boolean supplyPukForSubscriber(long subId, String puk, String pin);
/**
* Supply a pin to unlock the SIM. Blocks until a result is determined.
@@ -204,7 +204,7 @@
* @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code
* retValue[1] = number of attempts remaining if known otherwise -1
*/
- int[] supplyPinReportResultUsingSubId(long subId, String pin);
+ int[] supplyPinReportResultForSubscriber(long subId, String pin);
/**
* Supply puk to unlock the SIM and set SIM pin to new pin.
@@ -226,7 +226,7 @@
* @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code
* retValue[1] = number of attempts remaining if known otherwise -1
*/
- int[] supplyPukReportResultUsingSubId(long subId, String puk, String pin);
+ int[] supplyPukReportResultForSubscriber(long subId, String puk, String pin);
/**
* Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
@@ -245,7 +245,7 @@
* @param subId user preferred subId.
* @return true if MMI command is executed.
*/
- boolean handlePinMmiUsingSubId(long subId, String dialString);
+ boolean handlePinMmiForSubscriber(long subId, String dialString);
/**
* Toggles the radio on or off.
@@ -256,7 +256,7 @@
* Toggles the radio on or off on particular subId.
* @param subId user preferred subId.
*/
- void toggleRadioOnOffUsingSubId(long subId);
+ void toggleRadioOnOffForSubscriber(long subId);
/**
* Set the radio to on or off
@@ -267,7 +267,7 @@
* Set the radio to on or off on particular subId.
* @param subId user preferred subId.
*/
- boolean setRadioUsingSubId(long subId, boolean turnOn);
+ boolean setRadioForSubscriber(long subId, boolean turnOn);
/**
* Set the radio to on or off unconditionally
@@ -283,7 +283,7 @@
* Request to update location information for a subscrition in service state
* @param subId user preferred subId.
*/
- void updateServiceLocationUsingSubId(long subId);
+ void updateServiceLocationForSubscriber(long subId);
/**
* Enable location update notifications.
@@ -294,7 +294,7 @@
* Enable location update notifications.
* @param subId user preferred subId.
*/
- void enableLocationUpdatesUsingSubId(long subId);
+ void enableLocationUpdatesForSubscriber(long subId);
/**
* Disable location update notifications.
@@ -305,7 +305,7 @@
* Disable location update notifications.
* @param subId user preferred subId.
*/
- void disableLocationUpdatesUsingSubId(long subId);
+ void disableLocationUpdatesForSubscriber(long subId);
/**
* Allow mobile data connections.
@@ -334,7 +334,7 @@
/**
* Returns the call state for a subId.
*/
- int getCallStateUsingSubId(long subId);
+ int getCallStateForSubscriber(long subId);
int getDataActivity();
int getDataState();
@@ -352,7 +352,7 @@
* and TelephonyManager.PHONE_TYPE_GSM if RILConstants.GSM_PHONE
* @param subId user preferred subId.
*/
- int getActivePhoneTypeUsingSubId(long subId);
+ int getActivePhoneTypeForSubscriber(long subId);
/**
* Returns the CDMA ERI icon index to display
@@ -363,7 +363,7 @@
* Returns the CDMA ERI icon index to display on particular subId.
* @param subId user preferred subId.
*/
- int getCdmaEriIconIndexUsingSubId(long subId);
+ int getCdmaEriIconIndexForSubscriber(long subId);
/**
* Returns the CDMA ERI icon mode,
@@ -378,7 +378,7 @@
* 1 - FLASHING
* @param subId user preferred subId.
*/
- int getCdmaEriIconModeUsingSubId(long subId);
+ int getCdmaEriIconModeForSubscriber(long subId);
/**
* Returns the CDMA ERI text,
@@ -389,7 +389,7 @@
* Returns the CDMA ERI text for particular subId,
* @param subId user preferred subId.
*/
- String getCdmaEriTextUsingSubId(long subId);
+ String getCdmaEriTextForSubscriber(long subId);
/**
* Returns true if OTA service provisioning needs to run.
@@ -408,7 +408,7 @@
* @param subId user preferred subId.
* Returns the unread count of voicemails
*/
- int getVoiceMessageCountUsingSubId(long subId);
+ int getVoiceMessageCountForSubscriber(long subId);
/**
* Returns the network type for data transmission
@@ -420,7 +420,7 @@
* @param subId user preferred subId.
* Returns the network type
*/
- int getNetworkTypeUsingSubId(long subId);
+ int getNetworkTypeForSubscriber(long subId);
/**
* Returns the network type for data transmission
@@ -432,7 +432,7 @@
* @param subId user preferred subId.
* Returns the network type
*/
- int getDataNetworkTypeUsingSubId(long subId);
+ int getDataNetworkTypeForSubscriber(long subId);
/**
* Returns the network type for voice
@@ -444,7 +444,7 @@
* @param subId user preferred subId.
* Returns the network type
*/
- int getVoiceNetworkTypeUsingSubId(long subId);
+ int getVoiceNetworkTypeForSubscriber(long subId);
/**
* Return true if an ICC card is present
@@ -476,7 +476,7 @@
* @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
* or {@link PHone#LTE_ON_CDMA_TRUE}
*/
- int getLteOnCdmaModeUsingSubId(long subId);
+ int getLteOnCdmaModeForSubscriber(long subId);
/**
* Returns the all observed cell information of the device.
@@ -709,33 +709,34 @@
List<String> getCarrierPackageNamesForIntent(in Intent intent);
/**
- * Set whether Android should display a simplified Mobile Network Settings UI.
- * The setting won't be persisted during power cycle.
+ * Set whether Android should display a simplified Mobile Network Settings UI
+ * for the current ICCID.
*
* @param subId for which the simplified UI should be enabled or disabled.
* @param enable true means enabling the simplified UI.
*/
- void enableSimplifiedNetworkSettings(long subId, boolean enable);
+ void enableSimplifiedNetworkSettingsForSubscriber(long subId, boolean enable);
/**
- * Get whether a simplified Mobile Network Settings UI is enabled.
+ * Get whether a simplified Mobile Network Settings UI is enabled for the
+ * current ICCID.
*
* @param subId for which the simplified UI should be enabled or disabled.
* @return true if the simplified UI is enabled.
*/
- boolean getSimplifiedNetworkSettingsEnabled(long subId);
+ boolean getSimplifiedNetworkSettingsEnabledForSubscriber(long subId);
/**
- * Set the phone number string and its alphatag for line 1 for display
- * purpose only, for example, displayed in Phone Status. It won't change
- * the actual MSISDN/MDN. This setting won't be persisted during power cycle
- * and it should be set again after reboot.
+ * Set the line 1 phone number string and its alphatag for the current ICCID
+ * for display purpose only, for example, displayed in Phone Status. It won't
+ * change the actual MSISDN/MDN. To unset alphatag or number, pass in a null
+ * value.
*
* @param subId the subscriber that the alphatag and dialing number belongs to.
* @param alphaTag alpha-tagging of the dailing nubmer
* @param number The dialing number
*/
- void setLine1NumberForDisplay(long subId, String alphaTag, String number);
+ void setLine1NumberForDisplayForSubscriber(long subId, String alphaTag, String number);
/**
* Returns the displayed dialing number string if it was set previously via
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index fd2d1c7..d776833 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -30,30 +30,30 @@
interface ITelephonyRegistry {
void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);
- void listenUsingSubId(in long subId, String pkg, IPhoneStateListener callback, int events,
+ void listenForSubscriber(in long subId, String pkg, IPhoneStateListener callback, int events,
boolean notifyNow);
void notifyCallState(int state, String incomingNumber);
- void notifyCallStateUsingSubId(in long subId, int state, String incomingNumber);
+ void notifyCallStateForSubscriber(in long subId, int state, String incomingNumber);
void notifyServiceState(in ServiceState state);
- void notifyServiceStateUsingSubId(in long subId, in ServiceState state);
+ void notifyServiceStateForSubscriber(in long subId, in ServiceState state);
void notifySignalStrength(in SignalStrength signalStrength);
- void notifySignalStrengthUsingSubId(in long subId, in SignalStrength signalStrength);
+ void notifySignalStrengthForSubscriber(in long subId, in SignalStrength signalStrength);
void notifyMessageWaitingChanged(boolean mwi);
- void notifyMessageWaitingChangedUsingSubId(in long subId, boolean mwi);
+ void notifyMessageWaitingChangedForSubscriber(in long subId, boolean mwi);
void notifyCallForwardingChanged(boolean cfi);
- void notifyCallForwardingChangedUsingSubId(in long subId, boolean cfi);
+ void notifyCallForwardingChangedForSubscriber(in long subId, boolean cfi);
void notifyDataActivity(int state);
- void notifyDataActivityUsingSubId(in long subId, int state);
+ void notifyDataActivityForSubscriber(in long subId, int state);
void notifyDataConnection(int state, boolean isDataConnectivityPossible,
String reason, String apn, String apnType, in LinkProperties linkProperties,
in NetworkCapabilities networkCapabilities, int networkType, boolean roaming);
- void notifyDataConnectionUsingSubId(long subId, int state, boolean isDataConnectivityPossible,
+ void notifyDataConnectionForSubscriber(long subId, int state, boolean isDataConnectivityPossible,
String reason, String apn, String apnType, in LinkProperties linkProperties,
in NetworkCapabilities networkCapabilities, int networkType, boolean roaming);
void notifyDataConnectionFailed(String reason, String apnType);
- void notifyDataConnectionFailedUsingSubId(long subId, String reason, String apnType);
+ void notifyDataConnectionFailedForSubscriber(long subId, String reason, String apnType);
void notifyCellLocation(in Bundle cellLocation);
- void notifyCellLocationUsingSubId(in long subId, in Bundle cellLocation);
+ void notifyCellLocationForSubscriber(in long subId, in Bundle cellLocation);
void notifyOtaspChanged(in int otaspMode);
void notifyCellInfo(in List<CellInfo> cellInfo);
void notifyPreciseCallState(int ringingCallState, int foregroundCallState,
@@ -61,7 +61,7 @@
void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause);
void notifyPreciseDataConnectionFailed(String reason, String apnType, String apn,
String failCause);
- void notifyCellInfoUsingSubId(in long subId, in List<CellInfo> cellInfo);
+ void notifyCellInfoForSubscriber(in long subId, in List<CellInfo> cellInfo);
void notifyDataConnectionRealTimeInfo(in DataConnectionRealTimeInfo dcRtInfo);
void notifyVoLteServiceStateChanged(in VoLteServiceState lteState);
}
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 34992b8..c89208d 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -124,7 +124,7 @@
static final String PROPERTY_ECM_EXIT_TIMER = "ro.cdma.ecmexittimer";
/** the international dialing prefix of current operator network */
- static final String PROPERTY_OPERATOR_IDP_STRING = "telephony.operator.idpstring";
+ static final String PROPERTY_OPERATOR_IDP_STRING = "gsm.operator.idpstring";
/**
* Defines the schema for the carrier specified OTASP number
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 5a4e0eb..afe1d5d 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -790,24 +790,6 @@
/**
* @hide
*/
- @Override
- public void addCrossProfileIntentsForPackage(String packageName, int sourceUserId,
- int targetUserId) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * @hide
- */
- @Override
- public void removeCrossProfileIntentsForPackage(String packageName, int sourceUserId,
- int targetUserId) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * @hide
- */
public Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) {
throw new UnsupportedOperationException();
}
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index 44787e7..6837d22 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -73,7 +73,7 @@
Intent intent = new Intent(ActivityTestMain.this, SpamActivity.class);
Bundle options = null;
if (fg) {
- ActivityOptions opts = ActivityOptions.makeLaunchTaskBehindAnimation();
+ ActivityOptions opts = ActivityOptions.makeTaskLaunchBehind();
options = opts.toBundle();
}
startActivity(intent, options);
diff --git a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
index 5bf59c7..a2e9117 100644
--- a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
+++ b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
@@ -208,6 +208,12 @@
Log.d(TAG, "Found process " + app.processName);
return true;
}
+ for (String relatedPackage : app.pkgList) {
+ if (relatedPackage.equalsIgnoreCase(processName)) {
+ Log.d(TAG, "Found process " + app.processName);
+ return true;
+ }
+ }
}
Log.d(TAG, "Failed to find process " + processName + " with package name "
+ packageName);
diff --git a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java
index a68e04e..9df11fe 100644
--- a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java
+++ b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java
@@ -29,6 +29,7 @@
import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;
+import android.widget.Toast;
import com.android.demo.jobSchedulerApp.MainActivity;
@@ -84,12 +85,15 @@
currentId++;
jobParamsMap.put(currentId, params);
final int currId = this.currentId;
- Log.d(TAG, "putting :" + currId + " for " + params.toString());
- Log.d(TAG, " pulled: " + jobParamsMap.get(currId));
if (mActivity != null) {
mActivity.onReceivedStartJob(params);
}
+ Toast.makeText(
+ this, "On start job: '" + params.getJobId() + "' deadline exceeded: " +
+ params.isOverrideDeadlineExpired(),
+ Toast.LENGTH_LONG).show();
+
return true;
}
@@ -100,7 +104,7 @@
int ind = jobParamsMap.indexOfValue(params);
jobParamsMap.remove(ind);
mActivity.onReceivedStopJob();
- return true;
+ return false; // no reschedule
}
static int currentId = 0;
@@ -129,6 +133,7 @@
return false;
} else {
jobFinished(params, false);
+ jobParamsMap.removeAt(0);
return true;
}
}
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
index bbf1a17..f94ecba1 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
@@ -28,7 +28,8 @@
l-5.046875,0.0 0.0-1.0Z" />
<path
android:name="two"
- android:fillColor="#00ffff00"
+ android:fillColor="#ffff00"
+ android:fillAlpha="0"
android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0-5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375
q 1.1718752-1.1875 1.4687502-1.53125 0.578125-0.625 0.796875-1.0625
q 0.234375-0.453125 0.234375-0.875 0.0-0.703125-0.5-1.140625
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml
index 1aad7430..3f79968 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml
@@ -21,10 +21,12 @@
<group>
<path
- android:fillColor="#E6000000"
+ android:fillColor="#FF000000"
+ android:fillAlpha="0.9"
android:pathData="M11.994999,2.0C6.4679985,2.0 2.0,6.4780006 2.0,12.0s4.468,10.0 9.995,10.0S22.0,17.522 22.0,12.0S17.521,2.0 11.994999,2.0zM12.0,20.0c-4.42,0.0 -8.0,-3.582 -8.0,-8.0s3.58,-8.0 8.0,-8.0s8.0,3.582 8.0,8.0S16.419998,20.0 12.0,20.0z" />
<path
- android:fillColor="#E6000000"
+ android:fillColor="#FF000000"
+ android:fillAlpha="0.9"
android:pathData="M12.5,6.0l-1.5,0.0 0.0,7.0 5.3029995,3.1819992 0.75,-1.249999 -4.5529995,-2.7320004z" />
</group>
diff --git a/tests/WallpaperTest/Android.mk b/tests/WallpaperTest/Android.mk
new file mode 100644
index 0000000..b4259cd
--- /dev/null
+++ b/tests/WallpaperTest/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := WallpaperTest
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+include $(BUILD_PACKAGE)
+
diff --git a/tests/WallpaperTest/AndroidManifest.xml b/tests/WallpaperTest/AndroidManifest.xml
new file mode 100644
index 0000000..4c914dd
--- /dev/null
+++ b/tests/WallpaperTest/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.wallpapertest" >
+
+ <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
+
+ <application
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <service
+ android:label="@string/test_wallpaper"
+ android:name=".TestWallpaper"
+ android:permission="android.permission.BIND_WALLPAPER"
+ android:enabled="true">
+ <intent-filter>
+ <action android:name="android.service.wallpaper.WallpaperService" />
+ </intent-filter>
+ <meta-data android:name="android.service.wallpaper"
+ android:resource="@xml/test_wallpaper" />
+ </service>
+ </application>
+</manifest>
diff --git a/tests/WallpaperTest/res/drawable-hdpi/test_wallpaper_thumb.png b/tests/WallpaperTest/res/drawable-hdpi/test_wallpaper_thumb.png
new file mode 100644
index 0000000..df92eb5
--- /dev/null
+++ b/tests/WallpaperTest/res/drawable-hdpi/test_wallpaper_thumb.png
Binary files differ
diff --git a/tests/WallpaperTest/res/layout/activity_main.xml b/tests/WallpaperTest/res/layout/activity_main.xml
new file mode 100644
index 0000000..d968396
--- /dev/null
+++ b/tests/WallpaperTest/res/layout/activity_main.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/window_background">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/dimens"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/width"/>
+ <EditText
+ android:id="@+id/dimen_width"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="numberDecimal"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/height"/>
+ <EditText
+ android:id="@+id/dimen_height"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="numberDecimal"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/wallpaper_offset"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/x"/>
+ <EditText
+ android:id="@+id/walloff_x"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="numberDecimal"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/y"/>
+ <EditText
+ android:id="@+id/walloff_y"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="numberDecimal"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/padding"/>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/left"/>
+ <EditText
+ android:id="@+id/padding_left"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="number"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/right"/>
+ <EditText
+ android:id="@+id/padding_right"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="number"/>
+ </LinearLayout>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/top"/>
+ <EditText
+ android:id="@+id/padding_top"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="number"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/bottom"/>
+ <EditText
+ android:id="@+id/padding_bottom"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="number"/>
+ </LinearLayout>
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/display_offset"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/x"/>
+ <EditText
+ android:id="@+id/dispoff_x"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="numberSigned"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/y"/>
+ <EditText
+ android:id="@+id/dispoff_y"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="numberSigned"/>
+ </LinearLayout>
+ </LinearLayout>
+</ScrollView>
diff --git a/tests/WallpaperTest/res/values-v11/styles.xml b/tests/WallpaperTest/res/values-v11/styles.xml
new file mode 100644
index 0000000..95000b2
--- /dev/null
+++ b/tests/WallpaperTest/res/values-v11/styles.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2013 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.
+-->
+
+<resources>
+
+ <!--
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Wallpaper">
+ <!-- API 11 theme customizations can go here. -->
+ </style>
+
+</resources>
\ No newline at end of file
diff --git a/tests/WallpaperTest/res/values-v21/styles.xml b/tests/WallpaperTest/res/values-v21/styles.xml
new file mode 100644
index 0000000..e42d526
--- /dev/null
+++ b/tests/WallpaperTest/res/values-v21/styles.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2013 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.
+-->
+
+<resources>
+
+ <!--
+ Base application theme for API 21+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Material.Wallpaper">
+ <!-- API 14 theme customizations can go here. -->
+ </style>
+
+</resources>
\ No newline at end of file
diff --git a/tests/WallpaperTest/res/values/colors.xml b/tests/WallpaperTest/res/values/colors.xml
new file mode 100644
index 0000000..8c08249
--- /dev/null
+++ b/tests/WallpaperTest/res/values/colors.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+<resources>
+ <color name="window_background">#80000000</color>
+</resources>
\ No newline at end of file
diff --git a/tests/WallpaperTest/res/values/strings.xml b/tests/WallpaperTest/res/values/strings.xml
new file mode 100644
index 0000000..fd21259
--- /dev/null
+++ b/tests/WallpaperTest/res/values/strings.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 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.
+-->
+
+<resources>
+ <string name="app_name">Wallpaper Test</string>
+
+ <string name="test_wallpaper">Test Wallpaper</string>
+ <string name="test_wallpaper_author">Google</string>
+ <string name="test_wallpaper_desc">
+ Test wallpaper for use with the wallpaper test app.
+ </string>
+
+ <string name="dimens">Dimens: </string>
+ <string name="width">Width: </string>
+ <string name="height">Height: </string>
+
+ <string name="wallpaper_offset">Wall off: </string>
+ <string name="x">X: </string>
+ <string name="y">Y: </string>
+
+ <string name="padding">Padding: </string>
+ <string name="left">Left: </string>
+ <string name="right">Right: </string>
+ <string name="top">Top: </string>
+ <string name="bottom">Bottom: </string>
+
+ <string name="display_offset">Disp off: </string>
+</resources>
diff --git a/tests/WallpaperTest/res/values/styles.xml b/tests/WallpaperTest/res/values/styles.xml
new file mode 100644
index 0000000..d2b91d6
--- /dev/null
+++ b/tests/WallpaperTest/res/values/styles.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2013 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.
+-->
+
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Wallpaper">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
\ No newline at end of file
diff --git a/tests/WallpaperTest/res/xml/test_wallpaper.xml b/tests/WallpaperTest/res/xml/test_wallpaper.xml
new file mode 100644
index 0000000..9f7d714b
--- /dev/null
+++ b/tests/WallpaperTest/res/xml/test_wallpaper.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2008, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+
+<!-- The attributes in this XML file provide configuration information -->
+<!-- about the polar clock. -->
+
+<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
+ android:author="@string/test_wallpaper_author"
+ android:description="@string/test_wallpaper_desc"
+ android:thumbnail="@drawable/test_wallpaper_thumb" />
diff --git a/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java b/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java
new file mode 100644
index 0000000..7880f67
--- /dev/null
+++ b/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 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.example.wallpapertest;
+
+import android.app.Activity;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+public class MainActivity extends Activity {
+ private static final String TAG = "MainActivity";
+
+ WallpaperManager mWallpaperManager;
+ WindowManager mWindowManager;
+
+ TextView mDimenWidthView;
+ TextView mDimenHeightView;
+
+ TextView mWallOffXView;
+ TextView mWallOffYView;
+
+ TextView mPaddingLeftView;
+ TextView mPaddingRightView;
+ TextView mPaddingTopView;
+ TextView mPaddingBottomView;
+
+ TextView mDispOffXView;
+ TextView mDispOffYView;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ mWallpaperManager = (WallpaperManager)getSystemService(Context.WALLPAPER_SERVICE);
+ mWindowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
+
+ mDimenWidthView = (TextView) findViewById(R.id.dimen_width);
+ mDimenWidthView.addTextChangedListener(mTextWatcher);
+ mDimenHeightView = (TextView) findViewById(R.id.dimen_height);
+ mDimenHeightView.addTextChangedListener(mTextWatcher);
+
+ mWallOffXView = (TextView) findViewById(R.id.walloff_x);
+ mWallOffXView.addTextChangedListener(mTextWatcher);
+ mWallOffYView = (TextView) findViewById(R.id.walloff_y);
+ mWallOffYView.addTextChangedListener(mTextWatcher);
+
+ mPaddingLeftView = (TextView) findViewById(R.id.padding_left);
+ mPaddingLeftView.addTextChangedListener(mTextWatcher);
+ mPaddingRightView = (TextView) findViewById(R.id.padding_right);
+ mPaddingRightView.addTextChangedListener(mTextWatcher);
+ mPaddingTopView = (TextView) findViewById(R.id.padding_top);
+ mPaddingTopView.addTextChangedListener(mTextWatcher);
+ mPaddingBottomView = (TextView) findViewById(R.id.padding_bottom);
+ mPaddingBottomView.addTextChangedListener(mTextWatcher);
+
+ mDispOffXView = (TextView) findViewById(R.id.dispoff_x);
+ mDispOffXView.addTextChangedListener(mTextWatcher);
+ mDispOffYView = (TextView) findViewById(R.id.dispoff_y);
+ mDispOffYView.addTextChangedListener(mTextWatcher);
+
+ updateDimens();
+ updateWallOff();
+ updatePadding();
+ updateDispOff();
+ }
+
+ private int loadPropIntText(TextView view, int baseVal) {
+ String str = view.getText().toString();
+ if (str != null && !TextUtils.isEmpty(str)) {
+ try {
+ float fval = Float.parseFloat(str);
+ return (int)(fval*baseVal);
+ } catch (NumberFormatException e) {
+ Log.i(TAG, "Bad number: " + str, e);
+ }
+ }
+ return baseVal;
+ }
+
+ private float loadFloatText(TextView view) {
+ String str = view.getText().toString();
+ if (str != null && !TextUtils.isEmpty(str)) {
+ try {
+ return Float.parseFloat(str);
+ } catch (NumberFormatException e) {
+ Log.i(TAG, "Bad number: " + str, e);
+ }
+ }
+ return 0;
+ }
+
+ private int loadIntText(TextView view) {
+ String str = view.getText().toString();
+ if (str != null && !TextUtils.isEmpty(str)) {
+ try {
+ return Integer.parseInt(str);
+ } catch (NumberFormatException e) {
+ Log.i(TAG, "Bad number: " + str, e);
+ }
+ }
+ return 0;
+ }
+
+ public void updateDimens() {
+ Point minDims = new Point();
+ Point maxDims = new Point();
+ mWindowManager.getDefaultDisplay().getCurrentSizeRange(minDims, maxDims);
+ mWallpaperManager.suggestDesiredDimensions(
+ loadPropIntText(mDimenWidthView, maxDims.x),
+ loadPropIntText(mDimenHeightView, maxDims.y));
+ }
+
+ public void updateWallOff() {
+ IBinder token = getWindow().getDecorView().getWindowToken();
+ if (token != null) {
+ mWallpaperManager.setWallpaperOffsets(token, loadFloatText(mWallOffXView),
+ loadFloatText(mWallOffYView));
+ }
+ }
+
+ public void updatePadding() {
+ Rect padding = new Rect();
+ padding.left = loadIntText(mPaddingLeftView);
+ padding.top = loadIntText(mPaddingTopView);
+ padding.right = loadIntText(mPaddingRightView);
+ padding.bottom = loadIntText(mPaddingBottomView);
+ mWallpaperManager.setDisplayPadding(padding);
+ }
+
+ public void updateDispOff() {
+ IBinder token = getWindow().getDecorView().getWindowToken();
+ if (token != null) {
+ mWallpaperManager.setDisplayOffset(token, loadIntText(mDispOffXView),
+ loadIntText(mDispOffYView));
+ }
+ }
+
+ final TextWatcher mTextWatcher = new TextWatcher() {
+ @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override public void onTextChanged(CharSequence s, int start, int before, int count) {
+ updateDimens();
+ updateWallOff();
+ updatePadding();
+ updateDispOff();
+ }
+
+ @Override public void afterTextChanged(Editable s) {
+ }
+ };
+}
diff --git a/tests/WallpaperTest/src/com/example/wallpapertest/TestWallpaper.java b/tests/WallpaperTest/src/com/example/wallpapertest/TestWallpaper.java
new file mode 100644
index 0000000..95db6d1
--- /dev/null
+++ b/tests/WallpaperTest/src/com/example/wallpapertest/TestWallpaper.java
@@ -0,0 +1,251 @@
+/*
+ * 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.example.wallpapertest;
+
+import android.service.wallpaper.WallpaperService;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.Paint;
+import android.graphics.Color;
+import android.graphics.RectF;
+import android.text.TextPaint;
+import android.view.SurfaceHolder;
+import android.content.res.XmlResourceParser;
+
+import android.os.Handler;
+import android.util.Log;
+
+import android.view.WindowInsets;
+
+public class TestWallpaper extends WallpaperService {
+ private static final String LOG_TAG = "PolarClock";
+
+ private final Handler mHandler = new Handler();
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ }
+
+ public Engine onCreateEngine() {
+ return new ClockEngine();
+ }
+
+ class ClockEngine extends Engine {
+ private static final int OUTER_COLOR = 0xffff0000;
+ private static final int INNER_COLOR = 0xff000080;
+ private static final int STABLE_COLOR = 0xa000ff00;
+ private static final int TEXT_COLOR = 0xa0ffffff;
+
+ private final Paint.FontMetrics mTextMetrics = new Paint.FontMetrics();
+
+ private int mPadding;
+
+ private final Rect mMainInsets = new Rect();
+ private final Rect mStableInsets = new Rect();
+ private boolean mRound = false;
+
+ private int mDesiredWidth;
+ private int mDesiredHeight;
+
+ private float mOffsetX;
+ private float mOffsetY;
+ private float mOffsetXStep;
+ private float mOffsetYStep;
+ private int mOffsetXPixels;
+ private int mOffsetYPixels;
+
+ private final Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final Paint mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final TextPaint mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
+
+ private final Runnable mDrawClock = new Runnable() {
+ public void run() {
+ drawFrame();
+ }
+ };
+ private boolean mVisible;
+
+ ClockEngine() {
+ }
+
+ @Override
+ public void onCreate(SurfaceHolder surfaceHolder) {
+ super.onCreate(surfaceHolder);
+
+ mDesiredWidth = getDesiredMinimumWidth();
+ mDesiredHeight = getDesiredMinimumHeight();
+
+ Paint paint = mFillPaint;
+ paint.setStyle(Paint.Style.FILL);
+
+ paint = mStrokePaint;
+ paint.setStrokeWidth(3);
+ paint.setStrokeCap(Paint.Cap.ROUND);
+ paint.setStyle(Paint.Style.STROKE);
+
+ TextPaint tpaint = mTextPaint;
+ tpaint.density = getResources().getDisplayMetrics().density;
+ tpaint.setCompatibilityScaling(getResources().getCompatibilityInfo().applicationScale);
+ tpaint.setColor(TEXT_COLOR);
+ tpaint.setTextSize(18 * getResources().getDisplayMetrics().scaledDensity);
+ tpaint.setShadowLayer(4 * getResources().getDisplayMetrics().density, 0, 0, 0xff000000);
+
+ mTextPaint.getFontMetrics(mTextMetrics);
+
+ mPadding = (int)(16 * getResources().getDisplayMetrics().density);
+
+ if (isPreview()) {
+ mOffsetX = 0.5f;
+ mOffsetY = 0.5f;
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mHandler.removeCallbacks(mDrawClock);
+ }
+
+ @Override
+ public void onVisibilityChanged(boolean visible) {
+ mVisible = visible;
+ if (!visible) {
+ mHandler.removeCallbacks(mDrawClock);
+ }
+ drawFrame();
+ }
+
+ @Override
+ public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ super.onSurfaceChanged(holder, format, width, height);
+ drawFrame();
+ }
+
+ @Override
+ public void onSurfaceCreated(SurfaceHolder holder) {
+ super.onSurfaceCreated(holder);
+ }
+
+ @Override
+ public void onSurfaceDestroyed(SurfaceHolder holder) {
+ super.onSurfaceDestroyed(holder);
+ mVisible = false;
+ mHandler.removeCallbacks(mDrawClock);
+ }
+
+ @Override
+ public void onApplyWindowInsets(WindowInsets insets) {
+ super.onApplyWindowInsets(insets);
+ mMainInsets.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
+ insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
+ mStableInsets.set(insets.getStableInsetLeft(), insets.getStableInsetTop(),
+ insets.getStableInsetRight(), insets.getStableInsetBottom());
+ mRound = insets.isRound();
+ drawFrame();
+ }
+
+ @Override
+ public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {
+ super.onDesiredSizeChanged(desiredWidth, desiredHeight);
+ mDesiredWidth = desiredWidth;
+ mDesiredHeight = desiredHeight;
+ drawFrame();
+ }
+
+ @Override
+ public void onOffsetsChanged(float xOffset, float yOffset,
+ float xStep, float yStep, int xPixels, int yPixels) {
+ super.onOffsetsChanged(xOffset, yOffset, xStep, yStep, xPixels, yPixels);
+
+ if (isPreview()) return;
+
+ mOffsetX = xOffset;
+ mOffsetY = yOffset;
+ mOffsetXStep = xStep;
+ mOffsetYStep = yStep;
+ mOffsetXPixels = xPixels;
+ mOffsetYPixels = yPixels;
+
+ drawFrame();
+ }
+
+ void drawFrame() {
+ final SurfaceHolder holder = getSurfaceHolder();
+ final Rect frame = holder.getSurfaceFrame();
+ final int width = frame.width();
+ final int height = frame.height();
+
+ Canvas c = null;
+ try {
+ c = holder.lockCanvas();
+ if (c != null) {
+ final Paint paint = mFillPaint;
+
+ paint.setColor(OUTER_COLOR);
+ c.drawRect(0, 0, width, height, paint);
+
+ paint.setColor(INNER_COLOR);
+ c.drawRect(0+mMainInsets.left, 0+mMainInsets.top,
+ width-mMainInsets.right, height-mMainInsets.bottom, paint);
+
+ mStrokePaint.setColor(STABLE_COLOR);
+ c.drawRect(0 + mStableInsets.left, 0 + mStableInsets.top,
+ width - mStableInsets.right, height - mStableInsets.bottom,
+ mStrokePaint);
+
+ final int ascdesc = (int)(-mTextMetrics.ascent + mTextMetrics.descent);
+ final int linegap = (int)(-mTextMetrics.ascent + mTextMetrics.descent
+ + mTextMetrics.leading);
+
+ int x = mStableInsets.left + mPadding;
+ int y = height - mStableInsets.bottom - mPadding - ascdesc;
+ c.drawText("Surface Size: " + width + " x " + height,
+ x, y, mTextPaint);
+ y -= linegap;
+ c.drawText("Desired Size: " + mDesiredWidth + " x " + mDesiredHeight,
+ x, y, mTextPaint);
+ y -= linegap;
+ c.drawText("Cur Offset Raw: " + mOffsetX + ", " + mOffsetY,
+ x, y, mTextPaint);
+ y -= linegap;
+ c.drawText("Cur Offset Step: " + mOffsetXStep + ", " + mOffsetYStep,
+ x, y, mTextPaint);
+ y -= linegap;
+ c.drawText("Cur Offset Pixels: " + mOffsetXPixels + ", " + mOffsetYPixels,
+ x, y, mTextPaint);
+ y -= linegap;
+ c.drawText("Stable Insets: (" + mStableInsets.left + ", " + mStableInsets.top
+ + ") - (" + mStableInsets.right + ", " + mStableInsets.bottom + ")",
+ x, y, mTextPaint);
+ y -= linegap;
+ c.drawText("System Insets: (" + mMainInsets.left + ", " + mMainInsets.top
+ + ") - (" + mMainInsets.right + ", " + mMainInsets.bottom + ")",
+ x, y, mTextPaint);
+
+ }
+ } finally {
+ if (c != null) holder.unlockCanvasAndPost(c);
+ }
+ }
+ }
+}
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 27e60f3..41d8502 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -2390,7 +2390,8 @@
char* packageString = strtok(libs.lockBuffer(libs.length()), ":");
while (packageString != NULL) {
// Write the R.java file out with the correct package name
- err = writeResourceSymbols(bundle, assets, String8(packageString), true, false);
+ err = writeResourceSymbols(bundle, assets, String8(packageString), true,
+ bundle->getBuildSharedLibrary());
if (err < 0) {
goto bail;
}
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 5deeca2..afec5ed 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -1926,110 +1926,75 @@
return String16();
}
-static void writeResourceLoadedCallback(FILE* fp, int indent) {
- IndentPrinter p(fp, 4);
- p.indent(indent);
- p.println("private static void rewriteIntArrayField(java.lang.reflect.Field field, int packageId) throws IllegalAccessException {");
- {
- p.indent();
- p.println("int requiredModifiers = java.lang.reflect.Modifier.STATIC | java.lang.reflect.Modifier.PUBLIC;");
- p.println("if ((field.getModifiers() & requiredModifiers) != requiredModifiers) {");
- {
- p.indent();
- p.println("throw new IllegalArgumentException(\"Field \" + field.getName() + \" is not rewritable\");");
- p.indent(-1);
- }
- p.println("}");
- p.println("if (field.getType() != int[].class) {");
- {
- p.indent();
- p.println("throw new IllegalArgumentException(\"Field \" + field.getName() + \" is not an int array\");");
- p.indent(-1);
- }
- p.println("}");
- p.println("int[] array = (int[]) field.get(null);");
- p.println("for (int i = 0; i < array.length; i++) {");
- {
- p.indent();
- p.println("array[i] = (array[i] & 0x00ffffff) | (packageId << 24);");
- p.indent(-1);
- }
- p.println("}");
- p.indent(-1);
+static status_t writeResourceLoadedCallbackForLayoutClasses(
+ FILE* fp, const sp<AaptAssets>& assets,
+ const sp<AaptSymbols>& symbols, int indent, bool includePrivate)
+{
+ String16 attr16("attr");
+ String16 package16(assets->getPackage());
+
+ const char* indentStr = getIndentSpace(indent);
+ bool hasErrors = false;
+
+ size_t i;
+ size_t N = symbols->getNestedSymbols().size();
+ for (i=0; i<N; i++) {
+ sp<AaptSymbols> nsymbols = symbols->getNestedSymbols().valueAt(i);
+ String8 realClassName(symbols->getNestedSymbols().keyAt(i));
+ String8 nclassName(flattenSymbol(realClassName));
+
+ fprintf(fp,
+ "%sfor(int i = 0; i < styleable.%s.length; ++i) {\n"
+ "%sstyleable.%s[i] = (styleable.%s[i] & 0x00ffffff) | (packageId << 24);\n"
+ "%s}\n",
+ indentStr, nclassName.string(),
+ getIndentSpace(indent+1), nclassName.string(), nclassName.string(),
+ indentStr);
}
- p.println("}");
- p.println();
- p.println("private static void rewriteIntField(java.lang.reflect.Field field, int packageId) throws IllegalAccessException {");
- {
- p.indent();
- p.println("int requiredModifiers = java.lang.reflect.Modifier.STATIC | java.lang.reflect.Modifier.PUBLIC;");
- p.println("int bannedModifiers = java.lang.reflect.Modifier.FINAL;");
- p.println("int mod = field.getModifiers();");
- p.println("if ((mod & requiredModifiers) != requiredModifiers || (mod & bannedModifiers) != 0) {");
- {
- p.indent();
- p.println("throw new IllegalArgumentException(\"Field \" + field.getName() + \" is not rewritable\");");
- p.indent(-1);
+
+ return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
+}
+
+static status_t writeResourceLoadedCallback(
+ FILE* fp, const sp<AaptAssets>& assets, bool includePrivate,
+ const sp<AaptSymbols>& symbols, const String8& className, int indent)
+{
+ size_t i;
+ status_t err = NO_ERROR;
+
+ size_t N = symbols->getSymbols().size();
+ for (i=0; i<N; i++) {
+ const AaptSymbolEntry& sym = symbols->getSymbols().valueAt(i);
+ if (sym.typeCode == AaptSymbolEntry::TYPE_UNKNOWN) {
+ continue;
}
- p.println("}");
- p.println("if (field.getType() != int.class && field.getType() != Integer.class) {");
- {
- p.indent();
- p.println("throw new IllegalArgumentException(\"Field \" + field.getName() + \" is not an int\");");
- p.indent(-1);
+ if (!assets->isJavaSymbol(sym, includePrivate)) {
+ continue;
}
- p.println("}");
- p.println("int resId = field.getInt(null);");
- p.println("field.setInt(null, (resId & 0x00ffffff) | (packageId << 24));");
- p.indent(-1);
+ String8 flat_name(flattenSymbol(sym.name));
+ fprintf(fp,
+ "%s%s.%s = (%s.%s & 0x00ffffff) | (packageId << 24);\n",
+ getIndentSpace(indent), className.string(), flat_name.string(),
+ className.string(), flat_name.string());
}
- p.println("}");
- p.println();
- p.println("public static void onResourcesLoaded(int assignedPackageId) throws Exception {");
- {
- p.indent();
- p.println("Class<?>[] declaredClasses = R.class.getDeclaredClasses();");
- p.println("for (Class<?> clazz : declaredClasses) {");
- {
- p.indent();
- p.println("if (clazz.getSimpleName().equals(\"styleable\")) {");
- {
- p.indent();
- p.println("for (java.lang.reflect.Field field : clazz.getDeclaredFields()) {");
- {
- p.indent();
- p.println("if (field.getType() == int[].class) {");
- {
- p.indent();
- p.println("rewriteIntArrayField(field, assignedPackageId);");
- p.indent(-1);
- }
- p.println("}");
- p.indent(-1);
- }
- p.println("}");
- p.indent(-1);
- }
- p.println("} else {");
- {
- p.indent();
- p.println("for (java.lang.reflect.Field field : clazz.getDeclaredFields()) {");
- {
- p.indent();
- p.println("rewriteIntField(field, assignedPackageId);");
- p.indent(-1);
- }
- p.println("}");
- p.indent(-1);
- }
- p.println("}");
- p.indent(-1);
+
+ N = symbols->getNestedSymbols().size();
+ for (i=0; i<N; i++) {
+ sp<AaptSymbols> nsymbols = symbols->getNestedSymbols().valueAt(i);
+ String8 nclassName(symbols->getNestedSymbols().keyAt(i));
+ if (nclassName == "styleable") {
+ err = writeResourceLoadedCallbackForLayoutClasses(
+ fp, assets, nsymbols, indent, includePrivate);
+ } else {
+ err = writeResourceLoadedCallback(fp, assets, includePrivate, nsymbols,
+ nclassName, indent);
}
- p.println("}");
- p.indent(-1);
+ if (err != NO_ERROR) {
+ return err;
+ }
}
- p.println("}");
- p.println();
+
+ return NO_ERROR;
}
static status_t writeLayoutClasses(
@@ -2485,7 +2450,10 @@
}
if (emitCallback) {
- writeResourceLoadedCallback(fp, indent);
+ fprintf(fp, "%spublic static void onResourcesLoaded(int packageId) {\n",
+ getIndentSpace(indent));
+ writeResourceLoadedCallback(fp, assets, includePrivate, symbols, className, indent + 1);
+ fprintf(fp, "%s}\n", getIndentSpace(indent));
}
indent--;
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index b3c364b..8341de6 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2574,8 +2574,12 @@
continue;
}
const size_t N = t->getOrderedConfigs().size();
- sp<AaptSymbols> typeSymbols;
- typeSymbols = outSymbols->addNestedSymbol(String8(t->getName()), t->getPos());
+ sp<AaptSymbols> typeSymbols =
+ outSymbols->addNestedSymbol(String8(t->getName()), t->getPos());
+ if (typeSymbols == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
for (size_t ci=0; ci<N; ci++) {
sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
if (c == NULL) {
diff --git a/tools/layoutlib/.idea/codeStyleSettings.xml b/tools/layoutlib/.idea/codeStyleSettings.xml
index 33937b3..b324213 100644
--- a/tools/layoutlib/.idea/codeStyleSettings.xml
+++ b/tools/layoutlib/.idea/codeStyleSettings.xml
@@ -27,12 +27,12 @@
<package name="" withSubpackages="true" static="true" />
</value>
</option>
+ <option name="RIGHT_MARGIN" value="100" />
<option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="true" />
<option name="JD_ALIGN_PARAM_COMMENTS" value="false" />
<option name="JD_ADD_BLANK_AFTER_PARM_COMMENTS" value="true" />
<option name="JD_ADD_BLANK_AFTER_RETURN" value="true" />
<option name="JD_DO_NOT_WRAP_ONE_LINE_COMMENTS" value="true" />
- <option name="RIGHT_MARGIN" value="100" />
<option name="WRAP_COMMENTS" value="true" />
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index fbe21a8..aaba545 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -809,11 +809,6 @@
return new CharSequence[] { value };
}
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
- String.format(
- String.format("Unknown value for getTextArray(%d) => %s", //DEBUG
- index, mResourceData[index].getName())), null);
-
return null;
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index bd80cb8..bef5181 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -16,6 +16,8 @@
package android.graphics;
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
@@ -50,10 +52,12 @@
*/
public class FontFamily_Delegate {
+ public static final int DEFAULT_FONT_WEIGHT = 400;
+ public static final int BOLD_FONT_WEIGHT_DELTA = 300;
+ public static final int BOLD_FONT_WEIGHT = 700;
+
// FONT_SUFFIX_ITALIC will always match FONT_SUFFIX_BOLDITALIC and hence it must be checked
// separately.
- private static final String FONT_SUFFIX_BOLDITALIC = "BoldItalic.ttf";
- private static final String FONT_SUFFIX_BOLD = "Bold.ttf";
private static final String FONT_SUFFIX_ITALIC = "Italic.ttf";
private static final String FN_ALL_FONTS_LIST = "fontsInSdk.txt";
@@ -61,9 +65,10 @@
* A class associating {@link Font} with its metadata.
*/
private static final class FontInfo {
+ @Nullable
Font mFont;
- /** Regular, Bold, Italic, or BoldItalic. */
- int mStyle;
+ int mWeight;
+ boolean mIsItalic;
}
// ---- delegate manager ----
@@ -79,16 +84,18 @@
// ---- delegate data ----
private List<FontInfo> mFonts = new ArrayList<FontInfo>();
+
/**
* The variant of the Font Family - compact or elegant.
+ * <p/>
* 0 is unspecified, 1 is compact and 2 is elegant. This needs to be kept in sync with values in
* android.graphics.FontFamily
*
* @see Paint#setElegantTextHeight(boolean)
*/
private FontVariant mVariant;
- // Path of fonts that haven't been created since sFontLoader hasn't been initialized.
- private List<String> mPath = new ArrayList<String>();
+ // List of runnables to process fonts after sFontLoader is initialized.
+ private List<Runnable> mPostInitRunnables = new ArrayList<Runnable>();
/** @see #isValid() */
private boolean mValid = false;
@@ -139,27 +146,30 @@
sPostInitDelegate.clear();
}
- public Font getFont(int style) {
- FontInfo plainFont = null;
+ @Nullable
+ public Font getFont(int desiredWeight, boolean isItalic) {
+ FontInfo desiredStyle = new FontInfo();
+ desiredStyle.mWeight = desiredWeight;
+ desiredStyle.mIsItalic = isItalic;
+ FontInfo bestFont = null;
+ int bestMatch = Integer.MAX_VALUE;
for (FontInfo font : mFonts) {
- if (font.mStyle == style) {
- return font.mFont;
- }
- if (font.mStyle == Font.PLAIN && plainFont == null) {
- plainFont = font;
+ int match = computeMatch(font, desiredStyle);
+ if (match < bestMatch) {
+ bestMatch = match;
+ bestFont = font;
}
}
-
- // No font with the mentioned style is found. Try to derive one.
- if (plainFont != null && style > 0 && style < 4) {
- FontInfo styledFont = new FontInfo();
- styledFont.mFont = plainFont.mFont.deriveFont(style);
- styledFont.mStyle = style;
- // Add the font to the list of fonts so that we don't have to derive it the next time.
- mFonts.add(styledFont);
- return styledFont.mFont;
+ if (bestFont == null) {
+ return null;
}
- return null;
+ if (bestMatch == 0) {
+ return bestFont.mFont;
+ }
+ // Derive the font as required and add it to the list of Fonts.
+ deriveFont(bestFont, desiredStyle);
+ addFont(desiredStyle);
+ return desiredStyle.mFont;
}
public FontVariant getVariant() {
@@ -168,27 +178,14 @@
/**
* Returns if the FontFamily should contain any fonts. If this returns true and
- * {@link #getFont(int)} returns an empty list, it means that an error occurred while loading
- * the fonts. However, some fonts are deliberately skipped, for example they are not bundled
- * with the SDK. In such a case, this method returns false.
+ * {@link #getFont(int, boolean)} returns an empty list, it means that an error occurred while
+ * loading the fonts. However, some fonts are deliberately skipped, for example they are not
+ * bundled with the SDK. In such a case, this method returns false.
*/
public boolean isValid() {
return mValid;
}
- /*package*/ static int getFontStyle(String path) {
- int style = Font.PLAIN;
- String fontName = path.substring(path.lastIndexOf('/'));
- if (fontName.endsWith(FONT_SUFFIX_BOLDITALIC)) {
- style = Font.BOLD | Font.ITALIC;
- } else if (fontName.endsWith(FONT_SUFFIX_BOLD)) {
- style = Font.BOLD;
- } else if (fontName.endsWith(FONT_SUFFIX_ITALIC)) {
- style = Font.ITALIC;
- }
- return style;
- }
-
/*package*/ static Font loadFont(String path) {
if (path.startsWith(SYSTEM_FONTS) ) {
String relativePath = path.substring(SYSTEM_FONTS.length());
@@ -242,11 +239,16 @@
}
@LayoutlibDelegate
- /*package*/ static boolean nAddFont(long nativeFamily, String path) {
- FontFamily_Delegate delegate = getDelegate(nativeFamily);
+ /*package*/ static boolean nAddFont(long nativeFamily, final String path) {
+ final FontFamily_Delegate delegate = getDelegate(nativeFamily);
if (delegate != null) {
if (sFontLocation == null) {
- delegate.mPath.add(path);
+ delegate.mPostInitRunnables.add(new Runnable() {
+ @Override
+ public void run() {
+ delegate.addFont(path);
+ }
+ });
return true;
}
return delegate.addFont(path);
@@ -255,6 +257,25 @@
}
@LayoutlibDelegate
+ /*package*/ static boolean nAddFontWeightStyle(long nativeFamily, final String path,
+ final int weight, final boolean isItalic) {
+ final FontFamily_Delegate delegate = getDelegate(nativeFamily);
+ if (delegate != null) {
+ if (sFontLocation == null) {
+ delegate.mPostInitRunnables.add(new Runnable() {
+ @Override
+ public void run() {
+ delegate.addFont(path, weight, isItalic);
+ }
+ });
+ return true;
+ }
+ return delegate.addFont(path, weight, isItalic);
+ }
+ return false;
+ }
+
+ @LayoutlibDelegate
/*package*/ static boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr, String path) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"FontFamily.addFontFromAsset is not supported.", null, null);
@@ -265,15 +286,17 @@
// ---- private helper methods ----
private void init() {
- for (String path : mPath) {
- addFont(path);
+ for (Runnable postInitRunnable : mPostInitRunnables) {
+ postInitRunnable.run();
}
- mPath = null;
+ mPostInitRunnables = null;
}
- private boolean addFont(String path) {
- // If the font is not in the list of fonts bundled with the SDK, don't try to load it and
- // mark the FontFamily to be not valid.
+ private boolean addFont(@NonNull String path) {
+ return addFont(path, DEFAULT_FONT_WEIGHT, path.endsWith(FONT_SUFFIX_ITALIC));
+ }
+
+ private boolean addFont(@NonNull String path, int weight, boolean isItalic) {
if (path.startsWith(SYSTEM_FONTS) &&
!SDK_FONTS.contains(path.substring(SYSTEM_FONTS.length()))) {
return mValid = false;
@@ -286,9 +309,67 @@
}
FontInfo fontInfo = new FontInfo();
fontInfo.mFont = font;
- fontInfo.mStyle = getFontStyle(path);
- // TODO ensure that mFonts doesn't have the font with this style already.
+ fontInfo.mWeight = weight;
+ fontInfo.mIsItalic = isItalic;
+ addFont(fontInfo);
+ return true;
+ }
+
+ private boolean addFont(@NonNull FontInfo fontInfo) {
+ int weight = fontInfo.mWeight;
+ boolean isItalic = fontInfo.mIsItalic;
+ // The list is usually just two fonts big. So iterating over all isn't as bad as it looks.
+ // It's biggest for roboto where the size is 12.
+ for (FontInfo font : mFonts) {
+ if (font.mWeight == weight && font.mIsItalic == isItalic) {
+ return false;
+ }
+ }
mFonts.add(fontInfo);
return true;
}
+
+ /**
+ * Compute matching metric between two styles - 0 is an exact match.
+ */
+ private static int computeMatch(@NonNull FontInfo font1, @NonNull FontInfo font2) {
+ int score = Math.abs(font1.mWeight - font2.mWeight);
+ if (font1.mIsItalic != font2.mIsItalic) {
+ score += 200;
+ }
+ return score;
+ }
+
+ /**
+ * Try to derive a font from {@code srcFont} for the style in {@code outFont}.
+ * <p/>
+ * {@code outFont} is updated to reflect the style of the derived font.
+ * @param srcFont the source font
+ * @param outFont contains the desired font style. Updated to contain the derived font and
+ * its style
+ * @return outFont
+ */
+ @NonNull
+ private FontInfo deriveFont(@NonNull FontInfo srcFont, @NonNull FontInfo outFont) {
+ int desiredWeight = outFont.mWeight;
+ int srcWeight = srcFont.mWeight;
+ Font derivedFont = srcFont.mFont;
+ // Embolden the font if required.
+ if (desiredWeight >= BOLD_FONT_WEIGHT && desiredWeight - srcWeight > BOLD_FONT_WEIGHT_DELTA / 2) {
+ derivedFont = derivedFont.deriveFont(Font.BOLD);
+ srcWeight += BOLD_FONT_WEIGHT_DELTA;
+ }
+ // Italicize the font if required.
+ if (outFont.mIsItalic && !srcFont.mIsItalic) {
+ derivedFont = derivedFont.deriveFont(Font.ITALIC);
+ } else if (outFont.mIsItalic != srcFont.mIsItalic) {
+ // The desired font is plain, but the src font is italics. We can't convert it back. So
+ // we update the value to reflect the true style of the font we're deriving.
+ outFont.mIsItalic = srcFont.mIsItalic;
+ }
+ outFont.mFont = derivedFont;
+ outFont.mWeight = srcWeight;
+ // No need to update mIsItalics, as it's already been handled above.
+ return outFont;
+ }
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
index 832d0a3..14e9960 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
@@ -76,22 +76,19 @@
// ---- native methods ----
@LayoutlibDelegate
- /*package*/ static void nativeDestructor(long native_shader, long native_with_local_matrix) {
- // TODO: check what's native_with_local_matrix
+ /*package*/ static void nativeDestructor(long native_shader) {
sManager.removeJavaReferenceFor(native_shader);
}
@LayoutlibDelegate
- /*package*/ static long nativeSetLocalMatrix(long native_shader,
- long native_with_local_matrix, long matrix_instance) {
+ /*package*/ static void nativeSetLocalMatrix(long native_shader, long matrix_instance) {
// get the delegate from the native int.
Shader_Delegate shaderDelegate = sManager.getDelegate(native_shader);
if (shaderDelegate == null) {
- return 0;
+ return;
}
shaderDelegate.mLocalMatrix = Matrix_Delegate.getDelegate(matrix_instance);
- return 0;
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 72fe61c..276e134 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -55,8 +55,9 @@
@NonNull
private final FontFamily_Delegate[] mFontFamilies; // the reference to FontFamily_Delegate.
- /** @see FontFamily_Delegate.FontInfo#mStyle */
+ /** @see Font#getStyle() */
private final int mStyle;
+ private final int mWeight;
private static long sDefaultTypeface;
@@ -84,11 +85,18 @@
@NonNull
public List<Font> getFonts(FontVariant variant) {
assert variant != FontVariant.NONE;
+
+ // Calculate the required weight based on style and weight of this typeface.
+ int weight = mWeight + ((mStyle & Font.BOLD) == 0 ? 0 : FontFamily_Delegate.BOLD_FONT_WEIGHT_DELTA);
+ if (weight > 900) {
+ weight = 900;
+ }
+ final boolean isItalic = (mStyle & Font.ITALIC) != 0;
List<Font> fonts = new ArrayList<Font>(mFontFamilies.length);
for (int i = 0; i < mFontFamilies.length; i++) {
FontFamily_Delegate ffd = mFontFamilies[i];
if (ffd != null && ffd.isValid()) {
- Font font = ffd.getFont(mStyle);
+ Font font = ffd.getFont(weight, isItalic);
if (font != null) {
FontVariant ffdVariant = ffd.getVariant();
if (ffdVariant == FontVariant.NONE) {
@@ -102,7 +110,7 @@
FontFamily_Delegate ffd2 = mFontFamilies[++i];
assert ffd2 != null;
FontVariant ffd2Variant = ffd2.getVariant();
- Font font2 = ffd2.getFont(mStyle);
+ Font font2 = ffd2.getFont(weight, isItalic);
assert ffd2Variant != FontVariant.NONE && ffd2Variant != ffdVariant
&& font2 != null;
// Add the font with the matching variant to the list.
@@ -135,7 +143,22 @@
return 0;
}
- return sManager.addNewDelegate(new Typeface_Delegate(delegate.mFontFamilies, style));
+ return sManager.addNewDelegate(new Typeface_Delegate(delegate.mFontFamilies, style,
+ delegate.mWeight));
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long nativeCreateWeightAlias(long native_instance, int weight) {
+ Typeface_Delegate delegate = sManager.getDelegate(native_instance);
+ if (delegate == null) {
+ delegate = sManager.getDelegate(sDefaultTypeface);
+ }
+ if (delegate == null) {
+ return 0;
+ }
+ Typeface_Delegate weightAlias =
+ new Typeface_Delegate(delegate.mFontFamilies, delegate.mStyle, weight);
+ return sManager.addNewDelegate(weightAlias);
}
@LayoutlibDelegate
@@ -176,7 +199,12 @@
// ---- Private delegate/helper methods ----
private Typeface_Delegate(@NonNull FontFamily_Delegate[] fontFamilies, int style) {
+ this(fontFamilies, style, FontFamily_Delegate.DEFAULT_FONT_WEIGHT);
+ }
+
+ public Typeface_Delegate(@NonNull FontFamily_Delegate[] fontFamilies, int style, int weight) {
mFontFamilies = fontFamilies;
mStyle = style;
+ mWeight = weight;
}
}
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 2604e97..c403ce6 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -222,7 +222,8 @@
@Override
public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
- int startY, IRemoteCallback startedCallback, boolean scaleUp) {
+ int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
+ boolean scaleUp) {
// TODO Auto-generated method stub
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index 130500a..0ed6ab1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -174,6 +174,11 @@
}
@Override
+ public void setWallpaperDisplayOffset(IBinder windowToken, int x, int y) {
+ // pass for now.
+ }
+
+ @Override
public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
int z, Bundle extras, boolean sync) {
// pass for now.
diff --git a/tools/layoutlib/bridge/tests/Android.mk b/tools/layoutlib/bridge/tests/Android.mk
index 7a9e067..5e47c8c 100644
--- a/tools/layoutlib/bridge/tests/Android.mk
+++ b/tools/layoutlib/bridge/tests/Android.mk
@@ -34,5 +34,8 @@
include $(BUILD_HOST_JAVA_LIBRARY)
+# Copy the jar to DIST_DIR for sdk builds
+$(call dist-for-goals, sdk win_sdk, $(LOCAL_INSTALLED_MODULE))
+
# Build all sub-directories
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/layoutlib/create/Android.mk b/tools/layoutlib/create/Android.mk
index 9bd48ab..e6f0bc3 100644
--- a/tools/layoutlib/create/Android.mk
+++ b/tools/layoutlib/create/Android.mk
@@ -26,3 +26,6 @@
include $(BUILD_HOST_JAVA_LIBRARY)
+# Build all sub-directories
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/tools/layoutlib/create/tests/Android.mk b/tools/layoutlib/create/tests/Android.mk
index 0052ec2..c197d57 100644
--- a/tools/layoutlib/create/tests/Android.mk
+++ b/tools/layoutlib/create/tests/Android.mk
@@ -28,5 +28,8 @@
include $(BUILD_HOST_JAVA_LIBRARY)
+# Copy the jar to DIST_DIR for sdk builds
+$(call dist-for-goals, sdk win_sdk, $(LOCAL_INSTALLED_MODULE))
+
# Build all sub-directories
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/wifi/java/android/net/wifi/IWifiScanner.aidl b/wifi/java/android/net/wifi/IWifiScanner.aidl
index fef2d117..3984934 100644
--- a/wifi/java/android/net/wifi/IWifiScanner.aidl
+++ b/wifi/java/android/net/wifi/IWifiScanner.aidl
@@ -17,6 +17,7 @@
package android.net.wifi;
import android.os.Messenger;
+import android.os.Bundle;
/**
* {@hide}
@@ -24,4 +25,6 @@
interface IWifiScanner
{
Messenger getMessenger();
+
+ Bundle getAvailableChannels(int band);
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index ac2a176..aeaff71 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -341,6 +341,12 @@
/**
* @hide
+ * last time we connected, this configuration had no internet access
+ */
+ public boolean noInternetAccess;
+
+ /**
+ * @hide
* Uid of app creating the configuration
*/
@SystemApi
@@ -361,9 +367,9 @@
/**
* @hide
- * Uid of app owning the BSSID
+ * Uid used by autoJoin
*/
- public int bssidOwnerUid;
+ public String autoJoinBSSID;
/**
* @hide
@@ -461,8 +467,10 @@
public int rssi24; // strongest 2.4GHz RSSI
public int num5; // number of BSSIDs on 5GHz
public int num24; // number of BSSIDs on 2.4GHz
- public long age5; // timestamp of the strongest 5GHz BSSID (last time it was seen)
- public long age24; // timestamp of the strongest 2.4GHz BSSID (last time it was seen)
+ public long age5; // timestamp of the strongest 5GHz BSSID (last time it was seen)
+ public long age24; // timestamp of the strongest 2.4GHz BSSID (last time it was seen)
+ public String BSSID24;
+ public String BSSID5;
public Visibility() {
rssi5 = INVALID_RSSI;
@@ -476,6 +484,8 @@
age5 = source.age5;
num24 = source.num24;
num5 = source.num5;
+ BSSID5 = source.BSSID5;
+ BSSID24 = source.BSSID24;
}
@Override
@@ -486,6 +496,7 @@
sbuf.append(Integer.toString(rssi24));
sbuf.append(",");
sbuf.append(Integer.toString(num24));
+ if (BSSID24 != null) sbuf.append(",").append(BSSID24);
} else {
sbuf.append("*");
}
@@ -494,6 +505,7 @@
sbuf.append(Integer.toString(rssi5));
sbuf.append(",");
sbuf.append(Integer.toString(num5));
+ if (BSSID5 != null) sbuf.append(",").append(BSSID5);
}
sbuf.append("]");
return sbuf.toString();
@@ -543,11 +555,13 @@
if (result.level > status.rssi5) {
status.rssi5 = result.level;
status.age5 = result.seen;
+ status.BSSID5 = result.BSSID;
}
} else if (result.is24GHz()) {
if (result.level > status.rssi24) {
status.rssi24 = result.level;
status.age24 = result.seen;
+ status.BSSID24 = result.BSSID;
}
}
}
@@ -673,6 +687,49 @@
@SystemApi
public int numAssociation;
+ /**
+ * @hide
+ * Number of time user disabled WiFi while associated to this configuration with Low RSSI.
+ */
+ public int numUserTriggeredWifiDisableLowRSSI;
+
+ /**
+ * @hide
+ * Number of time user disabled WiFi while associated to this configuration with Bad RSSI.
+ */
+ public int numUserTriggeredWifiDisableBadRSSI;
+
+ /**
+ * @hide
+ * Number of time user disabled WiFi while associated to this configuration
+ * and RSSI was not HIGH.
+ */
+ public int numUserTriggeredWifiDisableNotHighRSSI;
+
+ /**
+ * @hide
+ * Number of ticks associated to this configuration with Low RSSI.
+ */
+ public int numTicksAtLowRSSI;
+
+ /**
+ * @hide
+ * Number of ticks associated to this configuration with Bad RSSI.
+ */
+ public int numTicksAtBadRSSI;
+
+ /**
+ * @hide
+ * Number of ticks associated to this configuration
+ * and RSSI was not HIGH.
+ */
+ public int numTicksAtNotHighRSSI;
+ /**
+ * @hide
+ * Number of time user (WifiManager) triggered association to this configuration.
+ * TODO: count this only for Wifi Settings uuid, so as to not count 3rd party apps
+ */
+ public int numUserTriggeredJoinAttempts;
/**
* @hide
@@ -725,6 +782,7 @@
selfAdded = false;
didSelfAdd = false;
ephemeral = false;
+ noInternetAccess = false;
mIpConfiguration = new IpConfiguration();
}
@@ -824,8 +882,10 @@
sbuf.append(" autoJoinStatus ").append(this.numConnectionFailures).append("\n");
}
if (this.didSelfAdd || this.selfAdded) {
- if (this.didSelfAdd) sbuf.append(" didSelfAdd ");
- if (this.selfAdded) sbuf.append(" selfAdded ");
+ if (this.didSelfAdd) sbuf.append(" didSelfAdd");
+ if (this.selfAdded) sbuf.append(" selfAdded");
+ if (this.noInternetAccess) sbuf.append(" noInternetAccess");
+
sbuf.append("\n");
}
sbuf.append(" KeyMgmt:");
@@ -896,18 +956,44 @@
sbuf.append(mIpConfiguration.toString());
- if (selfAdded) sbuf.append("selfAdded");
- if (creatorUid != 0) sbuf.append("uid=" + Integer.toString(creatorUid));
-
- if (blackListTimestamp != 0) {
+ if (this.creatorUid != 0) sbuf.append("uid=" + Integer.toString(creatorUid));
+ if (this.autoJoinBSSID != null) sbuf.append("autoJoinBSSID=" + autoJoinBSSID);
+ if (this.blackListTimestamp != 0) {
long now_ms = System.currentTimeMillis();
- long diff = now_ms - blackListTimestamp;
+ long diff = now_ms - this.blackListTimestamp;
if (diff <= 0) {
sbuf.append("blackListed since <incorrect>");
} else {
sbuf.append("blackListed since ").append(Long.toString(diff/1000)).append( "sec");
}
}
+ sbuf.append('\n');
+ if (this.linkedConfigurations != null) {
+ for(String key : this.linkedConfigurations.keySet()) {
+ sbuf.append(" linked: ").append(key);
+ sbuf.append('\n');
+ }
+ }
+ if (this.connectChoices != null) {
+ for(String key : this.connectChoices.keySet()) {
+ Integer choice = this.connectChoices.get(key);
+ if (choice != null) {
+ sbuf.append(" choice: ").append(key);
+ sbuf.append(" = ").append(choice);
+ sbuf.append('\n');
+ }
+ }
+ }
+ sbuf.append(" triggeredLow: ").append(numUserTriggeredWifiDisableLowRSSI);
+ sbuf.append(" triggeredBad: ").append(numUserTriggeredWifiDisableBadRSSI);
+ sbuf.append(" triggeredNotHigh: ").append(numUserTriggeredWifiDisableNotHighRSSI);
+ sbuf.append('\n');
+ sbuf.append(" ticksLow: ").append(numTicksAtLowRSSI);
+ sbuf.append(" ticksBad: ").append(numTicksAtBadRSSI);
+ sbuf.append(" ticksNotHigh: ").append(numTicksAtNotHighRSSI);
+ sbuf.append('\n');
+ sbuf.append(" triggeredJoin: ").append(numUserTriggeredJoinAttempts);
+ sbuf.append('\n');
return sbuf.toString();
}
@@ -1197,7 +1283,7 @@
mCachedConfigKey = null; //force null configKey
autoJoinStatus = source.autoJoinStatus;
selfAdded = source.selfAdded;
-
+ noInternetAccess = source.noInternetAccess;
if (source.visibility != null) {
visibility = new Visibility(source.visibility);
}
@@ -1206,7 +1292,6 @@
didSelfAdd = source.didSelfAdd;
lastConnectUid = source.lastConnectUid;
lastUpdateUid = source.lastUpdateUid;
- bssidOwnerUid = source.bssidOwnerUid;
creatorUid = source.creatorUid;
peerWifiConfiguration = source.peerWifiConfiguration;
blackListTimestamp = source.blackListTimestamp;
@@ -1217,6 +1302,14 @@
numScorerOverride = source.numScorerOverride;
numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork;
numAssociation = source.numAssociation;
+ numUserTriggeredWifiDisableLowRSSI = source.numUserTriggeredWifiDisableLowRSSI;
+ numUserTriggeredWifiDisableBadRSSI = source.numUserTriggeredWifiDisableBadRSSI;
+ numUserTriggeredWifiDisableNotHighRSSI = source.numUserTriggeredWifiDisableNotHighRSSI;
+ numTicksAtLowRSSI = source.numTicksAtLowRSSI;
+ numTicksAtBadRSSI = source.numTicksAtBadRSSI;
+ numTicksAtNotHighRSSI = source.numTicksAtNotHighRSSI;
+ numUserTriggeredJoinAttempts = source.numUserTriggeredJoinAttempts;
+ autoJoinBSSID = source.autoJoinBSSID;
}
}
@@ -1233,6 +1326,7 @@
dest.writeInt(disableReason);
dest.writeString(SSID);
dest.writeString(BSSID);
+ dest.writeString(autoJoinBSSID);
dest.writeString(FQDN);
dest.writeString(naiRealm);
dest.writeString(preSharedKey);
@@ -1259,16 +1353,24 @@
dest.writeInt(autoJoinStatus);
dest.writeInt(selfAdded ? 1 : 0);
dest.writeInt(didSelfAdd ? 1 : 0);
+ dest.writeInt(noInternetAccess ? 1 : 0);
dest.writeInt(creatorUid);
dest.writeInt(lastConnectUid);
dest.writeInt(lastUpdateUid);
- dest.writeInt(bssidOwnerUid);
dest.writeLong(blackListTimestamp);
dest.writeLong(lastConnectionFailure);
dest.writeInt(numConnectionFailures);
dest.writeInt(numScorerOverride);
dest.writeInt(numScorerOverrideAndSwitchedNetwork);
dest.writeInt(numAssociation);
+ dest.writeInt(numUserTriggeredWifiDisableLowRSSI);
+ dest.writeInt(numUserTriggeredWifiDisableBadRSSI);
+ dest.writeInt(numUserTriggeredWifiDisableNotHighRSSI);
+ dest.writeInt(numTicksAtLowRSSI);
+ dest.writeInt(numTicksAtBadRSSI);
+ dest.writeInt(numTicksAtNotHighRSSI);
+ dest.writeInt(numUserTriggeredJoinAttempts);
+
}
/** Implement the Parcelable interface {@hide} */
@@ -1281,6 +1383,7 @@
config.disableReason = in.readInt();
config.SSID = in.readString();
config.BSSID = in.readString();
+ config.autoJoinBSSID = in.readString();
config.FQDN = in.readString();
config.naiRealm = in.readString();
config.preSharedKey = in.readString();
@@ -1307,16 +1410,23 @@
config.autoJoinStatus = in.readInt();
config.selfAdded = in.readInt() != 0;
config.didSelfAdd = in.readInt() != 0;
+ config.noInternetAccess = in.readInt() != 0;
config.creatorUid = in.readInt();
config.lastConnectUid = in.readInt();
config.lastUpdateUid = in.readInt();
- config.bssidOwnerUid = in.readInt();
config.blackListTimestamp = in.readLong();
config.lastConnectionFailure = in.readLong();
config.numConnectionFailures = in.readInt();
config.numScorerOverride = in.readInt();
config.numScorerOverrideAndSwitchedNetwork = in.readInt();
config.numAssociation = in.readInt();
+ config.numUserTriggeredWifiDisableLowRSSI = in.readInt();
+ config.numUserTriggeredWifiDisableBadRSSI = in.readInt();
+ config.numUserTriggeredWifiDisableNotHighRSSI = in.readInt();
+ config.numTicksAtLowRSSI = in.readInt();
+ config.numTicksAtBadRSSI = in.readInt();
+ config.numTicksAtNotHighRSSI = in.readInt();
+ config.numUserTriggeredJoinAttempts = in.readInt();
return config;
}
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index e7bcb23..aaa2f98 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -18,6 +18,7 @@
import android.annotation.SystemApi;
import android.content.Context;
+import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -75,6 +76,11 @@
public static final int REASON_INVALID_LISTENER = -2;
/** Invalid request */
public static final int REASON_INVALID_REQUEST = -3;
+ /** Invalid request */
+ public static final int REASON_NOT_AUTHORIZED = -4;
+
+ /** @hide */
+ public static final String GET_AVAILABLE_CHANNELS_EXTRA = "Channels";
/**
* Generic action callback invocation interface
@@ -92,7 +98,12 @@
* @hide
*/
public List<Integer> getAvailableChannels(int band) {
- return null;
+ try {
+ Bundle bundle = mService.getAvailableChannels(band);
+ return bundle.getIntegerArrayList(GET_AVAILABLE_CHANNELS_EXTRA);
+ } catch (RemoteException e) {
+ return null;
+ }
}
/**