summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt40
-rw-r--r--core/java/android/bluetooth/IBluetoothGattCallback.aidl6
-rw-r--r--core/java/android/content/pm/LauncherApps.java69
-rw-r--r--core/java/android/hardware/camera2/CameraDevice.java20
-rw-r--r--core/java/android/hardware/hdmi/HdmiPortInfo.aidl19
-rw-r--r--core/java/android/hardware/hdmi/HdmiPortInfo.java164
-rw-r--r--core/java/android/hardware/hdmi/HdmiTvClient.java44
-rw-r--r--core/java/android/hardware/hdmi/IHdmiControlService.aidl1
-rw-r--r--core/java/android/net/ConnectivityManager.java295
-rw-r--r--core/java/android/net/Network.java5
-rw-r--r--core/java/android/net/NetworkRequest.java2
-rw-r--r--core/java/android/view/WindowInsets.java8
-rw-r--r--core/java/android/view/WindowManagerPolicy.java14
-rw-r--r--core/java/com/android/internal/widget/ActionBarOverlayLayout.java10
-rw-r--r--core/res/res/anim-land/task_close_enter.xml42
-rw-r--r--core/res/res/anim-land/task_close_exit.xml43
-rw-r--r--core/res/res/anim-land/task_open_enter.xml42
-rw-r--r--core/res/res/anim-land/task_open_exit.xml43
-rw-r--r--core/res/res/anim-sw720dp/task_close_enter.xml42
-rw-r--r--core/res/res/anim-sw720dp/task_close_exit.xml43
-rw-r--r--core/res/res/anim-sw720dp/task_open_enter.xml42
-rw-r--r--core/res/res/anim-sw720dp/task_open_exit.xml43
-rw-r--r--core/res/res/values/strings.xml2
-rw-r--r--libs/hwui/TessellationCache.cpp4
-rw-r--r--libs/hwui/TessellationCache.h1
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java58
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java2
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java54
-rw-r--r--rs/java/android/renderscript/FieldPacker.java6
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java11
-rw-r--r--services/core/java/com/android/server/hdmi/ActiveSourceHandler.java112
-rw-r--r--services/core/java/com/android/server/hdmi/DeviceSelectAction.java223
-rw-r--r--services/core/java/com/android/server/hdmi/FeatureAction.java5
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecController.java7
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java28
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java32
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiConstants.java6
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java195
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiUtils.java20
-rw-r--r--services/core/java/com/android/server/hdmi/RoutingControlAction.java244
-rw-r--r--services/core/java/com/android/server/job/JobServiceContext.java3
-rw-r--r--services/core/java/com/android/server/job/JobStore.java14
-rw-r--r--services/core/java/com/android/server/job/controllers/ConnectivityController.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java4
-rw-r--r--services/core/jni/com_android_server_hdmi_HdmiCecController.cpp94
-rw-r--r--telecomm/java/android/telecomm/CallCapabilities.java50
-rw-r--r--telecomm/java/android/telecomm/CallService.java46
-rw-r--r--telecomm/java/android/telecomm/CallServiceAdapter.java25
-rw-r--r--telecomm/java/android/telecomm/Connection.java122
-rw-r--r--telecomm/java/android/telecomm/ConnectionService.java113
-rw-r--r--telecomm/java/android/telecomm/InCallAdapter.java9
-rw-r--r--telecomm/java/android/telecomm/InCallCall.java24
-rw-r--r--telecomm/java/com/android/internal/telecomm/ICallService.aidl4
-rw-r--r--telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl6
-rw-r--r--telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl2
59 files changed, 1787 insertions, 811 deletions
diff --git a/api/current.txt b/api/current.txt
index 3962492..d01edd4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8247,11 +8247,11 @@ package android.content.pm {
}
public static abstract interface LauncherApps.OnAppsChangedListener {
- method public abstract void onPackageAdded(java.lang.String, android.os.UserHandle);
- method public abstract void onPackageChanged(java.lang.String, android.os.UserHandle);
- method public abstract void onPackageRemoved(java.lang.String, android.os.UserHandle);
- method public abstract void onPackagesAvailable(java.lang.String[], android.os.UserHandle, boolean);
- method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean);
+ method public abstract void onPackageAdded(android.os.UserHandle, java.lang.String);
+ method public abstract void onPackageChanged(android.os.UserHandle, java.lang.String);
+ method public abstract void onPackageRemoved(android.os.UserHandle, java.lang.String);
+ method public abstract void onPackagesAvailable(android.os.UserHandle, java.lang.String[], boolean);
+ method public abstract void onPackagesUnavailable(android.os.UserHandle, java.lang.String[], boolean);
}
public class PackageInfo implements android.os.Parcelable {
@@ -16096,28 +16096,25 @@ package android.net {
method public deprecated int getNetworkPreference();
method public static android.net.Network getProcessDefaultNetwork();
method public boolean isActiveNetworkMetered();
- method public boolean isNetworkActive();
+ method public boolean isDefaultNetworkActive();
method public static boolean isNetworkTypeValid(int);
- method public android.net.NetworkRequest listenForNetwork(android.net.NetworkCapabilities, android.net.ConnectivityManager.NetworkCallbackListener);
- method public void registerNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
- method public void releaseNetworkRequest(android.net.NetworkRequest);
+ method public void registerDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
+ method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
method public void reportBadNetwork(android.net.Network);
- method public android.net.NetworkRequest requestNetwork(android.net.NetworkCapabilities, android.net.ConnectivityManager.NetworkCallbackListener);
- method public android.net.NetworkRequest requestNetwork(android.net.NetworkCapabilities, android.app.PendingIntent);
+ method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
method public deprecated boolean requestRouteToHost(int, int);
method public deprecated void setNetworkPreference(int);
method public static boolean setProcessDefaultNetwork(android.net.Network);
method public deprecated int startUsingNetworkFeature(int, java.lang.String);
method public deprecated int stopUsingNetworkFeature(int, java.lang.String);
- method public void unregisterNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
+ method public void unregisterDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
+ method public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover";
field public static final deprecated java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
- field public static final java.lang.String EXTRA_NETWORK_REQUEST_NETWORK = "networkRequestNetwork";
- field public static final java.lang.String EXTRA_NETWORK_REQUEST_NETWORK_CAPABILITIES = "networkRequestNetworkCapabilities";
field public static final java.lang.String EXTRA_NETWORK_TYPE = "networkType";
field public static final java.lang.String EXTRA_NO_CONNECTIVITY = "noConnectivity";
field public static final java.lang.String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
@@ -16134,14 +16131,13 @@ package android.net {
field public static final int TYPE_WIMAX = 6; // 0x6
}
- public static class ConnectivityManager.NetworkCallbackListener {
- ctor public ConnectivityManager.NetworkCallbackListener();
- method public void onAvailable(android.net.NetworkRequest, android.net.Network);
- method public void onLinkPropertiesChanged(android.net.NetworkRequest, android.net.Network, android.net.LinkProperties);
- method public void onLosing(android.net.NetworkRequest, android.net.Network, int);
- method public void onLost(android.net.NetworkRequest, android.net.Network);
- method public void onNetworkCapabilitiesChanged(android.net.NetworkRequest, android.net.Network, android.net.NetworkCapabilities);
- method public void onReleased(android.net.NetworkRequest);
+ public static class ConnectivityManager.NetworkCallback {
+ ctor public ConnectivityManager.NetworkCallback();
+ method public void onAvailable(android.net.Network);
+ method public void onCapabilitiesChanged(android.net.Network, android.net.NetworkCapabilities);
+ method public void onLinkPropertiesChanged(android.net.Network, android.net.LinkProperties);
+ method public void onLosing(android.net.Network, int);
+ method public void onLost(android.net.Network);
}
public static abstract interface ConnectivityManager.OnNetworkActiveListener {
diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
index bf9e0a7..2d8eed4 100644
--- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
@@ -22,7 +22,7 @@ import android.os.ParcelUuid;
* Callback definitions for interacting with BLE / GATT
* @hide
*/
-interface IBluetoothGattCallback {
+oneway interface IBluetoothGattCallback {
void onClientRegistered(in int status, in int clientIf);
void onClientConnectionState(in int status, in int clientIf,
in boolean connected, in String address);
@@ -63,7 +63,7 @@ interface IBluetoothGattCallback {
in int charInstId, in ParcelUuid charUuid,
in byte[] value);
void onReadRemoteRssi(in String address, in int rssi, in int status);
- oneway void onAdvertiseStateChange(in int advertiseState, in int status);
- oneway void onMultiAdvertiseCallback(in int status);
+ void onAdvertiseStateChange(in int advertiseState, in int status);
+ void onMultiAdvertiseCallback(in int status);
void onConfigureMTU(in String address, in int mtu, in int status);
}
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 04c0b9f..69fa408 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -67,7 +67,6 @@ public class LauncherApps {
*
* @param user The UserHandle of the profile that generated the change.
* @param packageName The name of the package that was removed.
- * @hide remove before ship
*/
void onPackageRemoved(UserHandle user, String packageName);
@@ -76,7 +75,6 @@ public class LauncherApps {
*
* @param user The UserHandle of the profile that generated the change.
* @param packageName The name of the package that was added.
- * @hide remove before ship
*/
void onPackageAdded(UserHandle user, String packageName);
@@ -85,7 +83,6 @@ public class LauncherApps {
*
* @param user The UserHandle of the profile that generated the change.
* @param packageName The name of the package that has changed.
- * @hide remove before ship
*/
void onPackageChanged(UserHandle user, String packageName);
@@ -99,7 +96,6 @@ public class LauncherApps {
* available.
* @param replacing Indicates whether these packages are replacing
* existing ones.
- * @hide remove before ship
*/
void onPackagesAvailable(UserHandle user, String[] packageNames, boolean replacing);
@@ -113,59 +109,9 @@ public class LauncherApps {
* unavailable.
* @param replacing Indicates whether the packages are about to be
* replaced with new versions.
- * @hide remove before ship
*/
void onPackagesUnavailable(UserHandle user, String[] packageNames, boolean replacing);
- /**
- * Indicates that a package was removed from the specified profile.
- *
- * @param packageName The name of the package that was removed.
- * @param user The UserHandle of the profile that generated the change.
- */
- void onPackageRemoved(String packageName, UserHandle user);
-
- /**
- * Indicates that a package was added to the specified profile.
- *
- * @param packageName The name of the package that was added.
- * @param user The UserHandle of the profile that generated the change.
- */
- void onPackageAdded(String packageName, UserHandle user);
-
- /**
- * Indicates that a package was modified in the specified profile.
- *
- * @param packageName The name of the package that has changed.
- * @param user The UserHandle of the profile that generated the change.
- */
- void onPackageChanged(String packageName, UserHandle user);
-
- /**
- * Indicates that one or more packages have become available. For
- * example, this can happen when a removable storage card has
- * reappeared.
- *
- * @param packageNames The names of the packages that have become
- * available.
- * @param user The UserHandle of the profile that generated the change.
- * @param replacing Indicates whether these packages are replacing
- * existing ones.
- */
- void onPackagesAvailable(String [] packageNames, UserHandle user, boolean replacing);
-
- /**
- * Indicates that one or more packages have become unavailable. For
- * example, this can happen when a removable storage card has been
- * removed.
- *
- * @param packageNames The names of the packages that have become
- * unavailable.
- * @param user The UserHandle of the profile that generated the change.
- * @param replacing Indicates whether the packages are about to be
- * replaced with new versions.
- */
- void onPackagesUnavailable(String[] packageNames, UserHandle user, boolean replacing);
}
/** @hide */
@@ -361,8 +307,7 @@ public class LauncherApps {
}
synchronized (LauncherApps.this) {
for (OnAppsChangedListener listener : mListeners) {
- listener.onPackageRemoved(user, packageName); // TODO: Remove before ship
- listener.onPackageRemoved(packageName, user);
+ listener.onPackageRemoved(user, packageName);
}
}
}
@@ -374,8 +319,7 @@ public class LauncherApps {
}
synchronized (LauncherApps.this) {
for (OnAppsChangedListener listener : mListeners) {
- listener.onPackageChanged(user, packageName); // TODO: Remove before ship
- listener.onPackageChanged(packageName, user);
+ listener.onPackageChanged(user, packageName);
}
}
}
@@ -387,8 +331,7 @@ public class LauncherApps {
}
synchronized (LauncherApps.this) {
for (OnAppsChangedListener listener : mListeners) {
- listener.onPackageAdded(user, packageName); // TODO: Remove before ship
- listener.onPackageAdded(packageName, user);
+ listener.onPackageAdded(user, packageName);
}
}
}
@@ -401,8 +344,7 @@ public class LauncherApps {
}
synchronized (LauncherApps.this) {
for (OnAppsChangedListener listener : mListeners) {
- listener.onPackagesAvailable(user, packageNames, replacing); // TODO: Remove
- listener.onPackagesAvailable(packageNames, user, replacing);
+ listener.onPackagesAvailable(user, packageNames, replacing);
}
}
}
@@ -415,8 +357,7 @@ public class LauncherApps {
}
synchronized (LauncherApps.this) {
for (OnAppsChangedListener listener : mListeners) {
- listener.onPackagesUnavailable(user, packageNames, replacing); // TODO: Remove
- listener.onPackagesUnavailable(packageNames, user, replacing);
+ listener.onPackagesUnavailable(user, packageNames, replacing);
}
}
}
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 68f4d64..77d0c41 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -190,22 +190,18 @@ public abstract class CameraDevice implements AutoCloseable {
* Then obtain the Surface with
* {@link android.renderscript.Allocation#getSurface}.</li>
*
- * <li>For access to raw, uncompressed or JPEG data in the application: Create a
- * {@link android.media.ImageReader} object with the one of the supported
- * {@link StreamConfigurationMap#getOutputFormats() output image formats}, and a
- * size from the supported
- * {@link StreamConfigurationMap#getOutputSizes(int) sizes for that format}. Then obtain
- * a Surface from it with {@link android.media.ImageReader#getSurface}.</li>
+ * <li>For access to raw, uncompressed JPEG data in the application: Create an
+ * {@link android.media.ImageReader} object with one of the supported output formats given by
+ * {@link StreamConfigurationMap#getOutputFormats()}, setting its size to one of the
+ * corresponding supported sizes by passing the chosen output format into
+ * {@link StreamConfigurationMap#getOutputSizes(int)}. Then obtain a
+ * {@link android.view.Surface} from it with {@link android.media.ImageReader#getSurface()}.
+ * </li>
*
* </ul>
*
- * </p>
- *
* <p>The camera device will query each Surface's size and formats upon this
- * call, so they must be set to a valid setting at this time (in particular:
- * if the format is user-visible, it must be one of
- * {@link StreamConfigurationMap#getOutputFormats}; and the size must be one of
- * {@link StreamConfigurationMap#getOutputSizes(int)}).</p>
+ * call, so they must be set to a valid setting at this time.</p>
*
* <p>It can take several hundred milliseconds for the session's configuration to complete,
* since camera hardware may need to be powered on or reconfigured. Once the configuration is
diff --git a/core/java/android/hardware/hdmi/HdmiPortInfo.aidl b/core/java/android/hardware/hdmi/HdmiPortInfo.aidl
new file mode 100644
index 0000000..157b5b3
--- /dev/null
+++ b/core/java/android/hardware/hdmi/HdmiPortInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.hardware.hdmi;
+
+parcelable HdmiPortInfo;
diff --git a/core/java/android/hardware/hdmi/HdmiPortInfo.java b/core/java/android/hardware/hdmi/HdmiPortInfo.java
new file mode 100644
index 0000000..7b25f8a
--- /dev/null
+++ b/core/java/android/hardware/hdmi/HdmiPortInfo.java
@@ -0,0 +1,164 @@
+/*
+ * 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.hardware.hdmi;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class to encapsulate HDMI port information. Contains the capability of the ports such as
+ * HDMI-CEC, MHL, ARC(Audio Return Channel), and physical address assigned to each port.
+ *
+ * @hide
+ */
+@SystemApi
+public final class HdmiPortInfo implements Parcelable {
+ /** HDMI port type: Input */
+ public static final int PORT_INPUT = 0;
+
+ /** HDMI port type: Output */
+ public static final int PORT_OUTPUT = 1;
+
+ private final int mId;
+ private final int mType;
+ private final int mAddress;
+ private final boolean mCecSupported;
+ private final boolean mArcSupported;
+ private final boolean mMhlSupported;
+
+ /**
+ * Constructor.
+ *
+ * @param id identifier assigned to each port. 1 for HDMI port 1
+ * @param type HDMI port input/output type
+ * @param address physical address of the port
+ * @param cec {@code true} if HDMI-CEC is supported on the port
+ * @param mhl {@code true} if MHL is supported on the port
+ * @param arc {@code true} if audio return channel is supported on the port
+ */
+ public HdmiPortInfo(int id, int type, int address, boolean cec, boolean mhl, boolean arc) {
+ mId = id;
+ mType = type;
+ mAddress = address;
+ mCecSupported = cec;
+ mArcSupported = arc;
+ mMhlSupported = mhl;
+ }
+
+ /**
+ * Returns the port id.
+ *
+ * @return port id
+ */
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * Returns the port type.
+ *
+ * @return port type
+ */
+ public int getType() {
+ return mType;
+ }
+
+ /**
+ * Returns the port address.
+ *
+ * @return port address
+ */
+ public int getAddress() {
+ return mAddress;
+ }
+
+ /**
+ * Returns {@code true} if the port supports HDMI-CEC signaling.
+ *
+ * @return {@code true} if the port supports HDMI-CEC signaling.
+ */
+ public boolean isCecSupported() {
+ return mCecSupported;
+ }
+
+ /**
+ * Returns {@code true} if the port supports MHL signaling.
+ *
+ * @return {@code true} if the port supports MHL signaling.
+ */
+ public boolean isMhlSupported() {
+ return mMhlSupported;
+ }
+
+ /**
+ * Returns {@code true} if the port supports audio return channel.
+ *
+ * @return {@code true} if the port supports audio return channel
+ */
+ public boolean isArcSupported() {
+ return mArcSupported;
+ }
+
+ /**
+ * Describe the kinds of special objects contained in this Parcelable's
+ * marshalled representation.
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+
+ /**
+ * A helper class to deserialize {@link HdmiPortInfo} for a parcel.
+ */
+ public static final Parcelable.Creator<HdmiPortInfo> CREATOR =
+ new Parcelable.Creator<HdmiPortInfo>() {
+ @Override
+ public HdmiPortInfo createFromParcel(Parcel source) {
+ int id = source.readInt();
+ int type = source.readInt();
+ int address = source.readInt();
+ boolean cec = (source.readInt() == 1);
+ boolean arc = (source.readInt() == 1);
+ boolean mhl = (source.readInt() == 1);
+ return new HdmiPortInfo(id, type, address, cec, arc, mhl);
+ }
+
+ @Override
+ public HdmiPortInfo[] newArray(int size) {
+ return new HdmiPortInfo[size];
+ }
+ };
+
+ /**
+ * Serialize this object into a {@link Parcel}.
+ *
+ * @param dest The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written.
+ * May be 0 or {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE}.
+ */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mId);
+ dest.writeInt(mType);
+ dest.writeInt(mAddress);
+ dest.writeInt(mCecSupported ? 1 : 0);
+ dest.writeInt(mArcSupported ? 1 : 0);
+ dest.writeInt(mMhlSupported ? 1 : 0);
+ }
+}
diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java
index 6dc4a4f..85af3d1 100644
--- a/core/java/android/hardware/hdmi/HdmiTvClient.java
+++ b/core/java/android/hardware/hdmi/HdmiTvClient.java
@@ -16,6 +16,8 @@
package android.hardware.hdmi;
import android.annotation.SystemApi;
+import android.os.RemoteException;
+import android.util.Log;
/**
* HdmiTvClient represents HDMI-CEC logical device of type TV in the Android system
@@ -33,4 +35,46 @@ public final class HdmiTvClient {
HdmiTvClient(IHdmiControlService service) {
mService = service;
}
+
+ // Factory method for HdmiTvClient.
+ // Declared package-private. Accessed by HdmiControlManager only.
+ static HdmiTvClient create(IHdmiControlService service) {
+ return new HdmiTvClient(service);
+ }
+
+ /**
+ * Callback interface used to get the result of {@link #deviceSelect}.
+ */
+ public interface SelectCallback {
+ /**
+ * Called when the operation is finished.
+ *
+ * @param result the result value of {@link #deviceSelect}
+ */
+ void onComplete(int result);
+ }
+
+ /**
+ * Select a CEC logical device to be a new active source.
+ *
+ * @param logicalAddress
+ * @param callback
+ */
+ public void deviceSelect(int logicalAddress, SelectCallback callback) {
+ // TODO: Replace SelectCallback with PartialResult.
+ try {
+ mService.deviceSelect(logicalAddress, getCallbackWrapper(callback));
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to select device: ", e);
+ }
+ }
+
+ private static IHdmiControlCallback getCallbackWrapper(final SelectCallback callback) {
+ return new IHdmiControlCallback.Stub() {
+ @Override
+ public void onComplete(int result) {
+ callback.onComplete(result);
+ }
+ };
+ }
}
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index 8da38e1..8d7c638 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -33,4 +33,5 @@ interface IHdmiControlService {
void queryDisplayStatus(IHdmiControlCallback callback);
void addHotplugEventListener(IHdmiHotplugEventListener listener);
void removeHotplugEventListener(IHdmiHotplugEventListener listener);
+ void deviceSelect(int logicalAddress, IHdmiControlCallback callback);
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index ff90e78..ba31243 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -868,10 +868,10 @@ public class ConnectivityManager {
return -1;
}
- NetworkRequest request = removeRequestForFeature(netCap);
- if (request != null) {
+ NetworkCallback networkCallback = removeRequestForFeature(netCap);
+ if (networkCallback != null) {
Log.d(TAG, "stopUsingNetworkFeature for " + networkType + ", " + feature);
- releaseNetworkRequest(request);
+ unregisterNetworkCallback(networkCallback);
}
return 1;
}
@@ -982,15 +982,15 @@ public class ConnectivityManager {
int expireSequenceNumber;
Network currentNetwork;
int delay = -1;
- NetworkCallbackListener networkCallbackListener = new NetworkCallbackListener() {
+ NetworkCallback networkCallback = new NetworkCallback() {
@Override
- public void onAvailable(NetworkRequest request, Network network) {
+ public void onAvailable(Network network) {
currentNetwork = network;
Log.d(TAG, "startUsingNetworkFeature got Network:" + network);
setProcessDefaultNetworkForHostResolution(network);
}
@Override
- public void onLost(NetworkRequest request, Network network) {
+ public void onLost(Network network) {
if (network.equals(currentNetwork)) {
currentNetwork = null;
setProcessDefaultNetworkForHostResolution(null);
@@ -1024,7 +1024,7 @@ public class ConnectivityManager {
if (l == null) return;
ourSeqNum = l.expireSequenceNumber;
if (l.expireSequenceNumber == sequenceNum) {
- releaseNetworkRequest(l.networkRequest);
+ unregisterNetworkCallback(l.networkCallback);
sLegacyRequests.remove(netCap);
}
}
@@ -1041,7 +1041,7 @@ public class ConnectivityManager {
l.networkCapabilities = netCap;
l.delay = delay;
l.expireSequenceNumber = 0;
- l.networkRequest = sendRequestForNetwork(netCap, l.networkCallbackListener, 0,
+ l.networkRequest = sendRequestForNetwork(netCap, l.networkCallback, 0,
REQUEST, type);
if (l.networkRequest == null) return null;
sLegacyRequests.put(netCap, l);
@@ -1057,11 +1057,11 @@ public class ConnectivityManager {
}
}
- private NetworkRequest removeRequestForFeature(NetworkCapabilities netCap) {
+ private NetworkCallback removeRequestForFeature(NetworkCapabilities netCap) {
synchronized (sLegacyRequests) {
LegacyRequest l = sLegacyRequests.remove(netCap);
if (l == null) return null;
- return l.networkRequest;
+ return l.networkCallback;
}
}
@@ -1184,8 +1184,8 @@ public class ConnectivityManager {
}
/**
- * Callback for use with {@link ConnectivityManager#registerNetworkActiveListener} to
- * find out when the current network has gone in to a high power state.
+ * Callback for use with {@link ConnectivityManager#registerDefaultNetworkActiveListener}
+ * to find out when the system default network has gone in to a high power state.
*/
public interface OnNetworkActiveListener {
/**
@@ -1194,7 +1194,7 @@ public class ConnectivityManager {
* operations. Note that this listener only tells you when the network becomes
* active; if at any other time you want to know whether it is active (and thus okay
* to initiate network traffic), you can retrieve its instantaneous state with
- * {@link ConnectivityManager#isNetworkActive}.
+ * {@link ConnectivityManager#isDefaultNetworkActive}.
*/
public void onNetworkActive();
}
@@ -1215,13 +1215,18 @@ public class ConnectivityManager {
= new ArrayMap<OnNetworkActiveListener, INetworkActivityListener>();
/**
- * Start listening to reports when the data network is active, meaning it is
- * a good time to perform network traffic. Use {@link #isNetworkActive()}
- * to determine the current state of the network after registering the listener.
+ * Start listening to reports when the system's default data network is active, meaning it is
+ * a good time to perform network traffic. Use {@link #isDefaultNetworkActive()}
+ * to determine the current state of the system's default network after registering the
+ * listener.
+ * <p>
+ * If the process default network has been set with
+ * {@link ConnectivityManager#setProcessDefaultNetwork} this function will not
+ * reflect the process's default, but the system default.
*
* @param l The listener to be told when the network is active.
*/
- public void registerNetworkActiveListener(final OnNetworkActiveListener l) {
+ public void registerDefaultNetworkActiveListener(final OnNetworkActiveListener l) {
INetworkActivityListener rl = new INetworkActivityListener.Stub() {
@Override
public void onNetworkActive() throws RemoteException {
@@ -1238,11 +1243,11 @@ public class ConnectivityManager {
/**
* Remove network active listener previously registered with
- * {@link #registerNetworkActiveListener}.
+ * {@link #registerDefaultNetworkActiveListener}.
*
* @param l Previously registered listener.
*/
- public void unregisterNetworkActiveListener(OnNetworkActiveListener l) {
+ public void unregisterDefaultNetworkActiveListener(OnNetworkActiveListener l) {
INetworkActivityListener rl = mNetworkActivityListeners.get(l);
if (rl == null) {
throw new IllegalArgumentException("Listener not registered: " + l);
@@ -1261,7 +1266,7 @@ public class ConnectivityManager {
* this state. This method tells you whether right now is currently a good time to
* initiate network traffic, as the network is already active.
*/
- public boolean isNetworkActive() {
+ public boolean isDefaultNetworkActive() {
try {
return getNetworkManagementService().isNetworkActive();
} catch (RemoteException e) {
@@ -1893,7 +1898,7 @@ public class ConnectivityManager {
* Base class for NetworkRequest callbacks. Used for notifications about network
* changes. Should be extended by applications wanting notifications.
*/
- public static class NetworkCallbackListener {
+ public static class NetworkCallback {
/** @hide */
public static final int PRECHECK = 1;
/** @hide */
@@ -1916,78 +1921,68 @@ public class ConnectivityManager {
* Called whenever the framework connects to a network that it may use to
* satisfy this request
*/
- public void onPreCheck(NetworkRequest networkRequest, Network network) {}
+ public void onPreCheck(Network network) {}
/**
* Called when the framework connects and has declared new network ready for use.
+ * This callback may be called more than once if the {@link Network} that is
+ * satisfying the request changes.
*
- * @param networkRequest The {@link NetworkRequest} used to initiate the request.
* @param network The {@link Network} of the satisfying network.
*/
- public void onAvailable(NetworkRequest networkRequest, Network network) {}
+ public void onAvailable(Network network) {}
/**
* Called when the network is about to be disconnected. Often paired with an
- * {@link NetworkCallbackListener#onAvailable} call with the new replacement network
+ * {@link NetworkCallback#onAvailable} call with the new replacement network
* for graceful handover. This may not be called if we have a hard loss
* (loss without warning). This may be followed by either a
- * {@link NetworkCallbackListener#onLost} call or a
- * {@link NetworkCallbackListener#onAvailable} call for this network depending
+ * {@link NetworkCallback#onLost} call or a
+ * {@link NetworkCallback#onAvailable} call for this network depending
* on whether we lose or regain it.
*
- * @param networkRequest The {@link NetworkRequest} used to initiate the request.
- * @param network The {@link Network} of the failing network.
- * @param maxSecToLive The time in seconds the framework will attempt to keep the
- * network connected. Note that the network may suffers a
+ * @param network The {@link Network} that is about to be disconnected.
+ * @param maxMsToLive The time in ms the framework will attempt to keep the
+ * network connected. Note that the network may suffer a
* hard loss at any time.
*/
- public void onLosing(NetworkRequest networkRequest, Network network, int maxSecToLive) {}
+ public void onLosing(Network network, int maxMsToLive) {}
/**
* Called when the framework has a hard loss of the network or when the
* graceful failure ends.
*
- * @param networkRequest The {@link NetworkRequest} used to initiate the request.
* @param network The {@link Network} lost.
*/
- public void onLost(NetworkRequest networkRequest, Network network) {}
+ public void onLost(Network network) {}
/**
* Called if no network is found in the given timeout time. If no timeout is given,
* this will not be called.
* @hide
*/
- public void onUnavailable(NetworkRequest networkRequest) {}
+ public void onUnavailable() {}
/**
* Called when the network the framework connected to for this request
* changes capabilities but still satisfies the stated need.
*
- * @param networkRequest The {@link NetworkRequest} used to initiate the request.
* @param network The {@link Network} whose capabilities have changed.
* @param networkCapabilities The new {@link NetworkCapabilities} for this network.
*/
- public void onNetworkCapabilitiesChanged(NetworkRequest networkRequest, Network network,
+ public void onCapabilitiesChanged(Network network,
NetworkCapabilities networkCapabilities) {}
/**
* Called when the network the framework connected to for this request
* changes {@link LinkProperties}.
*
- * @param networkRequest The {@link NetworkRequest} used to initiate the request.
* @param network The {@link Network} whose link properties have changed.
* @param linkProperties The new {@link LinkProperties} for this network.
*/
- public void onLinkPropertiesChanged(NetworkRequest networkRequest, Network network,
- LinkProperties linkProperties) {}
+ public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {}
- /**
- * Called when a {@link #releaseNetworkRequest} call concludes and the registered
- * callbacks will no longer be used.
- *
- * @param networkRequest The {@link NetworkRequest} used to initiate the request.
- */
- public void onReleased(NetworkRequest networkRequest) {}
+ private NetworkRequest networkRequest;
}
private static final int BASE = Protocol.BASE_CONNECTIVITY_MANAGER;
@@ -2013,12 +2008,12 @@ public class ConnectivityManager {
private static final int EXPIRE_LEGACY_REQUEST = BASE + 10;
private class CallbackHandler extends Handler {
- private final HashMap<NetworkRequest, NetworkCallbackListener>mCallbackMap;
+ private final HashMap<NetworkRequest, NetworkCallback>mCallbackMap;
private final AtomicInteger mRefCount;
private static final String TAG = "ConnectivityManager.CallbackHandler";
private final ConnectivityManager mCm;
- CallbackHandler(Looper looper, HashMap<NetworkRequest, NetworkCallbackListener>callbackMap,
+ CallbackHandler(Looper looper, HashMap<NetworkRequest, NetworkCallback>callbackMap,
AtomicInteger refCount, ConnectivityManager cm) {
super(looper);
mCallbackMap = callbackMap;
@@ -2032,9 +2027,9 @@ public class ConnectivityManager {
switch (message.what) {
case CALLBACK_PRECHECK: {
NetworkRequest request = getNetworkRequest(message);
- NetworkCallbackListener callbacks = getCallbacks(request);
+ NetworkCallback callbacks = getCallbacks(request);
if (callbacks != null) {
- callbacks.onPreCheck(request, getNetwork(message));
+ callbacks.onPreCheck(getNetwork(message));
} else {
Log.e(TAG, "callback not found for PRECHECK message");
}
@@ -2042,9 +2037,9 @@ public class ConnectivityManager {
}
case CALLBACK_AVAILABLE: {
NetworkRequest request = getNetworkRequest(message);
- NetworkCallbackListener callbacks = getCallbacks(request);
+ NetworkCallback callbacks = getCallbacks(request);
if (callbacks != null) {
- callbacks.onAvailable(request, getNetwork(message));
+ callbacks.onAvailable(getNetwork(message));
} else {
Log.e(TAG, "callback not found for AVAILABLE message");
}
@@ -2052,9 +2047,9 @@ public class ConnectivityManager {
}
case CALLBACK_LOSING: {
NetworkRequest request = getNetworkRequest(message);
- NetworkCallbackListener callbacks = getCallbacks(request);
+ NetworkCallback callbacks = getCallbacks(request);
if (callbacks != null) {
- callbacks.onLosing(request, getNetwork(message), message.arg1);
+ callbacks.onLosing(getNetwork(message), message.arg1);
} else {
Log.e(TAG, "callback not found for LOSING message");
}
@@ -2062,9 +2057,9 @@ public class ConnectivityManager {
}
case CALLBACK_LOST: {
NetworkRequest request = getNetworkRequest(message);
- NetworkCallbackListener callbacks = getCallbacks(request);
+ NetworkCallback callbacks = getCallbacks(request);
if (callbacks != null) {
- callbacks.onLost(request, getNetwork(message));
+ callbacks.onLost(getNetwork(message));
} else {
Log.e(TAG, "callback not found for LOST message");
}
@@ -2072,12 +2067,12 @@ public class ConnectivityManager {
}
case CALLBACK_UNAVAIL: {
NetworkRequest req = (NetworkRequest)message.obj;
- NetworkCallbackListener callbacks = null;
+ NetworkCallback callbacks = null;
synchronized(mCallbackMap) {
callbacks = mCallbackMap.get(req);
}
if (callbacks != null) {
- callbacks.onUnavailable(req);
+ callbacks.onUnavailable();
} else {
Log.e(TAG, "callback not found for UNAVAIL message");
}
@@ -2085,12 +2080,12 @@ public class ConnectivityManager {
}
case CALLBACK_CAP_CHANGED: {
NetworkRequest request = getNetworkRequest(message);
- NetworkCallbackListener callbacks = getCallbacks(request);
+ NetworkCallback callbacks = getCallbacks(request);
if (callbacks != null) {
Network network = getNetwork(message);
NetworkCapabilities cap = mCm.getNetworkCapabilities(network);
- callbacks.onNetworkCapabilitiesChanged(request, network, cap);
+ callbacks.onCapabilitiesChanged(network, cap);
} else {
Log.e(TAG, "callback not found for CHANGED message");
}
@@ -2098,12 +2093,12 @@ public class ConnectivityManager {
}
case CALLBACK_IP_CHANGED: {
NetworkRequest request = getNetworkRequest(message);
- NetworkCallbackListener callbacks = getCallbacks(request);
+ NetworkCallback callbacks = getCallbacks(request);
if (callbacks != null) {
Network network = getNetwork(message);
LinkProperties lp = mCm.getLinkProperties(network);
- callbacks.onLinkPropertiesChanged(request, network, lp);
+ callbacks.onLinkPropertiesChanged(network, lp);
} else {
Log.e(TAG, "callback not found for CHANGED message");
}
@@ -2111,20 +2106,19 @@ public class ConnectivityManager {
}
case CALLBACK_RELEASED: {
NetworkRequest req = (NetworkRequest)message.obj;
- NetworkCallbackListener callbacks = null;
+ NetworkCallback callbacks = null;
synchronized(mCallbackMap) {
callbacks = mCallbackMap.remove(req);
}
if (callbacks != null) {
- callbacks.onReleased(req);
+ synchronized(mRefCount) {
+ if (mRefCount.decrementAndGet() == 0) {
+ getLooper().quit();
+ }
+ }
} else {
Log.e(TAG, "callback not found for CANCELED message");
}
- synchronized(mRefCount) {
- if (mRefCount.decrementAndGet() == 0) {
- getLooper().quit();
- }
- }
break;
}
case CALLBACK_EXIT: {
@@ -2142,7 +2136,7 @@ public class ConnectivityManager {
private NetworkRequest getNetworkRequest(Message msg) {
return (NetworkRequest)(msg.obj);
}
- private NetworkCallbackListener getCallbacks(NetworkRequest req) {
+ private NetworkCallback getCallbacks(NetworkRequest req) {
synchronized(mCallbackMap) {
return mCallbackMap.get(req);
}
@@ -2150,7 +2144,7 @@ public class ConnectivityManager {
private Network getNetwork(Message msg) {
return new Network(msg.arg2);
}
- private NetworkCallbackListener removeCallbacks(Message msg) {
+ private NetworkCallback removeCallbacks(Message msg) {
NetworkRequest req = (NetworkRequest)msg.obj;
synchronized(mCallbackMap) {
return mCallbackMap.remove(req);
@@ -2158,19 +2152,19 @@ public class ConnectivityManager {
}
}
- private void addCallbackListener() {
+ private void incCallbackHandlerRefCount() {
synchronized(sCallbackRefCount) {
if (sCallbackRefCount.incrementAndGet() == 1) {
// TODO - switch this over to a ManagerThread or expire it when done
HandlerThread callbackThread = new HandlerThread("ConnectivityManager");
callbackThread.start();
sCallbackHandler = new CallbackHandler(callbackThread.getLooper(),
- sNetworkCallbackListener, sCallbackRefCount, this);
+ sNetworkCallback, sCallbackRefCount, this);
}
}
}
- private void removeCallbackListener() {
+ private void decCallbackHandlerRefCount() {
synchronized(sCallbackRefCount) {
if (sCallbackRefCount.decrementAndGet() == 0) {
sCallbackHandler.obtainMessage(CALLBACK_EXIT).sendToTarget();
@@ -2179,8 +2173,8 @@ public class ConnectivityManager {
}
}
- static final HashMap<NetworkRequest, NetworkCallbackListener> sNetworkCallbackListener =
- new HashMap<NetworkRequest, NetworkCallbackListener>();
+ static final HashMap<NetworkRequest, NetworkCallback> sNetworkCallback =
+ new HashMap<NetworkRequest, NetworkCallback>();
static final AtomicInteger sCallbackRefCount = new AtomicInteger(0);
static CallbackHandler sCallbackHandler = null;
@@ -2188,51 +2182,48 @@ public class ConnectivityManager {
private final static int REQUEST = 2;
private NetworkRequest sendRequestForNetwork(NetworkCapabilities need,
- NetworkCallbackListener networkCallbackListener, int timeoutSec, int action,
+ NetworkCallback networkCallback, int timeoutSec, int action,
int legacyType) {
- NetworkRequest networkRequest = null;
- if (networkCallbackListener == null) {
- throw new IllegalArgumentException("null NetworkCallbackListener");
+ if (networkCallback == null) {
+ throw new IllegalArgumentException("null NetworkCallback");
}
if (need == null) throw new IllegalArgumentException("null NetworkCapabilities");
try {
- addCallbackListener();
+ incCallbackHandlerRefCount();
if (action == LISTEN) {
- networkRequest = mService.listenForNetwork(need, new Messenger(sCallbackHandler),
- new Binder());
+ networkCallback.networkRequest = mService.listenForNetwork(need,
+ new Messenger(sCallbackHandler), new Binder());
} else {
- networkRequest = mService.requestNetwork(need, new Messenger(sCallbackHandler),
- timeoutSec, new Binder(), legacyType);
+ networkCallback.networkRequest = mService.requestNetwork(need,
+ new Messenger(sCallbackHandler), timeoutSec, new Binder(), legacyType);
}
- if (networkRequest != null) {
- synchronized(sNetworkCallbackListener) {
- sNetworkCallbackListener.put(networkRequest, networkCallbackListener);
+ if (networkCallback.networkRequest != null) {
+ synchronized(sNetworkCallback) {
+ sNetworkCallback.put(networkCallback.networkRequest, networkCallback);
}
}
} catch (RemoteException e) {}
- if (networkRequest == null) removeCallbackListener();
- return networkRequest;
+ if (networkCallback.networkRequest == null) decCallbackHandlerRefCount();
+ return networkCallback.networkRequest;
}
/**
* Request a network to satisfy a set of {@link NetworkCapabilities}.
*
* This {@link NetworkRequest} will live until released via
- * {@link #releaseNetworkRequest} or the calling application exits.
+ * {@link #unregisterNetworkCallback} or the calling application exits.
* Status of the request can be followed by listening to the various
- * callbacks described in {@link NetworkCallbackListener}. The {@link Network}
+ * callbacks described in {@link NetworkCallback}. The {@link Network}
* can be used to direct traffic to the network.
*
- * @param need {@link NetworkCapabilities} required by this request.
- * @param networkCallbackListener The {@link NetworkCallbackListener} to be utilized for this
- * request. Note the callbacks can be shared by multiple
- * requests and the NetworkRequest token utilized to
- * determine to which request the callback relates.
- * @return A {@link NetworkRequest} object identifying the request.
+ * @param request {@link NetworkRequest} describing this request.
+ * @param networkCallback The {@link NetworkCallback} to be utilized for this
+ * request. Note the callback must not be shared - they
+ * uniquely specify this request.
*/
- public NetworkRequest requestNetwork(NetworkCapabilities need,
- NetworkCallbackListener networkCallbackListener) {
- return sendRequestForNetwork(need, networkCallbackListener, 0, REQUEST, TYPE_NONE);
+ public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback) {
+ sendRequestForNetwork(request.networkCapabilities, networkCallback, 0,
+ REQUEST, TYPE_NONE);
}
/**
@@ -2240,53 +2231,53 @@ public class ConnectivityManager {
* by a timeout.
*
* This function behaves identically to the non-timedout version, but if a suitable
- * network is not found within the given time (in Seconds) the
- * {@link NetworkCallbackListener#unavailable} callback is called. The request must
+ * network is not found within the given time (in milliseconds) the
+ * {@link NetworkCallback#unavailable} callback is called. The request must
* still be released normally by calling {@link releaseNetworkRequest}.
- * @param need {@link NetworkCapabilities} required by this request.
- * @param networkCallbackListener The callbacks to be utilized for this request. Note
- * the callbacks can be shared by multiple requests and
- * the NetworkRequest token utilized to determine to which
- * request the callback relates.
- * @param timeoutSec The time in seconds to attempt looking for a suitable network
- * before {@link NetworkCallbackListener#unavailable} is called.
- * @return A {@link NetworkRequest} object identifying the request.
+ * @param request {@link NetworkRequest} describing this request.
+ * @param networkCallback The callbacks to be utilized for this request. Note
+ * the callbacks must not be shared - they uniquely specify
+ * this request.
+ * @param timeoutMs The time in milliseconds to attempt looking for a suitable network
+ * before {@link NetworkCallback#unavailable} is called.
* @hide
*/
- public NetworkRequest requestNetwork(NetworkCapabilities need,
- NetworkCallbackListener networkCallbackListener, int timeoutSec) {
- return sendRequestForNetwork(need, networkCallbackListener, timeoutSec, REQUEST,
- TYPE_NONE);
+ public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback,
+ int timeoutMs) {
+ sendRequestForNetwork(request.networkCapabilities, networkCallback, timeoutMs,
+ REQUEST, TYPE_NONE);
}
/**
- * The maximum number of seconds the framework will look for a suitable network
+ * The maximum number of milliseconds the framework will look for a suitable network
* during a timeout-equiped call to {@link requestNetwork}.
* {@hide}
*/
- public final static int MAX_NETWORK_REQUEST_TIMEOUT_SEC = 100 * 60;
+ public final static int MAX_NETWORK_REQUEST_TIMEOUT_MS = 100 * 60 * 1000;
/**
* The lookup key for a {@link Network} object included with the intent after
* succesfully finding a network for the applications request. Retrieve it with
* {@link android.content.Intent#getParcelableExtra(String)}.
+ * @hide
*/
public static final String EXTRA_NETWORK_REQUEST_NETWORK = "networkRequestNetwork";
/**
- * The lookup key for a {@link NetworkCapabilities} object included with the intent after
+ * The lookup key for a {@link NetworkRequest} object included with the intent after
* succesfully finding a network for the applications request. Retrieve it with
* {@link android.content.Intent#getParcelableExtra(String)}.
+ * @hide
*/
- public static final String EXTRA_NETWORK_REQUEST_NETWORK_CAPABILITIES =
- "networkRequestNetworkCapabilities";
+ public static final String EXTRA_NETWORK_REQUEST_NETWORK_REQUEST =
+ "networkRequestNetworkRequest";
/**
* Request a network to satisfy a set of {@link NetworkCapabilities}.
*
- * This function behavies identically to the callback-equiped version, but instead
- * of {@link NetworkCallbackListener} a {@link PendingIntent} is used. This means
+ * This function behavies identically to the version that takes a NetworkCallback, but instead
+ * of {@link NetworkCallback} a {@link PendingIntent} is used. This means
* the request may outlive the calling application and get called back when a suitable
* network is found.
* <p>
@@ -2295,10 +2286,10 @@ public class ConnectivityManager {
* &lt;receiver&gt; tag in an AndroidManifest.xml file
* <p>
* The operation Intent is delivered with two extras, a {@link Network} typed
- * extra called {@link #EXTRA_NETWORK_REQUEST_NETWORK} and a {@link NetworkCapabilities}
- * typed extra called {@link #EXTRA_NETWORK_REQUEST_NETWORK_CAPABILITIES} containing
+ * extra called {@link #EXTRA_NETWORK_REQUEST_NETWORK} and a {@link NetworkRequest}
+ * typed extra called {@link #EXTRA_NETWORK_REQUEST_NETWORK_REQUEST} containing
* the original requests parameters. It is important to create a new,
- * {@link NetworkCallbackListener} based request before completing the processing of the
+ * {@link NetworkCallback} based request before completing the processing of the
* Intent to reserve the network or it will be released shortly after the Intent
* is processed.
* <p>
@@ -2306,51 +2297,49 @@ public class ConnectivityManager {
* two Intents defined by {@link Intent#filterEquals}), then it will be removed and
* replaced by this one, effectively releasing the previous {@link NetworkRequest}.
* <p>
- * The request may be released normally by calling {@link #releaseNetworkRequest}.
+ * The request may be released normally by calling {@link #unregisterNetworkCallback}.
*
- * @param need {@link NetworkCapabilities} required by this request.
+ * @param request {@link NetworkRequest} describing this request.
* @param operation Action to perform when the network is available (corresponds
- * to the {@link NetworkCallbackListener#onAvailable} call. Typically
+ * to the {@link NetworkCallback#onAvailable} call. Typically
* comes from {@link PendingIntent#getBroadcast}.
- * @return A {@link NetworkRequest} object identifying the request.
+ * @hide
*/
- public NetworkRequest requestNetwork(NetworkCapabilities need, PendingIntent operation) {
+ public void requestNetwork(NetworkRequest request, PendingIntent operation) {
try {
- return mService.pendingRequestForNetwork(need, operation);
+ mService.pendingRequestForNetwork(request.networkCapabilities, operation);
} catch (RemoteException e) {}
- return null;
}
/**
* Registers to receive notifications about all networks which satisfy the given
- * {@link NetworkCapabilities}. The callbacks will continue to be called until
- * either the application exits or the request is released using
- * {@link #releaseNetworkRequest}.
+ * {@link NetworkRequest}. The callbacks will continue to be called until
+ * either the application exits or {@link #unregisterNetworkCallback} is called
*
- * @param need {@link NetworkCapabilities} required by this request.
- * @param networkCallbackListener The {@link NetworkCallbackListener} to be called as suitable
- * networks change state.
- * @return A {@link NetworkRequest} object identifying the request.
+ * @param request {@link NetworkRequest} describing this request.
+ * @param networkCallback The {@link NetworkCallback} that the system will call as suitable
+ * networks change state.
*/
- public NetworkRequest listenForNetwork(NetworkCapabilities need,
- NetworkCallbackListener networkCallbackListener) {
- return sendRequestForNetwork(need, networkCallbackListener, 0, LISTEN, TYPE_NONE);
+ public void registerNetworkCallback(NetworkRequest request, NetworkCallback networkCallback) {
+ sendRequestForNetwork(request.networkCapabilities, networkCallback, 0, LISTEN, TYPE_NONE);
}
/**
- * Releases a {@link NetworkRequest} generated either through a {@link #requestNetwork}
- * or a {@link #listenForNetwork} call. The {@link NetworkCallbackListener} given in the
- * earlier call may continue receiving calls until the
- * {@link NetworkCallbackListener#onReleased} function is called, signifying the end
- * of the request.
+ * Unregisters callbacks about and possibly releases networks originating from
+ * {@link #requestNetwork} and {@link #registerNetworkCallback} calls. If the
+ * given {@code NetworkCallback} had previosuly been used with {@code #requestNetwork},
+ * any networks that had been connected to only to satisfy that request will be
+ * disconnected.
*
- * @param networkRequest The {@link NetworkRequest} generated by an earlier call to
- * {@link #requestNetwork} or {@link #listenForNetwork}.
+ * @param networkCallback The {@link NetworkCallback} used when making the request.
*/
- public void releaseNetworkRequest(NetworkRequest networkRequest) {
- if (networkRequest == null) throw new IllegalArgumentException("null NetworkRequest");
+ public void unregisterNetworkCallback(NetworkCallback networkCallback) {
+ if (networkCallback == null || networkCallback.networkRequest == null ||
+ networkCallback.networkRequest.requestId == REQUEST_ID_UNSET) {
+ throw new IllegalArgumentException("Invalid NetworkCallback");
+ }
try {
- mService.releaseNetworkRequest(networkRequest);
+ mService.releaseNetworkRequest(networkCallback.networkRequest);
} catch (RemoteException e) {}
}
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index d933f26..318aabe 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -29,8 +29,9 @@ import javax.net.SocketFactory;
/**
* Identifies a {@code Network}. This is supplied to applications via
- * {@link ConnectivityManager.NetworkCallbackListener} in response to
- * {@link ConnectivityManager#requestNetwork} or {@link ConnectivityManager#listenForNetwork}.
+ * {@link ConnectivityManager.NetworkCallback} in response to the active
+ * {@link ConnectivityManager#requestNetwork} or passive
+ * {@link ConnectivityManager#registerNetworkCallback} calls.
* It is used to direct traffic to the given {@code Network}, either on a {@link Socket} basis
* through a targeted {@link SocketFactory} or process-wide via
* {@link ConnectivityManager#setProcessDefaultNetwork}.
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 7911c72..36dc573 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -24,7 +24,7 @@ import java.util.concurrent.atomic.AtomicInteger;
/**
* Defines a request for a network, made through {@link NetworkRequest.Builder} and used
* to request a network via {@link ConnectivityManager#requestNetwork} or listen for changes
- * via {@link ConnectivityManager#listenForNetwork}.
+ * via {@link ConnectivityManager#registerNetworkCallback}.
*/
public class NetworkRequest implements Parcelable {
/**
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 7b3dc84..1d2f1bf 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -46,7 +46,13 @@ public final class WindowInsets {
* since it would allow them to inadvertently consume unknown insets by returning it.
* @hide
*/
- public static final WindowInsets EMPTY = new WindowInsets(EMPTY_RECT, EMPTY_RECT);
+ public static final WindowInsets CONSUMED;
+
+ static {
+ CONSUMED = new WindowInsets(EMPTY_RECT, EMPTY_RECT);
+ CONSUMED.mSystemWindowInsetsConsumed = true;
+ CONSUMED.mWindowDecorInsetsConsumed = true;
+ }
/** @hide */
public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets) {
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 2b4677c..d426edc 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -605,21 +605,21 @@ public interface WindowManagerPolicy {
public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation);
/**
- * Return whether the given window should forcibly hide everything
- * behind it. Typically returns true for the keyguard.
+ * Return whether the given window is forcibly hiding all windows except windows with
+ * FLAG_SHOW_WHEN_LOCKED set. Typically returns true for the keyguard.
*/
- public boolean doesForceHide(WindowManager.LayoutParams attrs);
+ public boolean isForceHiding(WindowManager.LayoutParams attrs);
/**
- * Return whether the given window can become one that passes doesForceHide() test.
+ * Return whether the given window can become one that passes isForceHiding() test.
* Typically returns true for the StatusBar.
*/
public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs);
/**
* Determine if a window that is behind one that is force hiding
- * (as determined by {@link #doesForceHide}) should actually be hidden.
+ * (as determined by {@link #isForceHiding}) should actually be hidden.
* For example, typically returns false for the status bar. Be careful
* to return false for any window that you may hide yourself, since this
* will conflict with what you set.
@@ -830,13 +830,11 @@ public interface WindowManagerPolicy {
* setting the window's frame, either here or in finishLayout().
*
* @param win The window being positioned.
- * @param attrs The LayoutParams of the window.
* @param attached For sub-windows, the window it is attached to; this
* window will already have had layoutWindow() called on it
* so you can use its Rect. Otherwise null.
*/
- public void layoutWindowLw(WindowState win,
- WindowManager.LayoutParams attrs, WindowState attached);
+ public void layoutWindowLw(WindowState win, WindowState attached);
/**
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index 8a9cb22..ea36e37 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -20,6 +20,7 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
@@ -246,6 +247,13 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar
}
@Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ init(getContext());
+ requestApplyInsets();
+ }
+
+ @Override
public void onWindowSystemUiVisibilityChanged(int visible) {
super.onWindowSystemUiVisibilityChanged(visible);
pullChildren();
@@ -329,7 +337,7 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar
// insets in all cases, we need to know the measured size of the various action
// bar elements. onApplyWindowInsets() happens before the measure pass, so we can't
// do that here. Instead we will take this up in onMeasure().
- return WindowInsets.EMPTY;
+ return WindowInsets.CONSUMED;
}
@Override
diff --git a/core/res/res/anim-land/task_close_enter.xml b/core/res/res/anim-land/task_close_enter.xml
deleted file mode 100644
index facc42b..0000000
--- a/core/res/res/anim-land/task_close_enter.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2009, 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">
-
- <alpha android:fromAlpha="0" android:toAlpha="1.0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quad"
- android:startOffset="300"
- android:duration="400"/>
-
- <translate android:fromXDelta="-120%" android:toXDelta="0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quint"
- android:startOffset="300"
- android:duration="400" />
-
- <scale android:fromXScale=".5" android:toXScale="1.0"
- android:fromYScale=".5" android:toYScale="1.0"
- android:pivotY="50%p" android:pivotX="0%p"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quad"
- android:startOffset="300"
- android:duration="400" />
-</set> \ No newline at end of file
diff --git a/core/res/res/anim-land/task_close_exit.xml b/core/res/res/anim-land/task_close_exit.xml
deleted file mode 100644
index e104c33..0000000
--- a/core/res/res/anim-land/task_close_exit.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2009, 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"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/accelerate_quad"
- android:duration="300"/>
-
- <translate android:fromXDelta="0" android:toXDelta="120%"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/accelerate_cubic"
- android:duration="300"/>
-
- <scale android:fromXScale="1.0" android:toXScale="0.5"
- android:fromYScale="1.0" android:toYScale="0.5"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:pivotY="50%p" android:pivotX="100%p"
- android:interpolator="@interpolator/accelerate_quad"
- android:duration="300" />
-
- <!-- This is needed to keep the animation running while task_open_enter completes -->
- <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
- android:duration="700" />
-</set> \ No newline at end of file
diff --git a/core/res/res/anim-land/task_open_enter.xml b/core/res/res/anim-land/task_open_enter.xml
deleted file mode 100644
index dc7c7a9..0000000
--- a/core/res/res/anim-land/task_open_enter.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2009, 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">
-
- <alpha android:fromAlpha="0" android:toAlpha="1.0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quad"
- android:startOffset="300"
- android:duration="400"/>
-
- <translate android:fromXDelta="120%" android:toXDelta="0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quint"
- android:startOffset="300"
- android:duration="400" />
-
- <scale android:fromXScale=".5" android:toXScale="1.0"
- android:fromYScale=".5" android:toYScale="1.0"
- android:pivotY="50%p" android:pivotX="100%p"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quad"
- android:startOffset="300"
- android:duration="400" />
-</set> \ No newline at end of file
diff --git a/core/res/res/anim-land/task_open_exit.xml b/core/res/res/anim-land/task_open_exit.xml
deleted file mode 100644
index 701afa6..0000000
--- a/core/res/res/anim-land/task_open_exit.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2009, 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"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/accelerate_quad"
- android:duration="300"/>
-
- <translate android:fromXDelta="0" android:toXDelta="-120%"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/accelerate_cubic"
- android:duration="300"/>
-
- <scale android:fromXScale="1.0" android:toXScale="0.5"
- android:fromYScale="1.0" android:toYScale="0.5"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:pivotY="50%p" android:pivotX="0%p"
- android:interpolator="@interpolator/accelerate_quad"
- android:duration="300" />
-
- <!-- This is needed to keep the animation running while task_open_enter completes -->
- <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
- android:duration="700" />
-</set> \ No newline at end of file
diff --git a/core/res/res/anim-sw720dp/task_close_enter.xml b/core/res/res/anim-sw720dp/task_close_enter.xml
deleted file mode 100644
index e25978b..0000000
--- a/core/res/res/anim-sw720dp/task_close_enter.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2009, 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">
-
- <alpha android:fromAlpha="0" android:toAlpha="1.0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quad"
- android:startOffset="500"
- android:duration="400"/>
-
- <translate android:fromYDelta="-50%" android:toYDelta="0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quint"
- android:startOffset="500"
- android:duration="400" />
-
- <scale android:fromXScale=".8" android:toXScale="1.0"
- android:fromYScale=".8" android:toYScale="1.0"
- android:pivotX="50%p" android:pivotY="0%p"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quad"
- android:startOffset="500"
- android:duration="400" />
-</set> \ No newline at end of file
diff --git a/core/res/res/anim-sw720dp/task_close_exit.xml b/core/res/res/anim-sw720dp/task_close_exit.xml
deleted file mode 100644
index 2d7e2a6..0000000
--- a/core/res/res/anim-sw720dp/task_close_exit.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2009, 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"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/accelerate_quad"
- android:duration="350"/>
-
- <translate android:fromYDelta="0" android:toYDelta="50%"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/accelerate_cubic"
- android:duration="350"/>
-
- <scale android:fromXScale="1.0" android:toXScale="0.8"
- android:fromYScale="1.0" android:toYScale="0.8"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:pivotX="50%p" android:pivotY="100%p"
- android:interpolator="@interpolator/accelerate_quad"
- android:duration="350" />
-
- <!-- This is needed to keep the animation running while task_close_enter completes -->
- <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
- android:duration="900" />
-</set> \ No newline at end of file
diff --git a/core/res/res/anim-sw720dp/task_open_enter.xml b/core/res/res/anim-sw720dp/task_open_enter.xml
deleted file mode 100644
index d583b6e..0000000
--- a/core/res/res/anim-sw720dp/task_open_enter.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2009, 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">
-
- <alpha android:fromAlpha="0" android:toAlpha="1.0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quad"
- android:startOffset="500"
- android:duration="400"/>
-
- <translate android:fromYDelta="50%" android:toYDelta="0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quint"
- android:startOffset="500"
- android:duration="400" />
-
- <scale android:fromXScale=".8" android:toXScale="1.0"
- android:fromYScale=".8" android:toYScale="1.0"
- android:pivotX="50%p" android:pivotY="100%p"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quad"
- android:startOffset="500"
- android:duration="400" />
-</set> \ No newline at end of file
diff --git a/core/res/res/anim-sw720dp/task_open_exit.xml b/core/res/res/anim-sw720dp/task_open_exit.xml
deleted file mode 100644
index dd25a0c..0000000
--- a/core/res/res/anim-sw720dp/task_open_exit.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2009, 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"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/accelerate_quad"
- android:duration="350"/>
-
- <translate android:fromYDelta="0" android:toYDelta="-50%"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/accelerate_cubic"
- android:duration="350"/>
-
- <scale android:fromXScale="1.0" android:toXScale="0.8"
- android:fromYScale="1.0" android:toYScale="0.8"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:pivotX="50%p" android:pivotY="0%p"
- android:interpolator="@interpolator/accelerate_quad"
- android:duration="350" />
-
- <!-- This is needed to keep the animation running while task_open_enter completes -->
- <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
- android:duration="900" />
-</set> \ No newline at end of file
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f1d9dc3..0ddfeb6 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -460,7 +460,7 @@
<string name="user_owner_label">Personal apps</string>
<!-- Label for a corporate profile in the intent forwarding app. -->
- <string name="managed_profile_label">Android for Work</string>
+ <string name="managed_profile_label">Android Work</string>
<!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permgrouplab_costMoney">Services that cost you money</string>
diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
index 79fe4d3..ef3d0d7 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -39,6 +39,7 @@ namespace uirenderer {
TessellationCache::Description::Description()
: type(kNone)
+ , aa(false)
, cap(SkPaint::kDefault_Cap)
, style(SkPaint::kFill_Style)
, strokeWidth(1.0f) {
@@ -47,6 +48,7 @@ TessellationCache::Description::Description()
TessellationCache::Description::Description(Type type)
: type(type)
+ , aa(false)
, cap(SkPaint::kDefault_Cap)
, style(SkPaint::kFill_Style)
, strokeWidth(1.0f) {
@@ -55,6 +57,7 @@ TessellationCache::Description::Description(Type type)
TessellationCache::Description::Description(Type type, const SkPaint* paint)
: type(type)
+ , aa(paint->isAntiAlias())
, cap(paint->getStrokeCap())
, style(paint->getStyle())
, strokeWidth(paint->getStrokeWidth()) {
@@ -63,6 +66,7 @@ TessellationCache::Description::Description(Type type, const SkPaint* paint)
hash_t TessellationCache::Description::hash() const {
uint32_t hash = JenkinsHashMix(0, type);
+ hash = JenkinsHashMix(hash, aa);
hash = JenkinsHashMix(hash, cap);
hash = JenkinsHashMix(hash, style);
hash = JenkinsHashMix(hash, android::hash_type(strokeWidth));
diff --git a/libs/hwui/TessellationCache.h b/libs/hwui/TessellationCache.h
index 8f37230..d4ff943 100644
--- a/libs/hwui/TessellationCache.h
+++ b/libs/hwui/TessellationCache.h
@@ -55,6 +55,7 @@ public:
};
Type type;
+ bool aa;
SkPaint::Cap cap;
SkPaint::Style style;
float strokeWidth;
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 3fa8b99..e8f3745 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -34,7 +34,6 @@ import android.os.Handler;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
-import android.util.Log;
import android.util.Slog;
import android.view.ContextThemeWrapper;
import android.view.View;
@@ -126,25 +125,16 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
updateNotification();
}
- private void cancelOther(int showing) {
- if (mShowing != SHOWING_NOTHING && mShowing != showing) {
- mNoMan.cancel(TAG_NOTIFICATION, ID_NOTIFICATION); // workaround no HUN on updates
- }
- }
-
private void updateNotification() {
Slog.d(TAG, "updateNotification mWarning=" + mWarning
+ " mSaver=" + mSaver + " mInvalidCharger=" + mInvalidCharger);
if (mInvalidCharger) {
- cancelOther(SHOWING_INVALID_CHARGER);
showInvalidChargerNotification();
mShowing = SHOWING_INVALID_CHARGER;
} else if (mWarning) {
- cancelOther(SHOWING_WARNING);
showWarningNotification();
mShowing = SHOWING_WARNING;
} else if (mSaver) {
- cancelOther(SHOWING_SAVER);
showSaverNotification();
mShowing = SHOWING_SAVER;
} else {
@@ -312,6 +302,12 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
@Override
public void dismissInvalidChargerWarning() {
+ dismissInvalidChargerNotification();
+ mFallbackDialogs.dismissInvalidChargerWarning();
+ }
+
+ private void dismissInvalidChargerNotification() {
+ Slog.i(TAG, "dismissing invalid charger notification");
mInvalidCharger = false;
updateNotification();
}
@@ -355,10 +351,12 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
- Log.d(TAG, "got " + action);
+ Slog.i(TAG, "Received " + action);
if (action.equals(ACTION_SHOW_FALLBACK_WARNING)) {
+ dismissLowBatteryNotification();
mFallbackDialogs.showLowBatteryWarning(false /*playSound*/);
} else if (action.equals(ACTION_SHOW_FALLBACK_CHARGER)) {
+ dismissInvalidChargerNotification();
mFallbackDialogs.showInvalidChargerWarning();
} else if (action.equals(ACTION_SHOW_BATTERY_SETTINGS)) {
dismissLowBatteryNotification();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 506f9dc..20684a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -133,7 +133,6 @@ public abstract class BaseStatusBar extends SystemUI implements
// for heads up notifications
protected HeadsUpNotificationView mHeadsUpNotificationView;
protected int mHeadsUpNotificationDecay;
- protected long mInterruptingNotificationTime;
// used to notify status bar for suppressing notification LED
protected boolean mPanelSlightlyVisible;
@@ -1420,6 +1419,9 @@ public abstract class BaseStatusBar extends SystemUI implements
&& !TextUtils.equals(notification.getNotification().tickerText,
oldEntry.notification.getNotification().tickerText);
+ final boolean shouldInterrupt = shouldInterrupt(notification);
+ final boolean alertAgain = alertAgain(oldEntry);
+ boolean updateSuccessful = false;
if (contentsUnchanged && bigContentsUnchanged && headsUpContentsUnchanged
&& publicUnchanged) {
if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
@@ -1439,8 +1441,6 @@ public abstract class BaseStatusBar extends SystemUI implements
}
}
- final boolean shouldInterrupt = shouldInterrupt(notification);
- final boolean alertAgain = alertAgain(oldEntry);
if (wasHeadsUp) {
if (shouldInterrupt) {
updateHeadsUpViews(oldEntry, notification);
@@ -1462,24 +1462,52 @@ public abstract class BaseStatusBar extends SystemUI implements
}
mNotificationData.updateRanking(ranking);
updateNotifications();
+ updateSuccessful = true;
}
catch (RuntimeException e) {
// It failed to add cleanly. Log, and remove the view from the panel.
Log.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
- removeNotificationViews(key, ranking);
- addNotificationViews(notification, ranking);
}
- } else {
+ }
+ if (!updateSuccessful) {
if (DEBUG) Log.d(TAG, "not reusing notification for key: " + key);
- if (DEBUG) Log.d(TAG, "contents was " + (contentsUnchanged ? "unchanged" : "changed"));
- removeNotificationViews(key, ranking);
- addNotificationViews(notification, ranking);
- final NotificationData.Entry newEntry = mNotificationData.findByKey(key);
- final boolean userChangedExpansion = oldEntry.row.hasUserChangedExpansion();
- if (userChangedExpansion) {
- boolean userExpanded = oldEntry.row.isUserExpanded();
- newEntry.row.setUserExpanded(userExpanded);
- newEntry.row.notifyHeightChanged();
+ if (wasHeadsUp) {
+ if (shouldInterrupt) {
+ if (DEBUG) Log.d(TAG, "rebuilding heads up for key: " + key);
+ Entry newEntry = new Entry(notification, null);
+ ViewGroup holder = mHeadsUpNotificationView.getHolder();
+ if (inflateViewsForHeadsUp(newEntry, holder)) {
+ mHeadsUpNotificationView.showNotification(newEntry);
+ if (alertAgain) {
+ resetHeadsUpDecayTimer();
+ }
+ } else {
+ Log.w(TAG, "Couldn't create new updated headsup for package "
+ + contentView.getPackage());
+ }
+ } else {
+ if (DEBUG) Log.d(TAG, "releasing heads up for key: " + key);
+ oldEntry.notification = notification;
+ mHeadsUpNotificationView.releaseAndClose();
+ return;
+ }
+ } else {
+ if (shouldInterrupt && alertAgain) {
+ if (DEBUG) Log.d(TAG, "reposting to invoke heads up for key: " + key);
+ removeNotificationViews(key, ranking);
+ addNotificationInternal(notification, ranking); //this will pop the headsup
+ } else {
+ if (DEBUG) Log.d(TAG, "rebuilding update in place for key: " + key);
+ removeNotificationViews(key, ranking);
+ addNotificationViews(notification, ranking);
+ final NotificationData.Entry newEntry = mNotificationData.findByKey(key);
+ final boolean userChangedExpansion = oldEntry.row.hasUserChangedExpansion();
+ if (userChangedExpansion) {
+ boolean userExpanded = oldEntry.row.isUserExpanded();
+ newEntry.row.setUserExpanded(userExpanded);
+ newEntry.row.notifyHeightChanged();
+ }
+ }
}
}
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 a2dbf75..b23992d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1068,8 +1068,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
Entry interruptionCandidate = new Entry(notification, null);
ViewGroup holder = mHeadsUpNotificationView.getHolder();
if (inflateViewsForHeadsUp(interruptionCandidate, holder)) {
- mInterruptingNotificationTime = System.currentTimeMillis();
-
// 1. Populate mHeadsUpNotificationView
mHeadsUpNotificationView.showNotification(interruptionCandidate);
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 0f6c4b2..0a48e34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -78,8 +78,10 @@ public class HeadsUpNotificationView extends FrameLayout implements SwipeHelper.
}
public boolean showNotification(NotificationData.Entry headsUp) {
- // bump any previous heads up back to the shade
- release();
+ if (mHeadsUp != null && headsUp != null && !mHeadsUp.key.equals(headsUp.key)) {
+ // bump any previous heads up back to the shade
+ release();
+ }
mHeadsUp = headsUp;
if (mContentHolder != null) {
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 d6ff4fc..cbad9dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -186,7 +186,7 @@ public class StackScrollAlgorithm {
if (!child.isTransparent()) {
// Only update the previous values if we are not transparent,
// otherwise we would clip to a transparent view.
- previousNotificationStart = newYTranslation + child.getClipTopAmount();
+ previousNotificationStart = newYTranslation + state.clipTopAmount;
previousNotificationEnd = newNotificationEnd;
previousNotificationIsSwiped = child.getTranslationX() != 0;
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index cacf66b..a86f466 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -435,6 +435,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
* be done once per window. */
private WindowState mWinDismissingKeyguard;
+ /** The window that is currently showing "over" the keyguard. If there is an app window
+ * belonging to another app on top of this the keyguard shows. If there is a fullscreen
+ * app window under this, still dismiss the keyguard but don't show the app underneath. Show
+ * the wallpaper. */
+ private WindowState mWinShowWhenLocked;
+
boolean mShowingLockscreen;
boolean mShowingDream;
boolean mDreamingLockscreen;
@@ -1669,8 +1675,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
@Override
- public boolean doesForceHide(WindowManager.LayoutParams attrs) {
- return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
+ public boolean isForceHiding(WindowManager.LayoutParams attrs) {
+ return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
+ (isKeyguardHostWindow(attrs) && isKeyguardSecureIncludingHidden());
}
@Override
@@ -3119,10 +3126,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
@Override
- public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs,
- WindowState attached) {
+ public void layoutWindowLw(WindowState win, WindowState attached) {
// we've already done the status bar
- if ((win == mStatusBar && !doesForceHide(attrs)) || win == mNavigationBar) {
+ final WindowManager.LayoutParams attrs = win.getAttrs();
+ if ((win == mStatusBar && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) == 0) ||
+ win == mNavigationBar) {
return;
}
final boolean isDefaultDisplay = win.isDefaultDisplay();
@@ -3603,12 +3611,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mDismissKeyguard = DISMISS_KEYGUARD_NONE;
mShowingLockscreen = false;
mShowingDream = false;
+ mWinShowWhenLocked = null;
}
/** {@inheritDoc} */
@Override
- public void applyPostLayoutPolicyLw(WindowState win,
- WindowManager.LayoutParams attrs) {
+ public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs) {
if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
+ win.isVisibleOrBehindKeyguardLw());
final int fl = PolicyControl.getWindowFlags(win, attrs);
@@ -3646,9 +3654,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
+ final boolean secureKeyguard = isKeyguardSecure();
if (appWindow) {
- if (showWhenLocked || (dismissKeyguard && !isKeyguardSecure())) {
+ if (showWhenLocked || (dismissKeyguard && !secureKeyguard)) {
+ // Remove any previous windows with the same appToken.
mAppsToBeHidden.remove(win.getAppToken());
+ if (mAppsToBeHidden.isEmpty() && showWhenLocked &&
+ isKeyguardSecureIncludingHidden()) {
+ mWinShowWhenLocked = win;
+ mHideLockScreen = true;
+ mForceStatusBarFromKeyguard = false;
+ }
} else {
mAppsToBeHidden.add(win.getAppToken());
}
@@ -3670,13 +3686,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mDismissKeyguard = mWinDismissingKeyguard == win ?
DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
mWinDismissingKeyguard = win;
- mForceStatusBarFromKeyguard = mShowingLockscreen && isKeyguardSecure();
+ mForceStatusBarFromKeyguard = mShowingLockscreen && secureKeyguard;
}
}
if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
mAllowLockscreenWhenOn = true;
}
}
+
+ if (mWinShowWhenLocked != null &&
+ mWinShowWhenLocked.getAppToken() != win.getAppToken()) {
+ win.hideLw(false);
+ }
}
}
}
@@ -3684,6 +3705,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
@Override
public int finishPostLayoutPolicyLw() {
+ if (mWinShowWhenLocked != null &&
+ mWinShowWhenLocked != mTopFullscreenOpaqueWindowState) {
+ // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the
+ // fullscreen window.
+ // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not.
+ mWinShowWhenLocked.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
+ mTopFullscreenOpaqueWindowState.hideLw(false);
+ mTopFullscreenOpaqueWindowState = mWinShowWhenLocked;
+ }
+
int changes = 0;
boolean topIsFullscreen = false;
@@ -4639,6 +4670,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return mKeyguardDelegate.isSecure();
}
+ // Returns true if keyguard is currently locked whether or not it is currently hidden.
+ private boolean isKeyguardSecureIncludingHidden() {
+ return mKeyguardDelegate.isSecure() && mKeyguardDelegate.isShowing();
+ }
+
/** {@inheritDoc} */
public boolean inKeyguardRestrictedKeyInputMode() {
if (mKeyguardDelegate == null) return false;
diff --git a/rs/java/android/renderscript/FieldPacker.java b/rs/java/android/renderscript/FieldPacker.java
index 0e57232..c9bba69 100644
--- a/rs/java/android/renderscript/FieldPacker.java
+++ b/rs/java/android/renderscript/FieldPacker.java
@@ -233,6 +233,9 @@ public class FieldPacker {
if (obj != null) {
if (RenderScript.sPointerSize == 8) {
addI64(obj.getID(null));
+ addI64(0);
+ addI64(0);
+ addI64(0);
}
else {
addI32((int)obj.getID(null));
@@ -240,6 +243,9 @@ public class FieldPacker {
} else {
if (RenderScript.sPointerSize == 8) {
addI64(0);
+ addI64(0);
+ addI64(0);
+ addI64(0);
} else {
addI32(0);
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 657d5ec..00bda06 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -20,7 +20,6 @@ import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
-import static android.net.ConnectivityManager.NetworkCallbackListener;
import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
import static android.net.ConnectivityManager.TYPE_DUMMY;
import static android.net.ConnectivityManager.TYPE_MOBILE;
@@ -5410,7 +5409,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
@Override
public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
- Messenger messenger, int timeoutSec, IBinder binder, int legacyType) {
+ Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
== false) {
enforceConnectivityInternalPermission();
@@ -5418,7 +5417,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
enforceChangePermission();
}
- if (timeoutSec < 0 || timeoutSec > ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_SEC) {
+ if (timeoutMs < 0 || timeoutMs > ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS) {
throw new IllegalArgumentException("Bad timeout specified");
}
NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities(
@@ -5428,9 +5427,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
NetworkRequestInfo.REQUEST);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri));
- if (timeoutSec > 0) {
+ if (timeoutMs > 0) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NETWORK_REQUEST,
- nri), timeoutSec * 1000);
+ nri), timeoutMs);
}
return networkRequest;
}
@@ -5694,7 +5693,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
int a2 = 0;
switch (notificationType) {
case ConnectivityManager.CALLBACK_LOSING:
- a1 = 30; // TODO - read this from NetworkMonitor
+ a1 = 30 * 1000; // TODO - read this from NetworkMonitor
// fall through
case ConnectivityManager.CALLBACK_PRECHECK:
case ConnectivityManager.CALLBACK_AVAILABLE:
diff --git a/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
new file mode 100644
index 0000000..32bcb69
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
@@ -0,0 +1,112 @@
+/*
+ * 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.annotation.Nullable;
+import android.hardware.hdmi.IHdmiControlCallback;
+import android.hardware.hdmi.HdmiCec;
+import android.hardware.hdmi.HdmiCecDeviceInfo;
+import android.hardware.hdmi.HdmiCecMessage;
+import android.os.RemoteException;
+import android.util.Slog;
+
+/**
+ * Handles CEC command &lt;Active Source&gt;.
+ *
+ * <p>Used by feature actions that need to handle the command in their flow.
+ */
+final class ActiveSourceHandler {
+ private static final String TAG = "ActiveSourceHandler";
+
+ private final HdmiControlService mService;
+ private final int mSourceAddress;
+ private final int mSourcePath;
+ @Nullable private final IHdmiControlCallback mCallback;
+
+ static ActiveSourceHandler create(HdmiControlService service, int sourceAddress,
+ int sourcePath, IHdmiControlCallback callback) {
+ if (service == null) {
+ Slog.e(TAG, "Wrong arguments");
+ return null;
+ }
+ return new ActiveSourceHandler(service, sourceAddress, sourcePath, callback);
+ }
+
+ private ActiveSourceHandler(HdmiControlService service, int sourceAddress, int sourcePath,
+ IHdmiControlCallback callback) {
+ mService = service;
+ mSourceAddress = sourceAddress;
+ mSourcePath = sourcePath;
+ mCallback = callback;
+ }
+
+ /**
+ * Handles the incoming active source command.
+ *
+ * @param deviceLogicalAddress logical address of the device to be the active source
+ * @param routingPath routing path of the device to be the active source
+ */
+ void process(int deviceLogicalAddress, int routingPath) {
+ if (mSourcePath == routingPath && mService.getActiveSource() == mSourceAddress) {
+ invokeCallback(HdmiCec.RESULT_SUCCESS);
+ return;
+ }
+ HdmiCecDeviceInfo device = mService.getDeviceInfo(deviceLogicalAddress);
+ if (device == null) {
+ // TODO: Start new device action (Device Discovery) sequence 5.
+ }
+
+ if (!mService.isInPresetInstallationMode()) {
+ int prevActiveInput = mService.getActiveInput();
+ mService.updateActiveDevice(deviceLogicalAddress, routingPath);
+ if (prevActiveInput != mService.getActiveInput()) {
+ // TODO: change port input here.
+ }
+ invokeCallback(HdmiCec.RESULT_SUCCESS);
+ } else {
+ // TV is in a mode that should keep its current source/input from
+ // being changed for its operation. Reclaim the active source
+ // or switch the port back to the one used for the current mode.
+ if (mService.getActiveSource() == mSourceAddress) {
+ HdmiCecMessage activeSource =
+ HdmiCecMessageBuilder.buildActiveSource(mSourceAddress, mSourcePath);
+ mService.sendCecCommand(activeSource);
+ mService.updateActiveDevice(deviceLogicalAddress, routingPath);
+ invokeCallback(HdmiCec.RESULT_SUCCESS);
+ } else {
+ int activePath = mService.getActivePath();
+ mService.sendCecCommand(HdmiCecMessageBuilder.buildRoutingChange(mSourceAddress,
+ routingPath, activePath));
+ // TODO: Start port select action here
+ // PortSelectAction action = new PortSelectAction(mService, mSourceAddress,
+ // activePath, mCallback);
+ // mService.addActionAndStart(action);
+ }
+ }
+ }
+
+ private void invokeCallback(int result) {
+ if (mCallback == null) {
+ return;
+ }
+ try {
+ mCallback.onComplete(result);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Callback failed:" + e);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
new file mode 100644
index 0000000..f170de0
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
@@ -0,0 +1,223 @@
+/*
+ * 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.IHdmiControlCallback;
+import android.hardware.hdmi.HdmiCecDeviceInfo;
+import android.hardware.hdmi.HdmiCec;
+import android.hardware.hdmi.HdmiCecMessage;
+import android.os.RemoteException;
+import android.util.Slog;
+
+/**
+ * Handles an action that selects a logical device as a new active source.
+ *
+ * Triggered by {@link HdmiTvClient}, attempts to select the given target device
+ * for a new active source. It does its best to wake up the target in standby mode
+ * before issuing the command &gt;Set Stream path&lt;.
+ */
+final class DeviceSelectAction extends FeatureAction {
+ private static final String TAG = "DeviceSelect";
+
+ // Time in milliseconds we wait for the device power status to switch to 'Standby'
+ private static final int TIMEOUT_TRANSIT_TO_STANDBY_MS = 5 * 1000;
+
+ // Time in milliseconds we wait for the device power status to turn to 'On'.
+ private static final int TIMEOUT_POWER_ON_MS = 5 * 1000;
+
+ // Time in milliseconds we wait for <Active Source>.
+ private static final int TIMEOUT_ACTIVE_SOURCE_MS = 20 * 1000;
+
+ // The number of times we try to wake up the target device before we give up
+ // and just send <Set Stream Path>.
+ private static final int LOOP_COUNTER_MAX = 20;
+
+ // State in which we wait for <Report Power Status> to come in response to the command
+ // <Give Device Power Status> we have sent.
+ private static final int STATE_WAIT_FOR_REPORT_POWER_STATUS = 1;
+
+ // State in which we wait for the device power status to switch to 'Standby'.
+ // We wait till the status becomes 'Standby' before we send <Set Stream Path>
+ // to wake up the device again.
+ private static final int STATE_WAIT_FOR_DEVICE_TO_TRANSIT_TO_STANDBY = 2;
+
+ // State in which we wait for the device power status to switch to 'on'. We wait
+ // maximum 100 seconds (20 * 5) before we give up and just send <Set Stream Path>.
+ private static final int STATE_WAIT_FOR_DEVICE_POWER_ON = 3;
+
+ // State in which we wait for the <Active Source> in response to the command
+ // <Set Stream Path> we have sent. We wait as much as TIMEOUT_ACTIVE_SOURCE_MS
+ // before we give up and mark the action as failure.
+ private static final int STATE_WAIT_FOR_ACTIVE_SOURCE = 4;
+
+ private final HdmiCecDeviceInfo mTarget;
+ private final IHdmiControlCallback mCallback;
+ private final int mSourcePath;
+
+ private int mPowerStatusCounter = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param service {@link HdmiControlService} instance
+ * @param sourceAddress logical address of TV initiating this action
+ * @param sourcePath physical address of TV
+ * @param target target logical device that will be a new active source
+ * @param callback callback object
+ */
+ public DeviceSelectAction(HdmiControlService service, int sourceAddress, int sourcePath,
+ HdmiCecDeviceInfo target, IHdmiControlCallback callback) {
+ super(service, sourceAddress);
+ mCallback = callback;
+ mSourcePath = sourcePath;
+ mTarget = target;
+ }
+
+ @Override
+ public boolean start() {
+ // TODO: Call the logic that display a banner saying the select action got started.
+ queryDevicePowerStatus();
+ return true;
+ }
+
+ private void queryDevicePowerStatus() {
+ sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
+ mSourceAddress, mTarget.getLogicalAddress()));
+ mState = STATE_WAIT_FOR_REPORT_POWER_STATUS;
+ addTimer(mState, TIMEOUT_MS);
+ }
+
+ @Override
+ public boolean processCommand(HdmiCecMessage cmd) {
+ if (cmd.getSource() != mTarget.getLogicalAddress()) {
+ return false;
+ }
+ int opcode = cmd.getOpcode();
+ byte[] params = cmd.getParams();
+
+ switch (mState) {
+ case STATE_WAIT_FOR_REPORT_POWER_STATUS:
+ if (opcode == HdmiCec.MESSAGE_REPORT_POWER_STATUS && params.length == 1) {
+ return handleReportPowerStatus(params[0]);
+ }
+ return false;
+ case STATE_WAIT_FOR_ACTIVE_SOURCE:
+ if (opcode == HdmiCec.MESSAGE_ACTIVE_SOURCE && params.length == 2) {
+ int activePath = HdmiUtils.twoBytesToInt(params);
+ ActiveSourceHandler.create(mService, mSourceAddress, mSourcePath, mCallback)
+ .process(cmd.getSource(), activePath);
+ finish();
+ return true;
+ }
+ return false;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ private boolean handleReportPowerStatus(int powerStatus) {
+ // TODO: Check TV's own status which might have been updated during the action.
+ // If in 'Standby' or 'Transit to standby', remove the banner
+ // and stop this action. Otherwise, send <Set Stream Path>
+ switch (powerStatus) {
+ case HdmiCec.POWER_STATUS_ON:
+ sendSetStreamPath();
+ return true;
+ case HdmiCec.POWER_STATUS_TRANSIENT_TO_STANDBY:
+ if (mPowerStatusCounter < 4) {
+ mState = STATE_WAIT_FOR_DEVICE_TO_TRANSIT_TO_STANDBY;
+ addTimer(mState, TIMEOUT_TRANSIT_TO_STANDBY_MS);
+ } else {
+ sendSetStreamPath();
+ }
+ return true;
+ case HdmiCec.POWER_STATUS_STANDBY:
+ if (mPowerStatusCounter == 0) {
+ turnOnDevice();
+ } else {
+ sendSetStreamPath();
+ }
+ return true;
+ case HdmiCec.POWER_STATUS_TRANSIENT_TO_ON:
+ if (mPowerStatusCounter < LOOP_COUNTER_MAX) {
+ mState = STATE_WAIT_FOR_DEVICE_POWER_ON;
+ addTimer(mState, TIMEOUT_POWER_ON_MS);
+ } else {
+ sendSetStreamPath();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private void turnOnDevice() {
+ sendRemoteKeyCommand(HdmiConstants.UI_COMMAND_POWER);
+ sendRemoteKeyCommand(HdmiConstants.UI_COMMAND_POWER_ON_FUNCTION);
+ mState = STATE_WAIT_FOR_DEVICE_POWER_ON;
+ addTimer(mState, TIMEOUT_POWER_ON_MS);
+ }
+
+ private void sendSetStreamPath() {
+ sendCommand(HdmiCecMessageBuilder.buildSetStreamPath(
+ mSourceAddress, mTarget.getPhysicalAddress()));
+ mState = STATE_WAIT_FOR_ACTIVE_SOURCE;
+ addTimer(mState, TIMEOUT_ACTIVE_SOURCE_MS);
+ }
+
+ private void sendRemoteKeyCommand(int keyCode) {
+ sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(mSourceAddress,
+ mTarget.getLogicalAddress(), keyCode));
+ sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(mSourceAddress,
+ mTarget.getLogicalAddress()));
+ }
+
+ @Override
+ public void handleTimerEvent(int timeoutState) {
+ if (mState != timeoutState) {
+ Slog.w(TAG, "Timer in a wrong state. Ignored.");
+ return;
+ }
+ switch (mState) {
+ case STATE_WAIT_FOR_REPORT_POWER_STATUS:
+ sendSetStreamPath();
+ break;
+ case STATE_WAIT_FOR_DEVICE_TO_TRANSIT_TO_STANDBY:
+ case STATE_WAIT_FOR_DEVICE_POWER_ON:
+ mPowerStatusCounter++;
+ queryDevicePowerStatus();
+ break;
+ case STATE_WAIT_FOR_ACTIVE_SOURCE:
+ // TODO: Remove the banner
+ // Display banner "Communication failed. Please check your cable or connection"
+ invokeCallback(HdmiCec.RESULT_TIMEOUT);
+ finish();
+ break;
+ }
+ }
+
+ private void invokeCallback(int result) {
+ if (mCallback == null) {
+ return;
+ }
+ try {
+ mCallback.onComplete(result);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Callback failed:" + e);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/FeatureAction.java b/services/core/java/com/android/server/hdmi/FeatureAction.java
index 0ba7773..ae272b4 100644
--- a/services/core/java/com/android/server/hdmi/FeatureAction.java
+++ b/services/core/java/com/android/server/hdmi/FeatureAction.java
@@ -46,8 +46,9 @@ abstract class FeatureAction {
// Timer handler message used for timeout event
protected static final int MSG_TIMEOUT = 100;
- // Default timeout for the incoming command to arrive in response to a request
- protected static final int TIMEOUT_MS = 1000;
+ // Default timeout for the incoming command to arrive in response to a request.
+ // TODO: Consider reading this value from configuration to allow customization.
+ protected static final int TIMEOUT_MS = 2000;
// Default state used in common by all the feature actions.
protected static final int STATE_NONE = 0;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index f869424..a0c635d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -19,6 +19,7 @@ package com.android.server.hdmi;
import android.hardware.hdmi.HdmiCec;
import android.hardware.hdmi.HdmiCecDeviceInfo;
import android.hardware.hdmi.HdmiCecMessage;
+import android.hardware.hdmi.HdmiPortInfo;
import android.os.Handler;
import android.os.Looper;
import android.os.MessageQueue;
@@ -308,6 +309,10 @@ final class HdmiCecController {
return mDeviceInfos.get(logicalAddress);
}
+ HdmiPortInfo[] getPortInfos() {
+ return nativeGetPortInfos(mNativePtr);
+ }
+
/**
* Return the locally hosted logical device of a given type.
*
@@ -641,8 +646,8 @@ final class HdmiCecController {
private static native int nativeGetPhysicalAddress(long controllerPtr);
private static native int nativeGetVersion(long controllerPtr);
private static native int nativeGetVendorId(long controllerPtr);
+ private static native HdmiPortInfo[] nativeGetPortInfos(long controllerPtr);
private static native void nativeSetOption(long controllerPtr, int flag, int value);
private static native void nativeSetAudioReturnChannel(long controllerPtr, boolean flag);
private static native boolean nativeIsConnected(long controllerPtr, int port);
-
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 8bd81ea..6394fe7 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -16,8 +16,11 @@
package com.android.server.hdmi;
+import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.hdmi.HdmiCec;
+import android.hardware.hdmi.HdmiCecDeviceInfo;
import android.hardware.hdmi.HdmiCecMessage;
+import android.os.RemoteException;
import android.util.Slog;
import java.util.Locale;
@@ -55,6 +58,31 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
}
}
+ /**
+ * Performs the action 'device select', or 'one touch play' initiated by TV.
+ *
+ * @param targetAddress logical address of the device to select
+ * @param callback callback object to report the result with
+ */
+ void deviceSelect(int targetAddress, IHdmiControlCallback callback) {
+ HdmiCecDeviceInfo targetDevice = mService.getDeviceInfo(targetAddress);
+ if (targetDevice == null) {
+ invokeCallback(callback, HdmiCec.RESULT_TARGET_NOT_AVAILABLE);
+ return;
+ }
+ mService.removeAction(DeviceSelectAction.class);
+ mService.addAndStartAction(new DeviceSelectAction(mService, mAddress,
+ mService.getPhysicalAddress(), targetDevice, callback));
+ }
+
+ private static void invokeCallback(IHdmiControlCallback callback, int result) {
+ try {
+ callback.onComplete(result);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Invoking callback failed:" + e);
+ }
+ }
+
@Override
protected boolean handleGetMenuLanguage(HdmiCecMessage message) {
HdmiCecMessage command = HdmiCecMessageBuilder.buildSetMenuLanguageCommand(
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
index 1fcb32f..8dbfd85 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
@@ -270,6 +270,38 @@ public class HdmiCecMessageBuilder {
}
/**
+ * Build &lt;Set Stream Path&gt; command.
+ *
+ * <p>This is a broadcast message sent to all devices on the bus.
+ *
+ * @param src source address of command
+ * @param streamPath physical address of the device to start streaming
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildSetStreamPath(int src, int streamPath) {
+ return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_SET_STREAM_PATH,
+ physicalAddressToParam(streamPath));
+ }
+
+ /**
+ * Build &lt;Routing Change&gt; command.
+ *
+ * <p>This is a broadcast message sent to all devices on the bus.
+ *
+ * @param src source address of command
+ * @param oldPath physical address of the currently active routing path
+ * @param newPath physical address of the new active routing path
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildRoutingChange(int src, int oldPath, int newPath) {
+ byte[] param = new byte[] {
+ (byte) ((oldPath >> 8) & 0xFF), (byte) (oldPath & 0xFF),
+ (byte) ((newPath >> 8) & 0xFF), (byte) (newPath & 0xFF)
+ };
+ return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_ROUTING_CHANGE, param);
+ }
+
+ /**
* Build &lt;Give Device Power Status&gt; command.
*
* @param src source address of command
diff --git a/services/core/java/com/android/server/hdmi/HdmiConstants.java b/services/core/java/com/android/server/hdmi/HdmiConstants.java
index 54b5dcb..8f319ea 100644
--- a/services/core/java/com/android/server/hdmi/HdmiConstants.java
+++ b/services/core/java/com/android/server/hdmi/HdmiConstants.java
@@ -39,9 +39,15 @@ final class HdmiConstants {
// Constants related to UI Command Codes.
// Refer to CEC Table 30 in HDMI Spec v1.4b.
+ static final int UI_COMMAND_POWER = 0x40;
static final int UI_COMMAND_MUTE = 0x43;
static final int UI_COMMAND_MUTE_FUNCTION = 0x65;
static final int UI_COMMAND_RESTORE_VOLUME_FUNCTION = 0x66;
+ static final int UI_COMMAND_POWER_ON_FUNCTION = 0x6D;
+
+ // Bit mask used to get the routing path of the top level device.
+ // When &'d with the path 1.2.2.0 (0x1220), for instance, gives 1.0.0.0.
+ static final int ROUTING_PATH_TOP_MASK = 0xF000;
// Flags used for setOption to CEC HAL.
/**
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index d41da30..0d7ac8d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -21,6 +21,7 @@ import android.content.Context;
import android.hardware.hdmi.HdmiCec;
import android.hardware.hdmi.HdmiCecDeviceInfo;
import android.hardware.hdmi.HdmiCecMessage;
+import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.hdmi.IHdmiControlService;
import android.hardware.hdmi.IHdmiHotplugEventListener;
@@ -40,6 +41,7 @@ import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback;
import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -105,9 +107,8 @@ public final class HdmiControlService extends SystemService {
// Used to synchronize the access to the service.
private final Object mLock = new Object();
- // Type of logical devices hosted in the system.
- @GuardedBy("mLock")
- private final int[] mLocalDevices;
+ // Type of logical devices hosted in the system. Stored in the unmodifiable list.
+ private final List<Integer> mLocalDevices;
// List of listeners registered by callers that want to get notified of
// hotplug events.
@@ -117,6 +118,9 @@ public final class HdmiControlService extends SystemService {
private final ArrayList<HotplugEventListenerRecord> mHotplugEventListenerRecords =
new ArrayList<>();
+ // Handler running on service thread. It's used to run a task in service thread.
+ private final Handler mHandler = new Handler();
+
private final HdmiCecMessageCache mCecMessageCache = new HdmiCecMessageCache();
@Nullable
@@ -125,6 +129,25 @@ public final class HdmiControlService extends SystemService {
@Nullable
private HdmiMhlController mMhlController;
+ // HDMI port information. Stored in the unmodifiable list to keep the static information
+ // from being modified.
+ private List<HdmiPortInfo> mPortInfo;
+
+ // Logical address of the active source.
+ @GuardedBy("mLock")
+ private int mActiveSource;
+
+ // Active routing path. Physical address of the active source but not all the time, such as
+ // when the new active source does not claim itself to be one.
+ @GuardedBy("mLock")
+ private int mActiveRoutingPath;
+
+ // Set to true while the service is in normal mode. While set to false, no input change is
+ // allowed. Used for situations where input change can confuse users such as channel auto-scan,
+ // system upgrade, etc., a.k.a. "prohibit mode".
+ @GuardedBy("mLock")
+ private boolean mInputChangeEnabled;
+
@GuardedBy("mLock")
// Whether ARC is "enabled" or not.
// TODO: it may need to hold lock if it's accessed from others.
@@ -134,13 +157,12 @@ public final class HdmiControlService extends SystemService {
// Whether SystemAudioMode is "On" or not.
private boolean mSystemAudioMode;
- // Handler running on service thread. It's used to run a task in service thread.
- private final Handler mHandler = new Handler();
-
public HdmiControlService(Context context) {
super(context);
- mLocalDevices = getContext().getResources().getIntArray(
- com.android.internal.R.array.config_hdmiCecLogicalDeviceType);
+ mLocalDevices = HdmiUtils.asImmutableList(getContext().getResources().getIntArray(
+ com.android.internal.R.array.config_hdmiCecLogicalDeviceType));
+ // TODO: Get control flag from persistent storage
+ mInputChangeEnabled = true;
}
@Override
@@ -158,14 +180,14 @@ public final class HdmiControlService extends SystemService {
if (mMhlController == null) {
Slog.i(TAG, "Device does not support MHL-control.");
}
-
+ mPortInfo = initPortInfo();
publishBinderService(Context.HDMI_CONTROL_SERVICE, new BinderService());
// TODO: Read the preference for SystemAudioMode and initialize mSystemAudioMode and
// start to monitor the preference value and invoke SystemAudioActionFromTv if needed.
}
- private void initializeLocalDevices(final int[] deviceTypes) {
+ private void initializeLocalDevices(final List<Integer> deviceTypes) {
// A container for [Logical Address, Local device info].
final SparseArray<HdmiCecLocalDevice> devices = new SparseArray<>();
final SparseIntArray finished = new SparseIntArray();
@@ -189,7 +211,7 @@ public final class HdmiControlService extends SystemService {
// Once finish address allocation for all devices, notify
// it to each device.
- if (deviceTypes.length == finished.size()) {
+ if (deviceTypes.size() == finished.size()) {
notifyAddressAllocated(devices);
}
}
@@ -205,6 +227,66 @@ public final class HdmiControlService extends SystemService {
}
}
+ // Initialize HDMI port information. Combine the information from CEC and MHL HAL and
+ // keep them in one place.
+ private List<HdmiPortInfo> initPortInfo() {
+ HdmiPortInfo[] cecPortInfo = null;
+
+ // CEC HAL provides majority of the info while MHL does only MHL support flag for
+ // each port. Return empty array if CEC HAL didn't provide the info.
+ if (mCecController != null) {
+ cecPortInfo = mCecController.getPortInfos();
+ }
+ if (cecPortInfo == null) {
+ return Collections.emptyList();
+ }
+
+ HdmiPortInfo[] mhlPortInfo = new HdmiPortInfo[0];
+ if (mMhlController != null) {
+ // TODO: Implement plumbing logic to get MHL port information.
+ // mhlPortInfo = mMhlController.getPortInfos();
+ }
+
+ // Use the id (port number) to find the matched info between CEC and MHL to combine them
+ // into one. Leave the field `mhlSupported` to false if matched MHL entry is not found.
+ ArrayList<HdmiPortInfo> result = new ArrayList<>(cecPortInfo.length);
+ for (int i = 0; i < cecPortInfo.length; ++i) {
+ HdmiPortInfo cec = cecPortInfo[i];
+ int id = cec.getId();
+ boolean mhlInfoFound = false;
+ for (HdmiPortInfo mhl : mhlPortInfo) {
+ if (id == mhl.getId()) {
+ result.add(new HdmiPortInfo(id, cec.getType(), cec.getAddress(),
+ cec.isCecSupported(), mhl.isMhlSupported(), cec.isArcSupported()));
+ mhlInfoFound = true;
+ break;
+ }
+ }
+ if (!mhlInfoFound) {
+ result.add(cec);
+ }
+ }
+
+ return Collections.unmodifiableList(result);
+ }
+
+ /**
+ * Returns HDMI port information for the given port id.
+ *
+ * @param portId HDMI port id
+ * @return {@link HdmiPortInfo} for the given port
+ */
+ HdmiPortInfo getPortInfo(int portId) {
+ // mPortInfo is an unmodifiable list and the only reference to its inner list.
+ // No lock is necessary.
+ for (HdmiPortInfo info : mPortInfo) {
+ if (portId == info.getId()) {
+ return info;
+ }
+ }
+ return null;
+ }
+
/**
* Returns {@link Looper} for IO operation.
*
@@ -224,6 +306,41 @@ public final class HdmiControlService extends SystemService {
return mHandler.getLooper();
}
+ int getActiveSource() {
+ synchronized (mLock) {
+ return mActiveSource;
+ }
+ }
+
+ int getActivePath() {
+ synchronized (mLock) {
+ return mActiveRoutingPath;
+ }
+ }
+
+ /**
+ * Returns the path (physical address) of the device at the top of the currently active
+ * routing path. Used to get the corresponding port address of the HDMI input of the TV.
+ */
+ int getActiveInput() {
+ synchronized (mLock) {
+ return mActiveRoutingPath & HdmiConstants.ROUTING_PATH_TOP_MASK;
+ }
+ }
+
+ void updateActiveDevice(int logicalAddress, int physicalAddress) {
+ synchronized (mLock) {
+ mActiveSource = logicalAddress;
+ mActiveRoutingPath = physicalAddress;
+ }
+ }
+
+ void setInputChangeEnabled(boolean enabled) {
+ synchronized (mLock) {
+ mInputChangeEnabled = enabled;
+ }
+ }
+
/**
* Returns physical address of the device.
*/
@@ -238,6 +355,11 @@ public final class HdmiControlService extends SystemService {
return mCecController.getVendorId();
}
+ HdmiCecDeviceInfo getDeviceInfo(int logicalAddress) {
+ assertRunOnServiceThread();
+ return mCecController.getDeviceInfo(logicalAddress);
+ }
+
/**
* Returns version of CEC.
*/
@@ -256,6 +378,24 @@ public final class HdmiControlService extends SystemService {
}
/**
+ * Returns the {@link HdmiCecDeviceInfo} instance whose physical address matches
+ * the given routing path. CEC devices use routing path for its physical address to
+ * describe the hierarchy of the devices in the network.
+ *
+ * @param path routing path or physical address
+ * @return {@link HdmiCecDeviceInfo} if the matched info is found; otherwise null
+ */
+ HdmiCecDeviceInfo getDeviceInfoByPath(int path) {
+ assertRunOnServiceThread();
+ for (HdmiCecDeviceInfo info : mCecController.getDeviceInfoList(false)) {
+ if (info.getPhysicalAddress() == path) {
+ return info;
+ }
+ }
+ return null;
+ }
+
+ /**
* Add and start a new {@link FeatureAction} to the action queue.
*
* @param action {@link FeatureAction} to add and start
@@ -304,7 +444,7 @@ public final class HdmiControlService extends SystemService {
}
// Remove all actions matched with the given Class type.
- private <T extends FeatureAction> void removeAction(final Class<T> clazz) {
+ <T extends FeatureAction> void removeAction(final Class<T> clazz) {
removeActionExcept(clazz, null);
}
@@ -569,11 +709,33 @@ public final class HdmiControlService extends SystemService {
@Override
public int[] getSupportedTypes() {
enforceAccessPermission();
- synchronized (mLock) {
- return mLocalDevices;
+ // mLocalDevices is an unmodifiable list - no lock necesary.
+ int[] localDevices = new int[mLocalDevices.size()];
+ for (int i = 0; i < localDevices.length; ++i) {
+ localDevices[i] = mLocalDevices.get(i);
}
+ return localDevices;
+ }
+
+ @Override
+ public void deviceSelect(final int logicalAddress, final IHdmiControlCallback callback) {
+ enforceAccessPermission();
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ HdmiCecLocalDeviceTv tv =
+ (HdmiCecLocalDeviceTv) mCecController.getLocalDevice(HdmiCec.DEVICE_TV);
+ if (tv == null) {
+ Slog.w(TAG, "Local playback device not available");
+ invokeCallback(callback, HdmiCec.RESULT_SOURCE_NOT_AVAILABLE);
+ return;
+ }
+ tv.deviceSelect(logicalAddress, callback);
+ }
+ });
}
+
@Override
public void oneTouchPlay(final IHdmiControlCallback callback) {
enforceAccessPermission();
@@ -710,8 +872,9 @@ public final class HdmiControlService extends SystemService {
}
boolean isInPresetInstallationMode() {
- // TODO: Implement this.
- return false;
+ synchronized (mLock) {
+ return !mInputChangeEnabled;
+ }
}
/**
diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java
index ca09fe6..b534377 100644
--- a/services/core/java/com/android/server/hdmi/HdmiUtils.java
+++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java
@@ -20,6 +20,10 @@ import android.hardware.hdmi.HdmiCec;
import android.hardware.hdmi.HdmiCecMessage;
import android.util.Slog;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
/**
* Various utilities to handle HDMI CEC messages.
*/
@@ -73,6 +77,22 @@ final class HdmiUtils {
}
/**
+ * Convert integer array to list of {@link Integer}.
+ *
+ * <p>The result is immutable.
+ *
+ * @param is integer array
+ * @return {@link List} instance containing the elements in the given array
+ */
+ static List<Integer> asImmutableList(final int[] is) {
+ ArrayList<Integer> list = new ArrayList<>(is.length);
+ for (int type : is) {
+ list.add(type);
+ }
+ return Collections.unmodifiableList(list);
+ }
+
+ /**
* Assemble two bytes into single integer value.
*
* @param data to be assembled
diff --git a/services/core/java/com/android/server/hdmi/RoutingControlAction.java b/services/core/java/com/android/server/hdmi/RoutingControlAction.java
new file mode 100644
index 0000000..26048d2
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/RoutingControlAction.java
@@ -0,0 +1,244 @@
+/*
+ * 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 java.util.concurrent.TimeUnit;
+
+import android.hardware.hdmi.IHdmiControlCallback;
+import android.hardware.hdmi.HdmiCec;
+import android.hardware.hdmi.HdmiCecDeviceInfo;
+import android.hardware.hdmi.HdmiCecMessage;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
+
+/**
+ * Feature action for routing control. Exchanges routing-related commands with other devices
+ * to determine the new active source.
+ *
+ * <p>This action is initiated by various cases:
+ * <ul>
+ * <li> Manual TV input switching
+ * <li> Routing change of a CEC switch other than TV
+ * <li> New CEC device at the tail of the active routing path
+ * <li> Removed CEC device from the active routing path
+ * <li> Routing at CEC enable time
+ * </ul>
+ */
+public class RoutingControlAction extends FeatureAction {
+ private static final String TAG = "RoutingControlAction";
+
+ // State in which we wait for <Routing Information> to arrive. If timed out, we use the
+ // latest routing path to set the new active source.
+ private final static int STATE_WAIT_FOR_ROUTING_INFORMATION = 1;
+
+ // State in which we wait for <Report Power Status> in response to <Give Device Power Status>
+ // we have sent. If the response tells us the device power is on, we send <Set Stream Path>
+ // to make it the active source. Otherwise we do not send <Set Stream Path>, and possibly
+ // just show the blank screen.
+ private final static int STATE_WAIT_FOR_REPORT_POWER_STATUS = 2;
+
+ // Time out in millseconds used for <Routing Information>
+ private static final int TIMEOUT_ROUTING_INFORMATION_MS = 1000;
+
+ // Time out in milliseconds used for <Report Power Status>
+ private static final int TIMEOUT_REPORT_POWER_STATUS_MS = 1000;
+
+ private final IHdmiControlCallback mCallback;
+
+ // The latest routing path. Updated by each <Routing Information> from CEC switches.
+ private int mCurrentRoutingPath;
+
+ RoutingControlAction(HdmiControlService service, int sourceAddress, int portId,
+ IHdmiControlCallback callback) {
+ super(service, sourceAddress);
+ mCallback = callback;
+ mCurrentRoutingPath = portToPath(portId);
+ }
+
+ @Override
+ public boolean start() {
+ mState = STATE_WAIT_FOR_ROUTING_INFORMATION;
+ addTimer(mState, TIMEOUT_ROUTING_INFORMATION_MS);
+ return true;
+ }
+
+ @Override
+ public boolean processCommand(HdmiCecMessage cmd) {
+ int opcode = cmd.getOpcode();
+ byte[] params = cmd.getParams();
+ if (mState == STATE_WAIT_FOR_ROUTING_INFORMATION
+ && opcode == HdmiCec.MESSAGE_ROUTING_INFORMATION) {
+ // Keep updating the physicalAddress as we receive <Routing Information>.
+ // If the routing path doesn't belong to the currently active one, we should
+ // ignore it since it might have come from other, routing change sequence.
+ int routingPath = HdmiUtils.twoBytesToInt(params);
+ if (isInActiveRoutingPath(mCurrentRoutingPath, routingPath)) {
+ return true;
+ }
+ mCurrentRoutingPath = routingPath;
+ // Stop possible previous routing change sequence if in progress.
+ mService.removeAction(RoutingControlAction.class);
+ addTimer(mState, TIMEOUT_ROUTING_INFORMATION_MS);
+ return true;
+ } else if (mState == STATE_WAIT_FOR_REPORT_POWER_STATUS
+ && opcode == HdmiCec.MESSAGE_REPORT_POWER_STATUS) {
+ handleReportPowerStatus(cmd.getParams()[0]);
+ return true;
+ }
+ return false;
+ }
+
+ private void handleReportPowerStatus(int devicePowerStatus) {
+ int tvPowerStatus = getTvPowerStatus();
+ if (isPowerStatusOnOrTransientToOn(tvPowerStatus)) {
+ if (isPowerStatusOnOrTransientToOn(devicePowerStatus)) {
+ sendSetStreamPath();
+ } else {
+ // The whole action should be stopped here if the device is in standby mode.
+ // We don't attempt to wake it up by sending <Set Stream Path>.
+ }
+ invokeCallback(HdmiCec.RESULT_SUCCESS);
+ finish();
+ } else {
+ // TV is going into standby mode.
+ // TODO: Figure out what to do.
+ }
+ }
+
+ private int getTvPowerStatus() {
+ // TODO: Obtain TV power status.
+ return HdmiCec.POWER_STATUS_ON;
+ }
+
+ private static boolean isPowerStatusOnOrTransientToOn(int status) {
+ return status == HdmiCec.POWER_STATUS_ON || status == HdmiCec.POWER_STATUS_TRANSIENT_TO_ON;
+ }
+
+ private void sendSetStreamPath() {
+ sendCommand(HdmiCecMessageBuilder.buildSetStreamPath(mSourceAddress, mCurrentRoutingPath));
+ }
+
+ private static boolean isInActiveRoutingPath(int activePath, int newPath) {
+ // Check each nibble of the currently active path and the new path till the position
+ // where the active nibble is not zero. For (activePath, newPath),
+ // (1.1.0.0, 1.0.0.0) -> true, new path is a parent
+ // (1.2.1.0, 1.2.1.2) -> true, new path is a descendant
+ // (1.1.0.0, 1.2.0.0) -> false, new path is a sibling
+ // (1.0.0.0, 2.0.0.0) -> false, in a completely different path
+ for (int i = 12; i >= 0; i -= 4) {
+ int nibbleActive = (activePath >> i) & 0xF;
+ if (nibbleActive == 0) {
+ break;
+ }
+ int nibbleNew = (newPath >> i) & 0xF;
+ if (nibbleNew == 0) {
+ break;
+ }
+ if (nibbleActive != nibbleNew) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void handleTimerEvent(int timeoutState) {
+ if (mState != timeoutState || mState == STATE_NONE) {
+ Slog.w("CEC", "Timer in a wrong state. Ignored.");
+ return;
+ }
+ switch (timeoutState) {
+ case STATE_WAIT_FOR_ROUTING_INFORMATION:
+ HdmiCecDeviceInfo device = mService.getDeviceInfoByPath(mCurrentRoutingPath);
+ if (device == null) {
+ maybeChangeActiveInput(pathToPort(mCurrentRoutingPath));
+ } else {
+ // TODO: Also check followings and then proceed:
+ // if routing change was neither triggered by TV at CEC enable time, nor
+ // at the detection of new device at the end of the active routing path, nor
+ // by TV power on with HDMI input as the active signal source.
+ int deviceLogicalAddress = device.getLogicalAddress();
+ queryDevicePowerStatus(deviceLogicalAddress, new SendMessageCallback() {
+ @Override
+ public void onSendCompleted(int error) {
+ handlDevicePowerStatusAckResult(error == HdmiCec.RESULT_SUCCESS);
+ }
+ });
+ }
+ return;
+ case STATE_WAIT_FOR_REPORT_POWER_STATUS:
+ int tvPowerStatus = getTvPowerStatus();
+ if (isPowerStatusOnOrTransientToOn(tvPowerStatus)) {
+ if (!maybeChangeActiveInput(pathToPort(mCurrentRoutingPath))) {
+ sendSetStreamPath();
+ }
+ }
+ invokeCallback(HdmiCec.RESULT_SUCCESS);
+ finish();
+ return;
+ }
+ }
+
+ // Called whenever an HDMI input of the TV shall become the active input.
+ private boolean maybeChangeActiveInput(int inputPortPath) {
+ if (mService.getActiveInput() == inputPortPath) {
+ return false;
+ }
+ // TODO: Remember the currently active input
+ // if PAP/PIP is active, move the focus to the right window, otherwise switch
+ // the port.
+ // Show the OSD input change banner.
+ return true;
+ }
+
+ private void queryDevicePowerStatus(int address, SendMessageCallback callback) {
+ sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(mSourceAddress, address),
+ callback);
+ }
+
+ private void handlDevicePowerStatusAckResult(boolean acked) {
+ if (acked) {
+ mState = STATE_WAIT_FOR_REPORT_POWER_STATUS;
+ addTimer(mState, TIMEOUT_REPORT_POWER_STATUS_MS);
+ } else {
+ maybeChangeActiveInput(pathToPort(mCurrentRoutingPath));
+ }
+ }
+
+ // Get the address of the TV port to which the given path is connected.
+ private static int pathToPort(int path) {
+ return path & HdmiConstants.ROUTING_PATH_TOP_MASK;
+ }
+
+ // Given the HDMI port id, return the port address.
+ private int portToPath(int portId) {
+ return mService.getPortInfo(portId).getAddress();
+ }
+
+ private void invokeCallback(int result) {
+ if (mCallback == null) {
+ return;
+ }
+ try {
+ mCallback.onComplete(result);
+ } catch (RemoteException e) {
+ // Do nothing.
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 92b643c..534faba3 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -481,11 +481,10 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne
*/
private void closeAndCleanupJobH(boolean reschedule) {
removeMessages(MSG_TIMEOUT);
+ mCompletedListener.onJobCompleted(mRunningJob, reschedule);
synchronized (mLock) {
mWakeLock.release();
mContext.unbindService(JobServiceContext.this);
- mCompletedListener.onJobCompleted(mRunningJob, reschedule);
-
mWakeLock = null;
mRunningJob = null;
mParams = null;
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 5f22b34..4ac26c1 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -262,16 +262,23 @@ public class JobStore {
@Override
public void run() {
final long startElapsed = SystemClock.elapsedRealtime();
+ List<JobStatus> mStoreCopy = new ArrayList<JobStatus>();
synchronized (JobStore.this) {
- writeJobsMapImpl();
+ // Copy over the jobs so we can release the lock before writing.
+ for (JobStatus jobStatus : mJobSet) {
+ JobStatus copy = new JobStatus(jobStatus.getJob(), jobStatus.getUid(),
+ jobStatus.getEarliestRunTime(), jobStatus.getLatestRunTimeElapsed());
+ mStoreCopy.add(copy);
+ }
}
+ writeJobsMapImpl(mStoreCopy);
if (JobSchedulerService.DEBUG) {
Slog.v(TAG, "Finished writing, took " + (SystemClock.elapsedRealtime()
- startElapsed) + "ms");
}
}
- private void writeJobsMapImpl() {
+ private void writeJobsMapImpl(List<JobStatus> jobList) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XmlSerializer out = new FastXmlSerializer();
@@ -281,8 +288,7 @@ public class JobStore {
out.startTag(null, "job-info");
out.attribute(null, "version", Integer.toString(JOBS_FILE_VERSION));
- for (int i = 0; i < mJobSet.size(); i++) {
- final JobStatus jobStatus = mJobSet.valueAt(i);
+ for (JobStatus jobStatus : jobList) {
if (DEBUG) {
Slog.d(TAG, "Saving job " + jobStatus.getJobId());
}
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index 7e79ff7..daba0d9 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -197,4 +197,4 @@ public class ConnectivityController extends StateController implements
+ ", UM=" + js.hasUnmeteredConstraint());
}
}
-} \ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 008d2fc..45326f7 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION;
import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE;
import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED;
@@ -227,7 +228,7 @@ public class WindowAnimator {
continue;
}
final WindowStateAnimator winAnimator = win.mWinAnimator;
- if (mPolicy.doesForceHide(win.mAttrs)) {
+ if ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
if (!winAnimator.mAnimating) {
// Create a new animation to delay until keyguard is gone on its own.
winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f);
@@ -268,7 +269,7 @@ public class WindowAnimator {
}
}
- if (mPolicy.doesForceHide(win.mAttrs)) {
+ if (mPolicy.isForceHiding(win.mAttrs)) {
if (!wasAnimating && nowAnimating) {
if (WindowManagerService.DEBUG_ANIM ||
WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 76085fa..4eea9c3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8442,7 +8442,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
win.mLayoutNeeded = false;
win.prelayout();
- mPolicy.layoutWindowLw(win, win.mAttrs, null);
+ mPolicy.layoutWindowLw(win, null);
win.mLayoutSeq = seq;
if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame="
+ win.mFrame + " mContainingFrame="
@@ -8494,7 +8494,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
win.mLayoutNeeded = false;
win.prelayout();
- mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
+ mPolicy.layoutWindowLw(win, win.mAttachedWindow);
win.mLayoutSeq = seq;
if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame="
+ win.mFrame + " mContainingFrame="
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
index cbc853d..df3b6d3 100644
--- a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
+++ b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
@@ -57,6 +57,8 @@ public:
int getVersion();
// Get vendor id used for vendor command.
uint32_t getVendorId();
+ // Get Port information on all the HDMI ports.
+ jobjectArray getPortInfos();
// Set a flag and its value.
void setOption(int flag, int value);
// Set audio return channel status.
@@ -69,6 +71,7 @@ public:
}
private:
+ static const int INVALID_PHYSICAL_ADDRESS = 0xFFFF;
static void onReceived(const hdmi_event_t* event, void* arg);
hdmi_cec_device_t* mDevice;
@@ -209,11 +212,11 @@ void HdmiCecController::clearLogicaladdress() {
}
int HdmiCecController::getPhysicalAddress() {
- uint16_t physicalAddress = 0xFFFF;
- if (mDevice->get_physical_address(mDevice, &physicalAddress) == 0) {
- return physicalAddress;
+ uint16_t addr;
+ if (!mDevice->get_physical_address(mDevice, &addr)) {
+ return addr;
}
- return -1;
+ return INVALID_PHYSICAL_ADDRESS;
}
int HdmiCecController::getVersion() {
@@ -228,6 +231,34 @@ uint32_t HdmiCecController::getVendorId() {
return vendorId;
}
+jobjectArray HdmiCecController::getPortInfos() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ jclass hdmiPortInfo = env->FindClass("com/android/server/hdmi/HdmiPortInfo");
+ if (hdmiPortInfo == NULL) {
+ return NULL;
+ }
+ jmethodID ctor = env->GetMethodID(hdmiPortInfo, "<init>", "(IIIZZZ)V");
+ if (ctor == NULL) {
+ return NULL;
+ }
+ hdmi_port_info* ports;
+ int numPorts;
+ mDevice->get_port_info(mDevice, &ports, &numPorts);
+ jobjectArray res = env->NewObjectArray(numPorts, hdmiPortInfo, NULL);
+
+ // MHL support field will be obtained from MHL HAL. Leave it to false.
+ jboolean mhlSupported = (jboolean) 0;
+ for (int i = 0; i < numPorts; ++i) {
+ hdmi_port_info* info = &ports[i];
+ jboolean cecSupported = (jboolean) info->cec_supported;
+ jboolean arcSupported = (jboolean) info->arc_supported;
+ jobject infoObj = env->NewObject(hdmiPortInfo, ctor, info->port_num, info->type,
+ info->physical_address, cecSupported, mhlSupported, arcSupported);
+ env->SetObjectArrayElement(res, i, infoObj);
+ }
+ return res;
+}
+
void HdmiCecController::setOption(int flag, int value) {
mDevice->set_option(mDevice, flag, value);
}
@@ -242,7 +273,6 @@ bool HdmiCecController::isConnected(int port) {
return mDevice->is_connected(mDevice, port) == HDMI_CONNECTED;
}
-
// static
void HdmiCecController::onReceived(const hdmi_event_t* event, void* arg) {
HdmiCecController* controller = static_cast<HdmiCecController*>(arg);
@@ -311,58 +341,50 @@ static jint nativeSendCecCommand(JNIEnv* env, jclass clazz, jlong controllerPtr,
return controller->sendMessage(message);
}
-static jint nativeAddLogicalAddress(JNIEnv* env, jclass clazz,
- jlong controllerPtr, jint logicalAddress) {
- HdmiCecController* controller =
- reinterpret_cast<HdmiCecController*>(controllerPtr);
- return controller->addLogicalAddress(
- static_cast<cec_logical_address_t>(logicalAddress));
+static jint nativeAddLogicalAddress(JNIEnv* env, jclass clazz, jlong controllerPtr,
+ jint logicalAddress) {
+ HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr);
+ return controller->addLogicalAddress(static_cast<cec_logical_address_t>(logicalAddress));
}
-static void nativeClearLogicalAddress(JNIEnv* env, jclass clazz,
- jlong controllerPtr) {
- HdmiCecController* controller =
- reinterpret_cast<HdmiCecController*>(controllerPtr);
+static void nativeClearLogicalAddress(JNIEnv* env, jclass clazz, jlong controllerPtr) {
+ HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr);
controller->clearLogicaladdress();
}
-static jint nativeGetPhysicalAddress(JNIEnv* env, jclass clazz,
- jlong controllerPtr) {
- HdmiCecController* controller =
- reinterpret_cast<HdmiCecController*>(controllerPtr);
+static jint nativeGetPhysicalAddress(JNIEnv* env, jclass clazz, jlong controllerPtr) {
+ HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr);
return controller->getPhysicalAddress();
}
-static jint nativeGetVersion(JNIEnv* env, jclass clazz,
- jlong controllerPtr) {
- HdmiCecController* controller =
- reinterpret_cast<HdmiCecController*>(controllerPtr);
+static jint nativeGetVersion(JNIEnv* env, jclass clazz, jlong controllerPtr) {
+ HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr);
return controller->getVersion();
}
static jint nativeGetVendorId(JNIEnv* env, jclass clazz, jlong controllerPtr) {
- HdmiCecController* controller =
- reinterpret_cast<HdmiCecController*>(controllerPtr);
+ HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr);
return controller->getVendorId();
}
-static void nativeSetOption(JNIEnv* env, jclass clazz, jlong controllerPtr, jint flag,
- jint value) {
- HdmiCecController* controller =
- reinterpret_cast<HdmiCecController*>(controllerPtr);
+static jobjectArray nativeGetPortInfos(JNIEnv* env, jclass clazz, jlong controllerPtr) {
+ HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr);
+ return controller->getPortInfos();
+}
+
+static void nativeSetOption(JNIEnv* env, jclass clazz, jlong controllerPtr, jint flag, jint value) {
+ HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr);
controller->setOption(flag, value);
}
static void nativeSetAudioReturnChannel(JNIEnv* env, jclass clazz, jlong controllerPtr,
jboolean enabled) {
- HdmiCecController* controller =
- reinterpret_cast<HdmiCecController*>(controllerPtr);
+ HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr);
controller->setAudioReturnChannel(enabled == JNI_TRUE);
}
static jboolean nativeIsConnected(JNIEnv* env, jclass clazz, jlong controllerPtr, jint port) {
- HdmiCecController* controller =
- reinterpret_cast<HdmiCecController*>(controllerPtr);
+ HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr);
return controller->isConnected(port) ? JNI_TRUE : JNI_FALSE ;
}
@@ -377,6 +399,9 @@ static JNINativeMethod sMethods[] = {
{ "nativeGetPhysicalAddress", "(J)I", (void *) nativeGetPhysicalAddress },
{ "nativeGetVersion", "(J)I", (void *) nativeGetVersion },
{ "nativeGetVendorId", "(J)I", (void *) nativeGetVendorId },
+ { "nativeGetPortInfos",
+ "(J)[Lcom/android/server/hdmi/HdmiPortInfo;",
+ (void *) nativeGetPortInfos },
{ "nativeSetOption", "(JII)V", (void *) nativeSetOption },
{ "nativeSetAudioReturnChannel", "(JZ)V", (void *) nativeSetAudioReturnChannel },
{ "nativeIsConnected", "(JI)Z", (void *) nativeIsConnected },
@@ -385,8 +410,7 @@ static JNINativeMethod sMethods[] = {
#define CLASS_PATH "com/android/server/hdmi/HdmiCecController"
int register_android_server_hdmi_HdmiCecController(JNIEnv* env) {
- int res = jniRegisterNativeMethods(env, CLASS_PATH, sMethods,
- NELEM(sMethods));
+ int res = jniRegisterNativeMethods(env, CLASS_PATH, sMethods, NELEM(sMethods));
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
return 0;
}
diff --git a/telecomm/java/android/telecomm/CallCapabilities.java b/telecomm/java/android/telecomm/CallCapabilities.java
index b2b33a3..5aff19c 100644
--- a/telecomm/java/android/telecomm/CallCapabilities.java
+++ b/telecomm/java/android/telecomm/CallCapabilities.java
@@ -17,7 +17,7 @@
package android.telecomm;
/** Defines actions a call currently supports. */
-public class CallCapabilities {
+public final class CallCapabilities {
/** Call can currently be put on hold or unheld. */
public static final int HOLD = 0x00000001;
@@ -27,24 +27,60 @@ public class CallCapabilities {
/** Call can currently be merged. */
public static final int MERGE_CALLS = 0x00000004;
- /* Call can currently be swapped with another call. */
+ /** Call can currently be swapped with another call. */
public static final int SWAP_CALLS = 0x00000008;
- /* Call currently supports adding another call to this one. */
+ /** Call currently supports adding another call to this one. */
public static final int ADD_CALL = 0x00000010;
- /* Call supports responding via text option. */
+ /** Call supports responding via text option. */
public static final int RESPOND_VIA_TEXT = 0x00000020;
- /* Call can be muted. */
+ /** Call can be muted. */
public static final int MUTE = 0x00000040;
- /* Call supports generic conference mode. */
+ /** Call supports generic conference mode. */
public static final int GENERIC_CONFERENCE = 0x00000080;
- /* Call currently supports switch between connections. */
+ /** Call currently supports switch between connections. */
public static final int CONNECTION_HANDOFF = 0x00000100;
public static final int ALL = HOLD | SUPPORT_HOLD | MERGE_CALLS | SWAP_CALLS | ADD_CALL
| RESPOND_VIA_TEXT | MUTE | GENERIC_CONFERENCE | CONNECTION_HANDOFF;
+
+ public static String toString(int capabilities) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("[Capabilities:");
+ if ((capabilities & HOLD) != 0) {
+ builder.append(" HOLD");
+ }
+ if ((capabilities & SUPPORT_HOLD) != 0) {
+ builder.append(" SUPPORT_HOLD");
+ }
+ if ((capabilities & MERGE_CALLS) != 0) {
+ builder.append(" MERGE_CALLS");
+ }
+ if ((capabilities & SWAP_CALLS) != 0) {
+ builder.append(" SWAP_CALLS");
+ }
+ if ((capabilities & ADD_CALL) != 0) {
+ builder.append(" ADD_CALL");
+ }
+ if ((capabilities & RESPOND_VIA_TEXT) != 0) {
+ builder.append(" RESPOND_VIA_TEXT");
+ }
+ if ((capabilities & MUTE) != 0) {
+ builder.append(" MUTE");
+ }
+ if ((capabilities & GENERIC_CONFERENCE) != 0) {
+ builder.append(" GENERIC_CONFERENCE");
+ }
+ if ((capabilities & CONNECTION_HANDOFF) != 0) {
+ builder.append(" HANDOFF");
+ }
+ builder.append("]");
+ return builder.toString();
+ }
+
+ private CallCapabilities() {}
}
diff --git a/telecomm/java/android/telecomm/CallService.java b/telecomm/java/android/telecomm/CallService.java
index a254459..0b5981c 100644
--- a/telecomm/java/android/telecomm/CallService.java
+++ b/telecomm/java/android/telecomm/CallService.java
@@ -61,7 +61,7 @@ public abstract class CallService extends Service {
private static final int MSG_ON_AUDIO_STATE_CHANGED = 11;
private static final int MSG_PLAY_DTMF_TONE = 12;
private static final int MSG_STOP_DTMF_TONE = 13;
- private static final int MSG_ADD_TO_CONFERENCE = 14;
+ private static final int MSG_CONFERENCE = 14;
private static final int MSG_SPLIT_FROM_CONFERENCE = 15;
private static final int MSG_ON_POST_DIAL_CONTINUE = 16;
@@ -128,24 +128,12 @@ public abstract class CallService extends Service {
case MSG_STOP_DTMF_TONE:
stopDtmfTone((String) msg.obj);
break;
- case MSG_ADD_TO_CONFERENCE: {
- SomeArgs args = (SomeArgs) msg.obj;
- try {
- @SuppressWarnings("unchecked")
- List<String> callIds = (List<String>) args.arg2;
- String conferenceCallId = (String) args.arg1;
- addToConference(conferenceCallId, callIds);
- } finally {
- args.recycle();
- }
- break;
- }
- case MSG_SPLIT_FROM_CONFERENCE: {
+ case MSG_CONFERENCE: {
SomeArgs args = (SomeArgs) msg.obj;
try {
String conferenceCallId = (String) args.arg1;
String callId = (String) args.arg2;
- splitFromConference(conferenceCallId, callId);
+ conference(conferenceCallId, callId);
} finally {
args.recycle();
}
@@ -162,6 +150,9 @@ public abstract class CallService extends Service {
}
break;
}
+ case MSG_SPLIT_FROM_CONFERENCE:
+ splitFromConference((String) msg.obj);
+ break;
default:
break;
}
@@ -245,19 +236,16 @@ public abstract class CallService extends Service {
}
@Override
- public void addToConference(String conferenceCallId, List<String> callsToConference) {
+ public void conference(String conferenceCallId, String callId) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = conferenceCallId;
- args.arg2 = callsToConference;
- mMessageHandler.obtainMessage(MSG_ADD_TO_CONFERENCE, args).sendToTarget();
+ args.arg2 = callId;
+ mMessageHandler.obtainMessage(MSG_CONFERENCE, args).sendToTarget();
}
@Override
- public void splitFromConference(String conferenceCallId, String callId) {
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = conferenceCallId;
- args.arg2 = callId;
- mMessageHandler.obtainMessage(MSG_SPLIT_FROM_CONFERENCE, args).sendToTarget();
+ public void splitFromConference(String callId) {
+ mMessageHandler.obtainMessage(MSG_SPLIT_FROM_CONFERENCE, callId).sendToTarget();
}
@Override
@@ -424,24 +412,22 @@ public abstract class CallService extends Service {
public abstract void onAudioStateChanged(String activeCallId, CallAudioState audioState);
/**
- * Adds the specified calls to the specified conference call.
+ * Conferences the specified call.
*
* @param conferenceCallId The unique ID of the conference call onto which the specified calls
* should be added.
- * @param callIds The calls to add to the conference call.
+ * @param callId The call to conference.
* @hide
*/
- public abstract void addToConference(String conferenceCallId, List<String> callIds);
+ public abstract void conference(String conferenceCallId, String callId);
/**
- * Removes the specified call from the specified conference call. This is a no-op if the call
- * is not already part of the conference call.
+ * Removes the specified call from a conference call.
*
- * @param conferenceCallId The conference call.
* @param callId The call to remove from the conference call
* @hide
*/
- public abstract void splitFromConference(String conferenceCallId, String callId);
+ public abstract void splitFromConference(String callId);
public void onPostDialContinue(String callId, boolean proceed) {}
public void onPostDialWait(Connection conn, String remaining) {}
diff --git a/telecomm/java/android/telecomm/CallServiceAdapter.java b/telecomm/java/android/telecomm/CallServiceAdapter.java
index 8c3ddad..0ba8161 100644
--- a/telecomm/java/android/telecomm/CallServiceAdapter.java
+++ b/telecomm/java/android/telecomm/CallServiceAdapter.java
@@ -179,12 +179,12 @@ public final class CallServiceAdapter {
* Indicates that the specified call can conference with any of the specified list of calls.
*
* @param callId The unique ID of the call.
- * @param conferenceCapableCallIds The unique IDs of the calls which can be conferenced.
+ * @param canConference Specified whether or not the call can be conferenced.
* @hide
*/
- public void setCanConferenceWith(String callId, List<String> conferenceCapableCallIds) {
+ public void setCanConference(String callId, boolean canConference) {
try {
- mAdapter.setCanConferenceWith(callId, conferenceCapableCallIds);
+ mAdapter.setCanConference(callId, canConference);
} catch (RemoteException ignored) {
}
}
@@ -193,13 +193,14 @@ public final class CallServiceAdapter {
* Indicates whether or not the specified call is currently conferenced into the specified
* conference call.
*
- * @param conferenceCallId The unique ID of the conference call.
* @param callId The unique ID of the call being conferenced.
+ * @param conferenceCallId The unique ID of the conference call. Null if call is not
+ * conferenced.
* @hide
*/
- public void setIsConferenced(String conferenceCallId, String callId, boolean isConferenced) {
+ public void setIsConferenced(String callId, String conferenceCallId) {
try {
- mAdapter.setIsConferenced(conferenceCallId, callId, isConferenced);
+ mAdapter.setIsConferenced(callId, conferenceCallId);
} catch (RemoteException ignored) {
}
}
@@ -236,4 +237,16 @@ public final class CallServiceAdapter {
} catch (RemoteException e) {
}
}
+
+ /**
+ * Indicates that a new conference call has been created.
+ *
+ * @param callId The unique ID of the conference call.
+ */
+ public void addConferenceCall(String callId) {
+ try {
+ mAdapter.addConferenceCall(callId, null);
+ } catch (RemoteException ignored) {
+ }
+ }
}
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index 344814f..7aee770 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -19,7 +19,10 @@ package android.telecomm;
import android.net.Uri;
import android.os.Bundle;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
/**
@@ -35,6 +38,8 @@ public abstract class Connection {
void onDisconnected(Connection c, int cause, String message);
void onRequestingRingback(Connection c, boolean ringback);
void onDestroyed(Connection c);
+ void onConferenceCapableChanged(Connection c, boolean isConferenceCapable);
+ void onParentConnectionChanged(Connection c, Connection parent);
}
public static class ListenerBase implements Listener {
@@ -65,6 +70,14 @@ public abstract class Connection {
/** {@inheritDoc} */
@Override
public void onRequestingRingback(Connection c, boolean ringback) {}
+
+ /** ${inheritDoc} */
+ @Override
+ public void onConferenceCapableChanged(Connection c, boolean isConferenceCapable) {}
+
+ /** ${inheritDoc} */
+ @Override
+ public void onParentConnectionChanged(Connection c, Connection parent) {}
}
public final class State {
@@ -79,10 +92,14 @@ public abstract class Connection {
}
private final Set<Listener> mListeners = new HashSet<>();
+ private final List<Connection> mChildConnections = new ArrayList<>();
+
private int mState = State.NEW;
private CallAudioState mCallAudioState;
private Uri mHandle;
private boolean mRequestingRingback = false;
+ private boolean mIsConferenceCapable = false;
+ private Connection mParentConnection;
/**
* Create a new Connection.
@@ -176,6 +193,16 @@ public abstract class Connection {
}
/**
+ * Separates this Connection from a parent connection.
+ *
+ * @hide
+ */
+ public final void separate() {
+ Log.d(this, "separate");
+ onSeparate();
+ }
+
+ /**
* Abort this Connection. The Connection will immediately transition to
* the {@link State#DISCONNECTED} state, and send no notifications of this
* or any other future events.
@@ -240,6 +267,14 @@ public abstract class Connection {
}
/**
+ * TODO(santoscordon): Needs updated documentation.
+ */
+ public final void conference() {
+ Log.d(this, "conference");
+ onConference();
+ }
+
+ /**
* Inform this Connection that the state of its audio output has been changed externally.
*
* @param state The new audio state.
@@ -274,7 +309,7 @@ public abstract class Connection {
}
/**
- * @return Whether this connection is requesting that the system play a ringback tone
+ * Returns whether this connection is requesting that the system play a ringback tone
* on its behalf.
*/
public boolean isRequestingRingback() {
@@ -282,6 +317,38 @@ public abstract class Connection {
}
/**
+ * Returns whether this connection is a conference connection (has child connections).
+ */
+ public boolean isConferenceConnection() {
+ return !mChildConnections.isEmpty();
+ }
+
+ public void setParentConnection(Connection parentConnection) {
+ Log.d(this, "parenting %s to %s", this, parentConnection);
+ if (mParentConnection != parentConnection) {
+ if (mParentConnection != null) {
+ mParentConnection.removeChild(this);
+ }
+ mParentConnection = parentConnection;
+ if (mParentConnection != null) {
+ mParentConnection.addChild(this);
+ // do something if the child connections goes down to ZERO.
+ }
+ for (Listener l : mListeners) {
+ l.onParentConnectionChanged(this, mParentConnection);
+ }
+ }
+ }
+
+ public Connection getParentConnection() {
+ return mParentConnection;
+ }
+
+ public List<Connection> getChildConnections() {
+ return mChildConnections;
+ }
+
+ /**
* Sets the value of the {@link #getHandle()} property and notifies listeners.
*
* @param handle The new handle.
@@ -359,6 +426,32 @@ public abstract class Connection {
}
/**
+ * TODO(santoscordon): Needs documentation.
+ */
+ protected void setIsConferenceCapable(boolean isConferenceCapable) {
+ if (mIsConferenceCapable != isConferenceCapable) {
+ mIsConferenceCapable = isConferenceCapable;
+ for (Listener l : mListeners) {
+ l.onConferenceCapableChanged(this, mIsConferenceCapable);
+ }
+ }
+ }
+
+ /**
+ * TODO(santoscordon): Needs documentation.
+ */
+ protected void setDestroyed() {
+ // It is possible that onDestroy() will trigger the listener to remove itself which will
+ // result in a concurrent modification exception. To counteract this we make a copy of the
+ // listeners and iterate on that.
+ for (Listener l : new ArrayList<>(mListeners)) {
+ if (mListeners.contains(l)) {
+ l.onDestroyed(this);
+ }
+ }
+ }
+
+ /**
* Notifies this Connection and listeners that the {@link #getCallAudioState()} property
* has a new value.
*
@@ -418,6 +511,11 @@ public abstract class Connection {
protected void onDisconnect() {}
/**
+ * Notifies this Connection of a request to disconnect.
+ */
+ protected void onSeparate() {}
+
+ /**
* Notifies this Connection of a request to abort.
*/
protected void onAbort() {}
@@ -449,6 +547,28 @@ public abstract class Connection {
*/
protected void onPostDialContinue(boolean proceed) {}
+ /**
+ * TODO(santoscordon): Needs documentation.
+ */
+ protected void onConference() {}
+
+ /**
+ * TODO(santoscordon): Needs documentation.
+ */
+ protected void onChildrenChanged(List<Connection> children) {}
+
+ private void addChild(Connection connection) {
+ Log.d(this, "adding child %s", connection);
+ mChildConnections.add(connection);
+ onChildrenChanged(mChildConnections);
+ }
+
+ private void removeChild(Connection connection) {
+ Log.d(this, "removing child %s", connection);
+ mChildConnections.remove(connection);
+ onChildrenChanged(mChildConnections);
+ }
+
private void setState(int state) {
Log.d(this, "setState: %s", stateToString(state));
onSetState(state);
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 59e977d..9dfad2d 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -20,10 +20,15 @@ import android.net.Uri;
import android.os.Bundle;
import android.telephony.DisconnectCause;
+import android.os.SystemClock;
+
+import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* A {@link android.app.Service} that provides telephone connections to
@@ -32,7 +37,6 @@ import java.util.Map;
public abstract class ConnectionService extends CallService {
// Flag controlling whether PII is emitted into the logs
private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
-
private static final Connection NULL_CONNECTION = new Connection() {};
// Mappings from Connections to IDs as understood by the current CallService implementation
@@ -99,6 +103,20 @@ public abstract class ConnectionService extends CallService {
Log.d(this, "Adapter onRingback %b", ringback);
getAdapter().setRequestingRingback(id, ringback);
}
+
+ @Override
+ public void onConferenceCapableChanged(Connection c, boolean isConferenceCapable) {
+ String id = mIdByConnection.get(c);
+ getAdapter().setCanConference(id, isConferenceCapable);
+ }
+
+ /** ${inheritDoc} */
+ @Override
+ public void onParentConnectionChanged(Connection c, Connection parent) {
+ String id = mIdByConnection.get(c);
+ String parentId = parent == null ? null : mIdByConnection.get(parent);
+ getAdapter().setIsConferenced(id, parentId);
+ }
};
@Override
@@ -110,8 +128,7 @@ public abstract class ConnectionService extends CallService {
@Override
public void onResult(Uri handle, Subscription... result) {
boolean isCompatible = result.length > 0;
- Log.d(this, "adapter setIsCompatibleWith "
- + callInfo.getId() + " " + isCompatible);
+ Log.d(this, "adapter setIsCompatibleWith ");
getAdapter().setIsCompatibleWith(callInfo.getId(), isCompatible);
}
@@ -135,7 +152,7 @@ public abstract class ConnectionService extends CallService {
new Response<ConnectionRequest, Connection>() {
@Override
public void onResult(ConnectionRequest request, Connection... result) {
- if (result.length != 1) {
+ if (result != null && result.length != 1) {
Log.d(this, "adapter handleFailedOutgoingCall %s", callInfo);
getAdapter().handleFailedOutgoingCall(
request,
@@ -145,10 +162,10 @@ public abstract class ConnectionService extends CallService {
c.abort();
}
} else {
- addConnection(callInfo.getId(), result[0]);
Log.d(this, "adapter handleSuccessfulOutgoingCall %s",
callInfo.getId());
getAdapter().handleSuccessfulOutgoingCall(callInfo.getId());
+ addConnection(callInfo.getId(), result[0]);
}
}
@@ -177,7 +194,7 @@ public abstract class ConnectionService extends CallService {
new Response<ConnectionRequest, Connection>() {
@Override
public void onResult(ConnectionRequest request, Connection... result) {
- if (result.length != 1) {
+ if (result != null && result.length != 1) {
Log.d(this, "adapter handleFailedOutgoingCall %s", callId);
getAdapter().handleFailedOutgoingCall(
request,
@@ -258,27 +275,43 @@ public abstract class ConnectionService extends CallService {
/** @hide */
@Override
- public final void addToConference(String conferenceCallId, List<String> callIds) {
- Log.d(this, "addToConference %s, %s", conferenceCallId, callIds);
-
- List<Connection> connections = new LinkedList<>();
- for (String id : callIds) {
- Connection connection = findConnectionForAction(id, "addToConference");
- if (connection == NULL_CONNECTION) {
- Log.w(this, "Connection missing in conference request %s.", id);
- return;
- }
- connections.add(connection);
+ public final void conference(final String conferenceCallId, String callId) {
+ Log.d(this, "conference %s, %s", conferenceCallId, callId);
+
+ Connection connection = findConnectionForAction(callId, "conference");
+ if (connection == NULL_CONNECTION) {
+ Log.w(this, "Connection missing in conference request %s.", callId);
+ return;
}
- // TODO(santoscordon): Find an existing conference call or create a new one. Then call
- // conferenceWith on it.
+ onCreateConferenceConnection(conferenceCallId, connection,
+ new Response<String, Connection>() {
+ /** ${inheritDoc} */
+ @Override
+ public void onResult(String ignored, Connection... result) {
+ Log.d(this, "onCreateConference.Response %s", (Object[]) result);
+ if (result != null && result.length == 1) {
+ Connection conferenceConnection = result[0];
+ if (!mIdByConnection.containsKey(conferenceConnection)) {
+ Log.v(this, "sending new conference call %s", conferenceCallId);
+ getAdapter().addConferenceCall(conferenceCallId);
+ addConnection(conferenceCallId, conferenceConnection);
+ }
+ }
+ }
+
+ /** ${inheritDoc} */
+ @Override
+ public void onError(String request, int code, String reason) {
+ // no-op
+ }
+ });
}
/** @hide */
@Override
- public final void splitFromConference(String conferenceCallId, String callId) {
- Log.d(this, "splitFromConference(%s, %s)", conferenceCallId, callId);
+ public final void splitFromConference(String callId) {
+ Log.d(this, "splitFromConference(%s)", callId);
Connection connection = findConnectionForAction(callId, "splitFromConference");
if (connection == NULL_CONNECTION) {
@@ -309,6 +342,13 @@ public abstract class ConnectionService extends CallService {
}
/**
+ * Returns all connections currently associated with this connection service.
+ */
+ public Collection<Connection> getAllConnections() {
+ return mConnectionById.values();
+ }
+
+ /**
* Find a set of Subscriptions matching a given handle (e.g. phone number).
*
* @param handle A handle (e.g. phone number) with which to connect.
@@ -329,6 +369,21 @@ public abstract class ConnectionService extends CallService {
Response<ConnectionRequest, Connection> callback) {}
/**
+ * Returns a new or existing conference connection when the the user elects to convert the
+ * specified connection into a conference call. The specified connection can be any connection
+ * which had previously specified itself as conference-capable including both simple connections
+ * and connections previously returned from this method.
+ *
+ * @param connection The connection from which the user opted to start a conference call.
+ * @param token The token to be passed into the response callback.
+ * @param callback The callback for providing the potentially-new conference connection.
+ */
+ public void onCreateConferenceConnection(
+ String token,
+ Connection connection,
+ Response<String, Connection> callback) {}
+
+ /**
* Create a Connection to match an incoming connection notification.
*
* @param request Data encapsulating details of the desired Connection.
@@ -338,6 +393,20 @@ public abstract class ConnectionService extends CallService {
ConnectionRequest request,
Response<ConnectionRequest, Connection> callback) {}
+ /**
+ * Notifies that a connection has been added to this connection service and sent to Telecomm.
+ *
+ * @param connection The connection which was added.
+ */
+ public void onConnectionAdded(Connection connection) {}
+
+ /**
+ * Notified that a connection has been removed from this connection service.
+ *
+ * @param connection The connection which was removed.
+ */
+ public void onConnectionRemoved(Connection connection) {}
+
static String toLogSafePhoneNumber(String number) {
// For unknown number, log empty string.
if (number == null) {
@@ -387,12 +456,14 @@ public abstract class ConnectionService extends CallService {
mConnectionById.put(callId, connection);
mIdByConnection.put(connection, callId);
connection.addConnectionListener(mConnectionListener);
+ onConnectionAdded(connection);
}
private void removeConnection(Connection connection) {
connection.removeConnectionListener(mConnectionListener);
mConnectionById.remove(mIdByConnection.get(connection));
mIdByConnection.remove(connection);
+ onConnectionRemoved(connection);
}
private Connection findConnectionForAction(String callId, String action) {
diff --git a/telecomm/java/android/telecomm/InCallAdapter.java b/telecomm/java/android/telecomm/InCallAdapter.java
index 0bef419..86b7a50 100644
--- a/telecomm/java/android/telecomm/InCallAdapter.java
+++ b/telecomm/java/android/telecomm/InCallAdapter.java
@@ -199,15 +199,14 @@ public final class InCallAdapter {
}
/**
- * Instructs Telecomm to conference the specified calls together.
+ * Instructs Telecomm to conference the specified call.
*
* @param callId The unique ID of the call.
- * @param callIdToConference The unique ID of the call to conference with.
* @hide
*/
- void conferenceWith(String callId, String callIdToConference) {
+ public void conference(String callId) {
try {
- mAdapter.conferenceWith(callId, callIdToConference);
+ mAdapter.conference(callId);
} catch (RemoteException ignored) {
}
}
@@ -219,7 +218,7 @@ public final class InCallAdapter {
* @param callId The unique ID of the call.
* @hide
*/
- void splitFromConference(String callId) {
+ public void splitFromConference(String callId) {
try {
mAdapter.splitFromConference(callId);
} catch (RemoteException ignored) {
diff --git a/telecomm/java/android/telecomm/InCallCall.java b/telecomm/java/android/telecomm/InCallCall.java
index b531ccd..432e378 100644
--- a/telecomm/java/android/telecomm/InCallCall.java
+++ b/telecomm/java/android/telecomm/InCallCall.java
@@ -39,7 +39,6 @@ public final class InCallCall implements Parcelable {
private final GatewayInfo mGatewayInfo;
private final CallServiceDescriptor mCurrentCallServiceDescriptor;
private final CallServiceDescriptor mHandoffCallServiceDescriptor;
- private final List<String> mConferenceCapableCallIds;
private final String mParentCallId;
private final List<String> mChildCallIds;
@@ -57,8 +56,7 @@ public final class InCallCall implements Parcelable {
CallServiceDescriptor descriptor,
CallServiceDescriptor handoffDescriptor) {
this(id, state, disconnectCauseCode, disconnectCauseMsg, capabilities, connectTimeMillis,
- handle, gatewayInfo, descriptor, handoffDescriptor, Collections.EMPTY_LIST, null,
- Collections.EMPTY_LIST);
+ handle, gatewayInfo, descriptor, handoffDescriptor, null, Collections.EMPTY_LIST);
}
/** @hide */
@@ -73,7 +71,6 @@ public final class InCallCall implements Parcelable {
GatewayInfo gatewayInfo,
CallServiceDescriptor descriptor,
CallServiceDescriptor handoffDescriptor,
- List<String> conferenceCapableCallIds,
String parentCallId,
List<String> childCallIds) {
mId = id;
@@ -86,7 +83,6 @@ public final class InCallCall implements Parcelable {
mGatewayInfo = gatewayInfo;
mCurrentCallServiceDescriptor = descriptor;
mHandoffCallServiceDescriptor = handoffDescriptor;
- mConferenceCapableCallIds = conferenceCapableCallIds;
mParentCallId = parentCallId;
mChildCallIds = childCallIds;
}
@@ -151,14 +147,6 @@ public final class InCallCall implements Parcelable {
}
/**
- * The calls with which this call can conference.
- * @hide
- */
- public List<String> getConferenceCapableCallIds() {
- return mConferenceCapableCallIds;
- }
-
- /**
* The conference call to which this call is conferenced. Null if not conferenced.
* @hide
*/
@@ -191,14 +179,12 @@ public final class InCallCall implements Parcelable {
GatewayInfo gatewayInfo = source.readParcelable(classLoader);
CallServiceDescriptor descriptor = source.readParcelable(classLoader);
CallServiceDescriptor handoffDescriptor = source.readParcelable(classLoader);
- List<String> conferenceCapableCallIds = new ArrayList<>();
- source.readList(conferenceCapableCallIds, classLoader);
String parentCallId = source.readString();
List<String> childCallIds = new ArrayList<>();
source.readList(childCallIds, classLoader);
return new InCallCall(id, state, disconnectCauseCode, disconnectCauseMsg, capabilities,
connectTimeMillis, handle, gatewayInfo, descriptor, handoffDescriptor,
- conferenceCapableCallIds, parentCallId, childCallIds);
+ parentCallId, childCallIds);
}
@Override
@@ -226,8 +212,12 @@ public final class InCallCall implements Parcelable {
destination.writeParcelable(mGatewayInfo, 0);
destination.writeParcelable(mCurrentCallServiceDescriptor, 0);
destination.writeParcelable(mHandoffCallServiceDescriptor, 0);
- destination.writeList(mConferenceCapableCallIds);
destination.writeString(mParentCallId);
destination.writeList(mChildCallIds);
}
+
+ @Override
+ public String toString() {
+ return String.format("[%s, parent:%s, children:%s]", mId, mParentCallId, mChildCallIds);
+ }
}
diff --git a/telecomm/java/com/android/internal/telecomm/ICallService.aidl b/telecomm/java/com/android/internal/telecomm/ICallService.aidl
index 9139aa6..827f331 100644
--- a/telecomm/java/com/android/internal/telecomm/ICallService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ICallService.aidl
@@ -56,9 +56,9 @@ oneway interface ICallService {
void stopDtmfTone(String callId);
- void addToConference(String conferenceCallId, in List<String> callIds);
+ void conference(String conferenceCallId, String callId);
- void splitFromConference(String conferenceCallId, String callId);
+ void splitFromConference(String callId);
void onPostDialContinue(String callId, boolean proceed);
}
diff --git a/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl b/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
index b380293..6e176eb 100644
--- a/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
@@ -47,9 +47,11 @@ oneway interface ICallServiceAdapter {
void setRequestingRingback(String callId, boolean ringing);
- void setCanConferenceWith(String callId, in List<String> conferenceCapableCallIds);
+ void setCanConference(String callId, boolean canConference);
- void setIsConferenced(String conferenceCallId, String callId, boolean isConferenced);
+ void setIsConferenced(String callId, String conferenceCallId);
+
+ void addConferenceCall(String callId, in CallInfo callInfo);
void removeCall(String callId);
diff --git a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
index f144043..5717456 100644
--- a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
@@ -48,7 +48,7 @@ oneway interface IInCallAdapter {
void handoffCall(String callId);
- void conferenceWith(String callId, String callIdToConference);
+ void conference(String callId);
void splitFromConference(String callId);
}