diff options
39 files changed, 3258 insertions, 660 deletions
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index e3d8e2047c96..1e8743cae68a 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -117,6 +117,40 @@ public class KeyguardManager { } /** + * isKeyguardLocked + * + * Return whether the keyguard is currently locked. + * + * @return true if in keyguard is locked. + * + * @hide + */ + public boolean isKeyguardLocked() { + try { + return mWM.isKeyguardSecure(); + } catch (RemoteException ex) { + return false; + } + } + + /** + * isKeyguardSecure + * + * Return whether the keyguard requires a password to unlock. + * + * @return true if in keyguard is secure. + * + * @hide + */ + public boolean isKeyguardSecure() { + try { + return mWM.isKeyguardSecure(); + } catch (RemoteException ex) { + return false; + } + } + + /** * If keyguard screen is showing or in restricted key input mode (i.e. in * keyguard password emergency screen). When in such mode, certain keys, * such as the Home key and the right soft keys, don't work. diff --git a/core/java/android/app/ListActivity.java b/core/java/android/app/ListActivity.java index d49968f8bfcc..2162521edce1 100644 --- a/core/java/android/app/ListActivity.java +++ b/core/java/android/app/ListActivity.java @@ -43,7 +43,7 @@ import android.widget.ListView; * <p> * Optionally, your custom view can contain another view object of any type to * display when the list view is empty. This "empty list" notifier must have an - * id "android:empty". Note that when an empty view is present, the list view + * id "android:id/empty". Note that when an empty view is present, the list view * will be hidden when there is no data to display. * <p> * The following code demonstrates an (ugly) custom screen layout. It has a list @@ -59,14 +59,14 @@ import android.widget.ListView; * android:paddingLeft="8dp" * android:paddingRight="8dp"> * - * <ListView android:id="@id/android:list" + * <ListView android:id="@android:id/list" * android:layout_width="match_parent" * android:layout_height="match_parent" * android:background="#00FF00" * android:layout_weight="1" * android:drawSelectorOnTop="false"/> * - * <TextView android:id="@id/android:empty" + * <TextView android:id="@android:id/empty" * android:layout_width="match_parent" * android:layout_height="match_parent" * android:background="#FF0000" diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 4656e153915d..1f4fe801e638 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -1049,6 +1049,9 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.A2DP) { BluetoothA2dp a2dp = new BluetoothA2dp(context, listener); return true; + } else if (profile == BluetoothProfile.INPUT_DEVICE) { + BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener); + return true; } else { return false; } diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java index 6ec347f65b79..116a0687d5f4 100644 --- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java +++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java @@ -136,17 +136,17 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine newState == BluetoothProfile.STATE_DISCONNECTED) { sendMessage(TRANSITION_TO_STABLE); } - } else if (action.equals(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED)) { - int newState = intent.getIntExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, 0); + } else if (action.equals(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED)) { + int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0); int oldState = - intent.getIntExtra(BluetoothInputDevice.EXTRA_PREVIOUS_INPUT_DEVICE_STATE, 0); + intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0); - if (oldState == BluetoothInputDevice.STATE_CONNECTED && - newState == BluetoothInputDevice.STATE_DISCONNECTED) { + if (oldState == BluetoothProfile.STATE_CONNECTED && + newState == BluetoothProfile.STATE_DISCONNECTED) { sendMessage(DISCONNECT_HID_INCOMING); } - if (newState == BluetoothInputDevice.STATE_CONNECTED || - newState == BluetoothInputDevice.STATE_DISCONNECTED) { + if (newState == BluetoothProfile.STATE_CONNECTED || + newState == BluetoothProfile.STATE_DISCONNECTED) { sendMessage(TRANSITION_TO_STABLE); } } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) { @@ -194,7 +194,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED); + filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); mContext.registerReceiver(mBroadcastReceiver, filter); @@ -286,7 +286,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine sendMessage(DISCONNECT_A2DP_OUTGOING); deferMessage(message); break; - } else if (mService.getInputDeviceState(mDevice) != + } else if (mService.getInputDeviceConnectionState(mDevice) != BluetoothInputDevice.STATE_DISCONNECTED) { sendMessage(DISCONNECT_HID_OUTGOING); deferMessage(message); diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java index a70de59a48f6..df212a82d4e6 100644 --- a/core/java/android/bluetooth/BluetoothInputDevice.java +++ b/core/java/android/bluetooth/BluetoothInputDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,91 +27,88 @@ import android.util.Log; import java.util.ArrayList; import java.util.List; + /** - * Public API for controlling the Bluetooth HID (Input Device) Profile - * - * BluetoothInputDevice is a proxy object used to make calls to Bluetooth Service - * which handles the HID profile. + * This class provides the public APIs to control the Bluetooth Input + * Device Profile. * - * Creating a BluetoothInputDevice object will initiate a binding with the - * Bluetooth service. Users of this object should call close() when they - * are finished, so that this proxy object can unbind from the service. + *<p>BluetoothInputDevice is a proxy object for controlling the Bluetooth + * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get + * the BluetoothInputDevice proxy object. * - * Currently the Bluetooth service runs in the system server and this - * proxy object will be immediately bound to the service on construction. - * - * @hide + *<p>Each method is protected with its appropriate permission. + *@hide */ -public final class BluetoothInputDevice { +public final class BluetoothInputDevice implements BluetoothProfile { private static final String TAG = "BluetoothInputDevice"; private static final boolean DBG = false; - /** int extra for ACTION_INPUT_DEVICE_STATE_CHANGED */ - public static final String EXTRA_INPUT_DEVICE_STATE = - "android.bluetooth.inputdevice.extra.INPUT_DEVICE_STATE"; - /** int extra for ACTION_INPUT_DEVICE_STATE_CHANGED */ - public static final String EXTRA_PREVIOUS_INPUT_DEVICE_STATE = - "android.bluetooth.inputdevice.extra.PREVIOUS_INPUT_DEVICE_STATE"; - - /** Indicates the state of an input device has changed. - * This intent will always contain EXTRA_INPUT_DEVICE_STATE, - * EXTRA_PREVIOUS_INPUT_DEVICE_STATE and BluetoothDevice.EXTRA_DEVICE - * extras. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_INPUT_DEVICE_STATE_CHANGED = - "android.bluetooth.inputdevice.action.INPUT_DEVICE_STATE_CHANGED"; - - public static final int STATE_DISCONNECTED = 0; - public static final int STATE_CONNECTING = 1; - public static final int STATE_CONNECTED = 2; - public static final int STATE_DISCONNECTING = 3; - - /** - * Auto connection, incoming and outgoing connection are allowed at this - * priority level. - */ - public static final int PRIORITY_AUTO_CONNECT = 1000; - /** - * Incoming and outgoing connection are allowed at this priority level - */ - public static final int PRIORITY_ON = 100; - /** - * Connections to the device are not allowed at this priority level. - */ - public static final int PRIORITY_OFF = 0; /** - * Default priority level when the device is unpaired. + * Intent used to broadcast the change in connection state of the Input + * Device profile. + * + * <p>This intent will have 3 extras: + * <ul> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * </ul> + * + * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of + * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, + * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to + * receive. */ - public static final int PRIORITY_UNDEFINED = -1; + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_CONNECTION_STATE_CHANGED = + "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED"; /** * Return codes for the connect and disconnect Bluez / Dbus calls. + * @hide */ public static final int INPUT_DISCONNECT_FAILED_NOT_CONNECTED = 5000; + /** + * @hide + */ public static final int INPUT_CONNECT_FAILED_ALREADY_CONNECTED = 5001; + /** + * @hide + */ public static final int INPUT_CONNECT_FAILED_ATTEMPT_FAILED = 5002; + /** + * @hide + */ public static final int INPUT_OPERATION_GENERIC_FAILURE = 5003; + /** + * @hide + */ public static final int INPUT_OPERATION_SUCCESS = 5004; - private final IBluetooth mService; - private final Context mContext; + private ServiceListener mServiceListener; + private BluetoothAdapter mAdapter; + private IBluetooth mService; /** * Create a BluetoothInputDevice proxy object for interacting with the local - * Bluetooth Service which handle the HID profile. - * @param c Context + * Bluetooth Service which handles the InputDevice profile + * */ - public BluetoothInputDevice(Context c) { - mContext = c; - + /*package*/ BluetoothInputDevice(Context mContext, ServiceListener l) { IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE); + mServiceListener = l; + mAdapter = BluetoothAdapter.getDefaultAdapter(); if (b != null) { mService = IBluetooth.Stub.asInterface(b); + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, this); + } } else { Log.w(TAG, "Bluetooth Service not available!"); @@ -121,130 +118,151 @@ public final class BluetoothInputDevice { } } - /** Initiate a connection to an Input device. - * - * This function returns false on error and true if the connection - * attempt is being made. - * - * Listen for INPUT_DEVICE_STATE_CHANGED_ACTION to find out when the - * connection is completed. - * @param device Remote BT device. - * @return false on immediate error, true otherwise - * @hide + /** + * {@inheritDoc} + * @hide */ - public boolean connectInputDevice(BluetoothDevice device) { - if (DBG) log("connectInputDevice(" + device + ")"); - try { - return mService.connectInputDevice(device); - } catch (RemoteException e) { - Log.e(TAG, "", e); - return false; + public boolean connect(BluetoothDevice device) { + if (DBG) log("connect(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.connectInputDevice(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; } - /** Initiate disconnect from an Input Device. - * This function return false on error and true if the disconnection - * attempt is being made. - * - * Listen for INPUT_DEVICE_STATE_CHANGED_ACTION to find out when - * disconnect is completed. - * - * @param device Remote BT device. - * @return false on immediate error, true otherwise - * @hide + /** + * {@inheritDoc} + * @hide */ - public boolean disconnectInputDevice(BluetoothDevice device) { - if (DBG) log("disconnectInputDevice(" + device + ")"); - try { - return mService.disconnectInputDevice(device); - } catch (RemoteException e) { - Log.e(TAG, "", e); - return false; + public boolean disconnect(BluetoothDevice device) { + if (DBG) log("disconnect(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.disconnectInputDevice(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; } - /** Check if a specified InputDevice is connected. - * - * @param device Remote BT device. - * @return True if connected , false otherwise and on error. - * @hide + /** + * {@inheritDoc} */ - public boolean isInputDeviceConnected(BluetoothDevice device) { - if (DBG) log("isInputDeviceConnected(" + device + ")"); - int state = getInputDeviceState(device); - if (state == STATE_CONNECTED) return true; - return false; + public List<BluetoothDevice> getConnectedDevices() { + if (DBG) log("getConnectedDevices()"); + if (mService != null && isEnabled()) { + try { + return mService.getConnectedInputDevices(); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); } - /** Check if any Input Device is connected. - * - * @return List of devices, empty List on error. - * @hide + /** + * {@inheritDoc} */ - public List<BluetoothDevice> getConnectedInputDevices() { - if (DBG) log("getConnectedInputDevices()"); - try { - return mService.getConnectedInputDevices(); - } catch (RemoteException e) { - Log.e(TAG, "", e); - return new ArrayList<BluetoothDevice>(); + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + if (DBG) log("getDevicesMatchingStates()"); + if (mService != null && isEnabled()) { + try { + return mService.getInputDevicesMatchingConnectionStates(states); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); } - /** Get the state of an Input Device. - * - * @param device Remote BT device. - * @return The current state of the Input Device - * @hide + /** + * {@inheritDoc} */ - public int getInputDeviceState(BluetoothDevice device) { - if (DBG) log("getInputDeviceState(" + device + ")"); - try { - return mService.getInputDeviceState(device); - } catch (RemoteException e) { - Log.e(TAG, "", e); - return STATE_DISCONNECTED; + public int getConnectionState(BluetoothDevice device) { + if (DBG) log("getState(" + device + ")"); + if (mService != null && isEnabled() + && isValidDevice(device)) { + try { + return mService.getInputDeviceConnectionState(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return BluetoothProfile.STATE_DISCONNECTED; + } } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.STATE_DISCONNECTED; } /** - * Set priority of an input device. - * - * Priority is a non-negative integer. Priority can take the following - * values: - * {@link PRIORITY_ON}, {@link PRIORITY_OFF}, {@link PRIORITY_AUTO_CONNECT} - * - * @param device Paired device. - * @param priority Integer priority - * @return true if priority is set, false on error + * {@inheritDoc} + * @hide */ - public boolean setInputDevicePriority(BluetoothDevice device, int priority) { - if (DBG) log("setInputDevicePriority(" + device + ", " + priority + ")"); - try { - return mService.setInputDevicePriority(device, priority); - } catch (RemoteException e) { - Log.e(TAG, "", e); - return false; + public boolean setPriority(BluetoothDevice device, int priority) { + if (DBG) log("setPriority(" + device + ", " + priority + ")"); + if (mService != null && isEnabled() + && isValidDevice(device)) { + if (priority != BluetoothProfile.PRIORITY_OFF && + priority != BluetoothProfile.PRIORITY_ON) { + return false; + } + try { + return mService.setInputDevicePriority(device, priority); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; } /** - * Get the priority associated with an Input Device. - * - * @param device Input Device - * @return non-negative priority, or negative error code on error. + * {@inheritDoc} + * @hide */ - public int getInputDevicePriority(BluetoothDevice device) { - if (DBG) log("getInputDevicePriority(" + device + ")"); - try { - return mService.getInputDevicePriority(device); - } catch (RemoteException e) { - Log.e(TAG, "", e); - return PRIORITY_OFF; + public int getPriority(BluetoothDevice device) { + if (DBG) log("getPriority(" + device + ")"); + if (mService != null && isEnabled() + && isValidDevice(device)) { + try { + return mService.getInputDevicePriority(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return BluetoothProfile.PRIORITY_OFF; + } } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.PRIORITY_OFF; + } + + private boolean isEnabled() { + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; + } + + private boolean isValidDevice(BluetoothDevice device) { + if (device == null) return false; + + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; } private static void log(String msg) { - Log.d(TAG, msg); + Log.d(TAG, msg); } } diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index ef80195d935d..1ffee7205395 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -62,6 +62,11 @@ public interface BluetoothProfile { * A2DP profile. */ public static final int A2DP = 2; + /** + * Input Device Profile + * @hide + */ + public static final int INPUT_DEVICE = 3; /** * Default priority for devices that we try to auto-connect to and diff --git a/core/java/android/bluetooth/BluetoothProfileState.java b/core/java/android/bluetooth/BluetoothProfileState.java index 3f36926a9ea7..18060a0234d5 100644 --- a/core/java/android/bluetooth/BluetoothProfileState.java +++ b/core/java/android/bluetooth/BluetoothProfileState.java @@ -72,10 +72,10 @@ public class BluetoothProfileState extends HierarchicalStateMachine { newState == BluetoothProfile.STATE_DISCONNECTED)) { sendMessage(TRANSITION_TO_STABLE); } - } else if (action.equals(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED)) { - int newState = intent.getIntExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, 0); - if (mProfile == HID && (newState == BluetoothInputDevice.STATE_CONNECTED || - newState == BluetoothInputDevice.STATE_DISCONNECTED)) { + } else if (action.equals(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED)) { + int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0); + if (mProfile == HID && (newState == BluetoothProfile.STATE_CONNECTED || + newState == BluetoothProfile.STATE_DISCONNECTED)) { sendMessage(TRANSITION_TO_STABLE); } } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) { @@ -96,7 +96,7 @@ public class BluetoothProfileState extends HierarchicalStateMachine { IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED); + filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); context.registerReceiver(mBroadcastReceiver, filter); } diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl index f3e73cf5db2f..69fb06a0f7b0 100644 --- a/core/java/android/bluetooth/IBluetooth.aidl +++ b/core/java/android/bluetooth/IBluetooth.aidl @@ -85,7 +85,8 @@ interface IBluetooth boolean connectInputDevice(in BluetoothDevice device); boolean disconnectInputDevice(in BluetoothDevice device); List<BluetoothDevice> getConnectedInputDevices(); - int getInputDeviceState(in BluetoothDevice device); + List<BluetoothDevice> getInputDevicesMatchingConnectionStates(in int[] states); + int getInputDeviceConnectionState(in BluetoothDevice device); boolean setInputDevicePriority(in BluetoothDevice device, int priority); int getInputDevicePriority(in BluetoothDevice device); diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 85f64d058bde..81eb09c1ad99 100755 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -115,7 +115,7 @@ public class Resources { private CompatibilityInfo mCompatibilityInfo; private Display mDefaultDisplay; - private static final LongSparseArray<Object> EMPTY_ARRAY = new LongSparseArray<Object>() { + private static final LongSparseArray<Object> EMPTY_ARRAY = new LongSparseArray<Object>(0) { @Override public void put(long k, Object o) { throw new UnsupportedOperationException(); diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index 3316ea51f701..c0b3cc8fb523 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -57,6 +57,7 @@ class BluetoothEventLoop { private final BluetoothService mBluetoothService; private final BluetoothAdapter mAdapter; private BluetoothA2dp mA2dp; + private BluetoothInputDevice mInputDevice; private final Context mContext; // The WakeLock is used for bringing up the LCD during a pairing request // from remote device when Android is in Suspend state. @@ -125,15 +126,24 @@ class BluetoothEventLoop { /*package*/ void getProfileProxy() { mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.A2DP); + mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.INPUT_DEVICE); } private BluetoothProfile.ServiceListener mProfileServiceListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { - mA2dp = (BluetoothA2dp) proxy; + if (profile == BluetoothProfile.A2DP) { + mA2dp = (BluetoothA2dp) proxy; + } else if (profile == BluetoothProfile.INPUT_DEVICE) { + mInputDevice = (BluetoothInputDevice) proxy; + } } public void onServiceDisconnected(int profile) { - mA2dp = null; + if (profile == BluetoothProfile.A2DP) { + mA2dp = null; + } else if (profile == BluetoothProfile.INPUT_DEVICE) { + mInputDevice = null; + } } }; @@ -651,10 +661,9 @@ class BluetoothEventLoop { } else { Log.i(TAG, "Rejecting incoming A2DP / AVRCP connection from " + address); } - } else if (BluetoothUuid.isInputDevice(uuid) && !isOtherInputDeviceConnected(address)) { - BluetoothInputDevice inputDevice = new BluetoothInputDevice(mContext); - authorized = inputDevice.getInputDevicePriority(device) > - BluetoothInputDevice.PRIORITY_OFF; + } else if (mInputDevice != null && BluetoothUuid.isInputDevice(uuid)) { + // We can have more than 1 input device connected. + authorized = mInputDevice.getPriority(device) > BluetoothInputDevice.PRIORITY_OFF; if (authorized) { Log.i(TAG, "Allowing incoming HID connection from " + address); } else { @@ -669,18 +678,6 @@ class BluetoothEventLoop { return authorized; } - private boolean isOtherInputDeviceConnected(String address) { - List<BluetoothDevice> devices = - mBluetoothService.lookupInputDevicesMatchingStates(new int[] { - BluetoothInputDevice.STATE_CONNECTING, - BluetoothInputDevice.STATE_CONNECTED}); - - for (BluetoothDevice device : devices) { - if (!device.getAddress().equals(address)) return true; - } - return false; - } - private boolean onAgentOutOfBandDataAvailable(String objectPath) { if (!mBluetoothService.isEnabled()) return false; @@ -758,7 +755,7 @@ class BluetoothEventLoop { boolean connected = false; BluetoothDevice device = mAdapter.getRemoteDevice(address); - int state = mBluetoothService.getInputDeviceState(device); + int state = mBluetoothService.getInputDeviceConnectionState(device); if (state == BluetoothInputDevice.STATE_CONNECTING) { if (result == BluetoothInputDevice.INPUT_CONNECT_FAILED_ALREADY_CONNECTED) { connected = true; diff --git a/core/java/android/server/BluetoothInputProfileHandler.java b/core/java/android/server/BluetoothInputProfileHandler.java index 7ffa5ae2c727..cdc0f2df5d17 100644 --- a/core/java/android/server/BluetoothInputProfileHandler.java +++ b/core/java/android/server/BluetoothInputProfileHandler.java @@ -64,7 +64,7 @@ final class BluetoothInputProfileHandler { BluetoothDeviceProfileState state) { String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress()); if (objectPath == null || - getInputDeviceState(device) != BluetoothInputDevice.STATE_DISCONNECTED || + getInputDeviceConnectionState(device) != BluetoothInputDevice.STATE_DISCONNECTED || getInputDevicePriority(device) == BluetoothInputDevice.PRIORITY_OFF) { return false; } @@ -92,7 +92,7 @@ final class BluetoothInputProfileHandler { BluetoothDeviceProfileState state) { String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress()); if (objectPath == null || - getInputDeviceState(device) == BluetoothInputDevice.STATE_DISCONNECTED) { + getInputDeviceConnectionState(device) == BluetoothInputDevice.STATE_DISCONNECTED) { return false; } if (state != null) { @@ -115,7 +115,7 @@ final class BluetoothInputProfileHandler { return true; } - synchronized int getInputDeviceState(BluetoothDevice device) { + synchronized int getInputDeviceConnectionState(BluetoothDevice device) { if (mInputDevices.get(device) == null) { return BluetoothInputDevice.STATE_DISCONNECTED; } @@ -128,6 +128,11 @@ final class BluetoothInputProfileHandler { return devices; } + synchronized List<BluetoothDevice> getInputDevicesMatchingConnectionStates(int[] states) { + List<BluetoothDevice> devices = lookupInputDevicesMatchingStates(states); + return devices; + } + synchronized int getInputDevicePriority(BluetoothDevice device) { return Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()), @@ -147,7 +152,7 @@ final class BluetoothInputProfileHandler { List<BluetoothDevice> inputDevices = new ArrayList<BluetoothDevice>(); for (BluetoothDevice device: mInputDevices.keySet()) { - int inputDeviceState = getInputDeviceState(device); + int inputDeviceState = getInputDeviceConnectionState(device); for (int state : states) { if (state == inputDeviceState) { inputDevices.add(device); @@ -178,10 +183,10 @@ final class BluetoothInputProfileHandler { setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_AUTO_CONNECT); } - Intent intent = new Intent(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED); + Intent intent = new Intent(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - intent.putExtra(BluetoothInputDevice.EXTRA_PREVIOUS_INPUT_DEVICE_STATE, prevState); - intent.putExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, state); + intent.putExtra(BluetoothInputDevice.EXTRA_PREVIOUS_STATE, prevState); + intent.putExtra(BluetoothInputDevice.EXTRA_STATE, state); mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM); debugLog("InputDevice state : device: " + device + " State:" + prevState + "->" + state); diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java index a295de5660f6..70aaf0a009f1 100644 --- a/core/java/android/server/BluetoothService.java +++ b/core/java/android/server/BluetoothService.java @@ -31,6 +31,7 @@ import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDeviceProfileState; import android.bluetooth.BluetoothHeadset; +import android.bluetooth.BluetoothInputDevice; import android.bluetooth.BluetoothPan; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfileState; @@ -83,6 +84,7 @@ public class BluetoothService extends IBluetooth.Stub { private int mNativeData; private BluetoothEventLoop mEventLoop; private BluetoothHeadset mBluetoothHeadset; + private BluetoothInputDevice mInputDevice; private boolean mIsAirplaneSensitive; private boolean mIsAirplaneToggleable; private int mBluetoothState; @@ -2078,6 +2080,8 @@ public class BluetoothService extends IBluetooth.Stub { mAdapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, BluetoothProfile.HEADSET); + mAdapter.getProfileProxy(mContext, + mBluetoothProfileServiceListener, BluetoothProfile.INPUT_DEVICE); pw.println("\n--Known devices--"); for (String address : mDeviceProperties.keySet()) { @@ -2119,8 +2123,17 @@ public class BluetoothService extends IBluetooth.Stub { } } - // Rather not do this from here, but no-where else and I need this - // dump + dumpHeadsetProfile(pw); + dumpInputDeviceProfile(pw); + + pw.println("\n--Application Service Records--"); + for (Integer handle : mServiceRecordToPid.keySet()) { + Integer pid = mServiceRecordToPid.get(handle); + pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle)); + } + } + + private void dumpHeadsetProfile(PrintWriter pw) { pw.println("\n--Headset Service--"); if (mBluetoothHeadset != null) { List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices(); @@ -2158,24 +2171,60 @@ public class BluetoothService extends IBluetooth.Stub { pw.println("SCO audio connected to device:" + device); } } - - mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); } + mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); + } - pw.println("\n--Application Service Records--"); - for (Integer handle : mServiceRecordToPid.keySet()) { - Integer pid = mServiceRecordToPid.get(handle); - pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle)); + private void dumpInputDeviceProfile(PrintWriter pw) { + pw.println("\n--Bluetooth Service- Input Device Profile"); + if (mInputDevice != null) { + List<BluetoothDevice> deviceList = mInputDevice.getConnectedDevices(); + if (deviceList.size() == 0) { + pw.println("\nNo input devices connected--"); + } else { + pw.println("\nNumber of connected devices:" + deviceList.size()); + BluetoothDevice device = deviceList.get(0); + pw.println("getConnectedDevices[0] = " + device); + pw.println("Priority of Connected device = " + mInputDevice.getPriority(device)); + + switch (mInputDevice.getConnectionState(device)) { + case BluetoothInputDevice.STATE_CONNECTING: + pw.println("getConnectionState() = STATE_CONNECTING"); + break; + case BluetoothInputDevice.STATE_CONNECTED: + pw.println("getConnectionState() = STATE_CONNECTED"); + break; + case BluetoothInputDevice.STATE_DISCONNECTING: + pw.println("getConnectionState() = STATE_DISCONNECTING"); + break; + } + } + deviceList.clear(); + deviceList = mInputDevice.getDevicesMatchingConnectionStates(new int[] { + BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED}); + pw.println("--Connected and Disconnected input devices"); + for (BluetoothDevice device: deviceList) { + pw.println(device); + } } + mAdapter.closeProfileProxy(BluetoothProfile.INPUT_DEVICE, mBluetoothHeadset); } private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { - mBluetoothHeadset = (BluetoothHeadset) proxy; - } + if (profile == BluetoothProfile.HEADSET) { + mBluetoothHeadset = (BluetoothHeadset) proxy; + } else if (profile == BluetoothProfile.INPUT_DEVICE) { + mInputDevice = (BluetoothInputDevice) proxy; + } + } public void onServiceDisconnected(int profile) { - mBluetoothHeadset = null; + if (profile == BluetoothProfile.HEADSET) { + mBluetoothHeadset = null; + } else if (profile == BluetoothProfile.INPUT_DEVICE) { + mInputDevice = null; + } } }; @@ -2311,9 +2360,9 @@ public class BluetoothService extends IBluetooth.Stub { return mBluetoothInputProfileHandler.disconnectInputDeviceInternal(device); } - public synchronized int getInputDeviceState(BluetoothDevice device) { + public synchronized int getInputDeviceConnectionState(BluetoothDevice device) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - return mBluetoothInputProfileHandler.getInputDeviceState(device); + return mBluetoothInputProfileHandler.getInputDeviceConnectionState(device); } @@ -2322,6 +2371,13 @@ public class BluetoothService extends IBluetooth.Stub { return mBluetoothInputProfileHandler.getConnectedInputDevices(); } + public synchronized List<BluetoothDevice> getInputDevicesMatchingConnectionStates( + int[] states) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + return mBluetoothInputProfileHandler.getInputDevicesMatchingConnectionStates(states); + } + + public synchronized int getInputDevicePriority(BluetoothDevice device) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); return mBluetoothInputProfileHandler.getInputDevicePriority(device); diff --git a/core/java/android/util/AttributeSet.java b/core/java/android/util/AttributeSet.java index 82592b9f7e06..470526cf1bdd 100644 --- a/core/java/android/util/AttributeSet.java +++ b/core/java/android/util/AttributeSet.java @@ -56,10 +56,53 @@ package android.util; * identifier associated with a particular XML attribute name. */ public interface AttributeSet { + /** + * Returns the number of attributes available in the set. + * + * @return A positive integer, or 0 if the set is empty. + */ public int getAttributeCount(); + + /** + * Returns the name of the specified attribute. + * + * @param index Index of the desired attribute, 0...count-1. + * + * @return A String containing the name of the attribute, or null if the + * attribute cannot be found. + */ public String getAttributeName(int index); + + /** + * Returns the value of the specified attribute as a string representation. + * + * @param index Index of the desired attribute, 0...count-1. + * + * @return A String containing the value of the attribute, or null if the + * attribute cannot be found. + */ public String getAttributeValue(int index); + + /** + * Returns the value of the specified attribute as a string representation. + * The lookup is performed using the attribute name. + * + * @param namespace The namespace of the attribute to get the value from. + * @param name The name of the attribute to get the value from. + * + * @return A String containing the value of the attribute, or null if the + * attribute cannot be found. + */ public String getAttributeValue(String namespace, String name); + + /** + * Returns a description of the current position of the attribute set. + * For instance, if the attribute set is loaded from an XML document, + * the position description could indicate the current line number. + * + * @return A string representation of the current position in the set, + * may be null. + */ public String getPositionDescription(); /** @@ -80,7 +123,8 @@ public interface AttributeSet { /** * Return the index of the value of 'attribute' in the list 'options'. - * + * + * @param namespace Namespace of attribute to retrieve. * @param attribute Name of attribute to retrieve. * @param options List of strings whose values we are checking against. * @param defaultValue Value returned if attribute doesn't exist or no @@ -94,6 +138,7 @@ public interface AttributeSet { /** * Return the boolean value of 'attribute'. * + * @param namespace Namespace of attribute to retrieve. * @param attribute The attribute to retrieve. * @param defaultValue What to return if the attribute isn't found. * @@ -111,6 +156,7 @@ public interface AttributeSet { * "@package:type/resource"); the other method returns a resource * identifier that identifies the name of the attribute. * + * @param namespace Namespace of attribute to retrieve. * @param attribute The attribute to retrieve. * @param defaultValue What to return if the attribute isn't found. * @@ -122,6 +168,7 @@ public interface AttributeSet { /** * Return the integer value of 'attribute'. * + * @param namespace Namespace of attribute to retrieve. * @param attribute The attribute to retrieve. * @param defaultValue What to return if the attribute isn't found. * @@ -135,6 +182,7 @@ public interface AttributeSet { * unsigned value. In particular, the formats 0xn...n and #n...n are * handled. * + * @param namespace Namespace of attribute to retrieve. * @param attribute The attribute to retrieve. * @param defaultValue What to return if the attribute isn't found. * @@ -146,6 +194,7 @@ public interface AttributeSet { /** * Return the float value of 'attribute'. * + * @param namespace Namespace of attribute to retrieve. * @param attribute The attribute to retrieve. * @param defaultValue What to return if the attribute isn't found. * @@ -165,8 +214,7 @@ public interface AttributeSet { * * @return Index in to 'options' or defaultValue. */ - public int getAttributeListValue(int index, - String[] options, int defaultValue); + public int getAttributeListValue(int index, String[] options, int defaultValue); /** * Return the boolean value of attribute at 'index'. @@ -176,8 +224,7 @@ public interface AttributeSet { * * @return Resulting value. */ - public boolean getAttributeBooleanValue(int index, - boolean defaultValue); + public boolean getAttributeBooleanValue(int index, boolean defaultValue); /** * Return the value of attribute at 'index' as a resource identifier. @@ -193,8 +240,7 @@ public interface AttributeSet { * * @return Resulting value. */ - public int getAttributeResourceValue(int index, - int defaultValue); + public int getAttributeResourceValue(int index, int defaultValue); /** * Return the integer value of attribute at 'index'. @@ -204,8 +250,7 @@ public interface AttributeSet { * * @return Resulting value. */ - public int getAttributeIntValue(int index, - int defaultValue); + public int getAttributeIntValue(int index, int defaultValue); /** * Return the integer value of attribute at 'index' that is formatted as an @@ -217,8 +262,7 @@ public interface AttributeSet { * * @return Resulting value. */ - public int getAttributeUnsignedIntValue(int index, - int defaultValue); + public int getAttributeUnsignedIntValue(int index, int defaultValue); /** * Return the float value of attribute at 'index'. @@ -228,8 +272,7 @@ public interface AttributeSet { * * @return Resulting value. */ - public float getAttributeFloatValue(int index, - float defaultValue); + public float getAttributeFloatValue(int index, float defaultValue); /** * Return the value of the "id" attribute or null if there is not one. @@ -266,4 +309,3 @@ public interface AttributeSet { */ public int getStyleAttribute(); } - diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 51653df16d1c..dd8242a6fef1 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -100,6 +100,8 @@ interface IWindowManager void disableKeyguard(IBinder token, String tag); void reenableKeyguard(IBinder token); void exitKeyguardSecurely(IOnKeyguardExitResult callback); + boolean isKeyguardLocked(); + boolean isKeyguardSecure(); boolean inKeyguardRestrictedInputMode(); void closeSystemDialogs(String reason); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index eefce0694af2..ae06888addc1 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -6665,7 +6665,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * view specifying how it should be arranged. There are many subclasses of * ViewGroup.LayoutParams, and these correspond to the different subclasses * of ViewGroup that are responsible for arranging their children. - * @return The LayoutParams associated with this view + * + * This method may return null if this View is not attached to a parent + * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)} + * was not invoked successfully. When a View is attached to a parent + * ViewGroup, this method must not return null. + * + * @return The LayoutParams associated with this view, or null if no + * parameters have been set yet */ @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_") public ViewGroup.LayoutParams getLayoutParams() { @@ -6679,11 +6686,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * correspond to the different subclasses of ViewGroup that are responsible * for arranging their children. * - * @param params the layout parameters for this view + * @param params The layout parameters for this view, cannot be null */ public void setLayoutParams(ViewGroup.LayoutParams params) { if (params == null) { - throw new NullPointerException("params == null"); + throw new NullPointerException("Layout parameters cannot be null"); } mLayoutParams = params; requestLayout(); diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index ad069029eabe..be68cb9e4a44 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -754,6 +754,24 @@ public interface WindowManagerPolicy { void exitKeyguardSecurely(OnKeyguardExitResult callback); /** + * isKeyguardLocked + * + * Return whether the keyguard is currently locked. + * + * @return true if in keyguard is locked. + */ + public boolean isKeyguardLocked(); + + /** + * isKeyguardSecure + * + * Return whether the keyguard requires a password to unlock. + * + * @return true if in keyguard is secure. + */ + public boolean isKeyguardSecure(); + + /** * inKeyguardRestrictedKeyInputMode * * if keyguard screen is showing or in restricted key input mode (i.e. in diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 74e6628d66ef..d9f050b34fe1 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -5531,6 +5531,8 @@ public class WebView extends AbsoluteLayout ted.mPoints[0] = new Point(contentX, contentY); ted.mMetaState = ev.getMetaState(); ted.mReprocess = mDeferTouchProcess; + ted.mNativeLayer = nativeScrollableLayer( + contentX, contentY, ted.mNativeLayerRect, null); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); if (mDeferTouchProcess) { // still needs to set them for compute deltaX/Y @@ -5575,6 +5577,8 @@ public class WebView extends AbsoluteLayout ted.mPoints[0] = new Point(contentX, contentY); ted.mMetaState = ev.getMetaState(); ted.mReprocess = mDeferTouchProcess; + ted.mNativeLayer = mScrollingLayer; + ted.mNativeLayerRect.set(mScrollingLayerRect); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); mLastSentTouchTime = eventTime; if (mDeferTouchProcess) { @@ -5754,6 +5758,8 @@ public class WebView extends AbsoluteLayout ted.mPoints[0] = new Point(contentX, contentY); ted.mMetaState = ev.getMetaState(); ted.mReprocess = mDeferTouchProcess; + ted.mNativeLayer = mScrollingLayer; + ted.mNativeLayerRect.set(mScrollingLayerRect); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); } mLastTouchUpTime = eventTime; @@ -5773,6 +5779,9 @@ public class WebView extends AbsoluteLayout ted.mPoints[0] = new Point(contentX, contentY); ted.mMetaState = ev.getMetaState(); ted.mReprocess = mDeferTouchProcess; + ted.mNativeLayer = nativeScrollableLayer( + contentX, contentY, + ted.mNativeLayerRect, null); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); } else if (mPreventDefault != PREVENT_DEFAULT_YES){ mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY); @@ -6004,6 +6013,8 @@ public class WebView extends AbsoluteLayout ted.mPoints = new Point[1]; ted.mPoints[0] = new Point(x, y); ted.mAction = MotionEvent.ACTION_CANCEL; + ted.mNativeLayer = nativeScrollableLayer( + x, y, ted.mNativeLayerRect, null); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); mPreventDefault = PREVENT_DEFAULT_IGNORE; } @@ -6643,8 +6654,9 @@ public class WebView extends AbsoluteLayout // mLastTouchX and mLastTouchY are the point in the current viewport int contentX = viewToContentX(mLastTouchX + mScrollX); int contentY = viewToContentY(mLastTouchY + mScrollY); - Rect rect = new Rect(contentX - mNavSlop, contentY - mNavSlop, - contentX + mNavSlop, contentY + mNavSlop); + int slop = viewToContentDimension(mNavSlop); + Rect rect = new Rect(contentX - slop, contentY - slop, + contentX + slop, contentY + slop); nativeSelectBestAt(rect); mInitialHitTestResult = hitTestResult(null); } @@ -6718,7 +6730,8 @@ public class WebView extends AbsoluteLayout } int x = viewToContentX((int) event.getX() + mWebTextView.getLeft()); int y = viewToContentY((int) event.getY() + mWebTextView.getTop()); - nativeMotionUp(x, y, mNavSlop); + int slop = viewToContentDimension(mNavSlop); + nativeMotionUp(x, y, slop); } /** @@ -6741,6 +6754,7 @@ public class WebView extends AbsoluteLayout // mLastTouchX and mLastTouchY are the point in the current viewport int contentX = viewToContentX(mLastTouchX + mScrollX); int contentY = viewToContentY(mLastTouchY + mScrollY); + int slop = viewToContentDimension(mNavSlop); if (getSettings().supportTouchOnly()) { removeTouchHighlight(false); WebViewCore.TouchUpData touchUpData = new WebViewCore.TouchUpData(); @@ -6748,7 +6762,7 @@ public class WebView extends AbsoluteLayout // it used when processing GET_TOUCH_HIGHLIGHT_RECTS touchUpData.mMoveGeneration = 0; mWebViewCore.sendMessage(EventHub.TOUCH_UP, touchUpData); - } else if (nativePointInNavCache(contentX, contentY, mNavSlop)) { + } else if (nativePointInNavCache(contentX, contentY, slop)) { WebViewCore.MotionUpData motionUpData = new WebViewCore .MotionUpData(); motionUpData.mFrame = nativeCacheHitFramePointer(); @@ -6764,7 +6778,8 @@ public class WebView extends AbsoluteLayout } private void doMotionUp(int contentX, int contentY) { - if (nativeMotionUp(contentX, contentY, mNavSlop) && mLogEvent) { + int slop = viewToContentDimension(mNavSlop); + if (nativeMotionUp(contentX, contentY, slop) && mLogEvent) { EventLog.writeEvent(EventLogTags.BROWSER_SNAP_CENTER); } if (nativeHasCursorNode() && !nativeCursorIsTextInput()) { @@ -6777,7 +6792,8 @@ public class WebView extends AbsoluteLayout * plugin. Otherwise a NULL rectangle is returned. */ Rect getPluginBounds(int x, int y) { - if (nativePointInNavCache(x, y, mNavSlop) && nativeCacheHitIsPlugin()) { + int slop = viewToContentDimension(mNavSlop); + if (nativePointInNavCache(x, y, slop) && nativeCacheHitIsPlugin()) { return nativeCacheHitNodeBounds(); } else { return null; @@ -7161,6 +7177,9 @@ public class WebView extends AbsoluteLayout // simplicity for now, we don't set it. ted.mMetaState = 0; ted.mReprocess = mDeferTouchProcess; + ted.mNativeLayer = nativeScrollableLayer( + ted.mPoints[0].x, ted.mPoints[0].y, + ted.mNativeLayerRect, null); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); } else if (mPreventDefault != PREVENT_DEFAULT_YES) { mTouchMode = TOUCH_DONE_MODE; @@ -8033,6 +8052,8 @@ public class WebView extends AbsoluteLayout touchUpData.mNode = node; touchUpData.mX = x; touchUpData.mY = y; + touchUpData.mNativeLayer = nativeScrollableLayer( + x, y, touchUpData.mNativeLayerRect, null); mWebViewCore.sendMessage(EventHub.TOUCH_UP, touchUpData); } diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index da4ce43835dc..fb0f61ce595e 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -778,6 +778,8 @@ final class WebViewCore { int mNode; int mX; int mY; + int mNativeLayer; + Rect mNativeLayerRect = new Rect(); } static class TouchHighlightData { @@ -821,6 +823,8 @@ final class WebViewCore { int mMetaState; boolean mReprocess; MotionEvent mMotionEvent; + int mNativeLayer; + Rect mNativeLayerRect = new Rect(); } static class GeolocationPermissionsData { @@ -1304,6 +1308,10 @@ final class WebViewCore { case TOUCH_UP: TouchUpData touchUpData = (TouchUpData) msg.obj; + if (touchUpData.mNativeLayer != 0) { + nativeScrollLayer(touchUpData.mNativeLayer, + touchUpData.mNativeLayerRect); + } nativeTouchUp(touchUpData.mMoveGeneration, touchUpData.mFrame, touchUpData.mNode, touchUpData.mX, touchUpData.mY); @@ -1318,6 +1326,10 @@ final class WebViewCore { xArray[c] = ted.mPoints[c].x; yArray[c] = ted.mPoints[c].y; } + if (ted.mNativeLayer != 0) { + nativeScrollLayer(ted.mNativeLayer, + ted.mNativeLayerRect); + } Message.obtain( mWebView.mPrivateHandler, WebView.PREVENT_TOUCH_ID, @@ -2702,4 +2714,5 @@ final class WebViewCore { int slop); private native void nativeAutoFillForm(int queryId); + private native void nativeScrollLayer(int layer, Rect rect); } diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java index a84df16d2d59..0383b5c8c0cd 100644 --- a/core/java/android/widget/GridView.java +++ b/core/java/android/widget/GridView.java @@ -37,14 +37,46 @@ import android.widget.RemoteViews.RemoteView; * * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-gridview.html">Grid * View tutorial</a>.</p> + * + * @attr ref android.R.styleable#GridView_horizontalSpacing + * @attr ref android.R.styleable#GridView_verticalSpacing + * @attr ref android.R.styleable#GridView_stretchMode + * @attr ref android.R.styleable#GridView_columnWidth + * @attr ref android.R.styleable#GridView_numColumns + * @attr ref android.R.styleable#GridView_gravity */ @RemoteView public class GridView extends AbsListView { + /** + * Disables stretching. + * + * @see #setStretchMode(int) + */ public static final int NO_STRETCH = 0; + /** + * Stretches the spacing between columns. + * + * @see #setStretchMode(int) + */ public static final int STRETCH_SPACING = 1; + /** + * Stretches columns. + * + * @see #setStretchMode(int) + */ public static final int STRETCH_COLUMN_WIDTH = 2; + /** + * Stretches the spacing between columns. The spacing is uniform. + * + * @see #setStretchMode(int) + */ public static final int STRETCH_SPACING_UNIFORM = 3; - + + /** + * Creates as many columns as can fit on screen. + * + * @see #setNumColumns(int) + */ public static final int AUTO_FIT = -1; private int mNumColumns = AUTO_FIT; diff --git a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp index bf2365094917..acf858aff440 100755 --- a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp +++ b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp @@ -89,40 +89,40 @@ static int setup_listening_socket(int dev, int channel); #endif static void classInitNative(JNIEnv* env, jclass clazz) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH /* in */ field_mNativeData = get_field(env, clazz, "mNativeData", "I"); - field_mHandsfreeAgRfcommChannel = + field_mHandsfreeAgRfcommChannel = get_field(env, clazz, "mHandsfreeAgRfcommChannel", "I"); - field_mHeadsetAgRfcommChannel = + field_mHeadsetAgRfcommChannel = get_field(env, clazz, "mHeadsetAgRfcommChannel", "I"); /* out */ - field_mConnectingHeadsetAddress = - get_field(env, clazz, + field_mConnectingHeadsetAddress = + get_field(env, clazz, "mConnectingHeadsetAddress", "Ljava/lang/String;"); - field_mConnectingHeadsetRfcommChannel = + field_mConnectingHeadsetRfcommChannel = get_field(env, clazz, "mConnectingHeadsetRfcommChannel", "I"); - field_mConnectingHeadsetSocketFd = + field_mConnectingHeadsetSocketFd = get_field(env, clazz, "mConnectingHeadsetSocketFd", "I"); - field_mConnectingHandsfreeAddress = - get_field(env, clazz, + field_mConnectingHandsfreeAddress = + get_field(env, clazz, "mConnectingHandsfreeAddress", "Ljava/lang/String;"); - field_mConnectingHandsfreeRfcommChannel = + field_mConnectingHandsfreeRfcommChannel = get_field(env, clazz, "mConnectingHandsfreeRfcommChannel", "I"); - field_mConnectingHandsfreeSocketFd = + field_mConnectingHandsfreeSocketFd = get_field(env, clazz, "mConnectingHandsfreeSocketFd", "I"); - field_mTimeoutRemainingMs = + field_mTimeoutRemainingMs = get_field(env, clazz, "mTimeoutRemainingMs", "I"); #endif } static void initializeNativeDataNative(JNIEnv* env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t)); if (NULL == nat) { @@ -150,7 +150,7 @@ static void initializeNativeDataNative(JNIEnv* env, jobject object) { } static void cleanupNativeDataNative(JNIEnv* env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); if (nat) { @@ -165,7 +165,7 @@ static void cleanupNativeDataNative(JNIEnv* env, jobject object) { static int set_nb(int sk, bool nb) { int flags = fcntl(sk, F_GETFL); if (flags < 0) { - LOGE("Can't get socket flags with fcntl(): %s (%d)", + LOGE("Can't get socket flags with fcntl(): %s (%d)", strerror(errno), errno); close(sk); return -1; @@ -255,7 +255,7 @@ static inline int on_accept_set_fields(JNIEnv* env, jobject object, static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, jint timeout_ms) { -// LOGV(__FUNCTION__); +// LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH env->SetIntField(object, field_mTimeoutRemainingMs, timeout_ms); @@ -264,11 +264,11 @@ static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, native_data_t *nat = get_native_data(env, object); #if USE_ACCEPT_DIRECTLY if (nat->hf_ag_rfcomm_channel > 0) { - LOGI("Setting HF AG server socket to RFCOMM port %d!", + LOGI("Setting HF AG server socket to RFCOMM port %d!", nat->hf_ag_rfcomm_channel); struct timeval tv; int len = sizeof(tv); - if (getsockopt(nat->hf_ag_rfcomm_channel, + if (getsockopt(nat->hf_ag_rfcomm_channel, SOL_SOCKET, SO_RCVTIMEO, &tv, &len) < 0) { LOGE("getsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)", nat->hf_ag_rfcomm_channel, @@ -276,12 +276,12 @@ static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, errno); return JNI_FALSE; } - LOGI("Current HF AG server socket RCVTIMEO is (%d(s), %d(us))!", + LOGI("Current HF AG server socket RCVTIMEO is (%d(s), %d(us))!", (int)tv.tv_sec, (int)tv.tv_usec); if (timeout_ms >= 0) { tv.tv_sec = timeout_ms / 1000; tv.tv_usec = 1000 * (timeout_ms % 1000); - if (setsockopt(nat->hf_ag_rfcomm_channel, + if (setsockopt(nat->hf_ag_rfcomm_channel, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { LOGE("setsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)", nat->hf_ag_rfcomm_channel, @@ -289,11 +289,11 @@ static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, errno); return JNI_FALSE; } - LOGI("Changed HF AG server socket RCVTIMEO to (%d(s), %d(us))!", + LOGI("Changed HF AG server socket RCVTIMEO to (%d(s), %d(us))!", (int)tv.tv_sec, (int)tv.tv_usec); } - if (!do_accept(env, object, nat->hf_ag_rfcomm_sock, + if (!do_accept(env, object, nat->hf_ag_rfcomm_sock, field_mConnectingHandsfreeSocketFd, field_mConnectingHandsfreeAddress, field_mConnectingHandsfreeRfcommChannel)) @@ -309,13 +309,13 @@ static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, FD_ZERO(&rset); int cnt = 0; if (nat->hf_ag_rfcomm_channel > 0) { - LOGI("Setting HF AG server socket to RFCOMM port %d!", + LOGI("Setting HF AG server socket to RFCOMM port %d!", nat->hf_ag_rfcomm_channel); cnt++; FD_SET(nat->hf_ag_rfcomm_sock, &rset); } if (nat->hs_ag_rfcomm_channel > 0) { - LOGI("Setting HS AG server socket to RFCOMM port %d!", + LOGI("Setting HS AG server socket to RFCOMM port %d!", nat->hs_ag_rfcomm_channel); cnt++; FD_SET(nat->hs_ag_rfcomm_sock, &rset); @@ -330,7 +330,7 @@ static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, to.tv_sec = timeout_ms / 1000; to.tv_usec = 1000 * (timeout_ms % 1000); } - n = select(MAX(nat->hf_ag_rfcomm_sock, + n = select(MAX(nat->hf_ag_rfcomm_sock, nat->hs_ag_rfcomm_sock) + 1, &rset, NULL, @@ -354,7 +354,7 @@ static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, return JNI_FALSE; } - n = on_accept_set_fields(env, object, + n = on_accept_set_fields(env, object, &rset, nat->hf_ag_rfcomm_sock, field_mConnectingHandsfreeSocketFd, field_mConnectingHandsfreeAddress, @@ -371,7 +371,7 @@ static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, struct pollfd fds[2]; int cnt = 0; if (nat->hf_ag_rfcomm_channel > 0) { -// LOGI("Setting HF AG server socket %d to RFCOMM port %d!", +// LOGI("Setting HF AG server socket %d to RFCOMM port %d!", // nat->hf_ag_rfcomm_sock, // nat->hf_ag_rfcomm_channel); fds[cnt].fd = nat->hf_ag_rfcomm_sock; @@ -379,7 +379,7 @@ static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, cnt++; } if (nat->hs_ag_rfcomm_channel > 0) { -// LOGI("Setting HS AG server socket %d to RFCOMM port %d!", +// LOGI("Setting HS AG server socket %d to RFCOMM port %d!", // nat->hs_ag_rfcomm_sock, // nat->hs_ag_rfcomm_channel); fds[cnt].fd = nat->hs_ag_rfcomm_sock; @@ -411,7 +411,7 @@ static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, if (fds[cnt].fd == nat->hf_ag_rfcomm_sock) { if (fds[cnt].revents & (POLLIN | POLLPRI | POLLOUT)) { LOGI("Accepting HF connection.\n"); - err += do_accept(env, object, fds[cnt].fd, + err += do_accept(env, object, fds[cnt].fd, field_mConnectingHandsfreeSocketFd, field_mConnectingHandsfreeAddress, field_mConnectingHandsfreeRfcommChannel); @@ -421,7 +421,7 @@ static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, else if (fds[cnt].fd == nat->hs_ag_rfcomm_sock) { if (fds[cnt].revents & (POLLIN | POLLPRI | POLLOUT)) { LOGI("Accepting HS connection.\n"); - err += do_accept(env, object, fds[cnt].fd, + err += do_accept(env, object, fds[cnt].fd, field_mConnectingHeadsetSocketFd, field_mConnectingHeadsetAddress, field_mConnectingHeadsetRfcommChannel); @@ -444,7 +444,7 @@ static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, } static jboolean setUpListeningSocketsNative(JNIEnv* env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); @@ -509,7 +509,7 @@ static int setup_listening_socket(int dev, int channel) { private native void tearDownListeningSocketsNative(); */ static void tearDownListeningSocketsNative(JNIEnv *env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); diff --git a/core/jni/android_bluetooth_BluetoothSocket.cpp b/core/jni/android_bluetooth_BluetoothSocket.cpp index 31ebf8ca58cc..b87f7c4a62c0 100644 --- a/core/jni/android_bluetooth_BluetoothSocket.cpp +++ b/core/jni/android_bluetooth_BluetoothSocket.cpp @@ -66,7 +66,7 @@ static struct asocket *get_socketData(JNIEnv *env, jobject obj) { static void initSocketFromFdNative(JNIEnv *env, jobject obj, jint fd) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); struct asocket *s = asocket_init(fd); @@ -85,7 +85,7 @@ static void initSocketFromFdNative(JNIEnv *env, jobject obj, jint fd) { static void initSocketNative(JNIEnv *env, jobject obj) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); int fd; int lm = 0; @@ -161,7 +161,7 @@ static void initSocketNative(JNIEnv *env, jobject obj) { static void connectNative(JNIEnv *env, jobject obj) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); int ret; jint type; @@ -240,7 +240,7 @@ static void connectNative(JNIEnv *env, jobject obj) { /* Returns errno instead of throwing, so java can check errno */ static int bindListenNative(JNIEnv *env, jobject obj) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); jint type; socklen_t addr_sz; @@ -307,7 +307,7 @@ static int bindListenNative(JNIEnv *env, jobject obj) { static jobject acceptNative(JNIEnv *env, jobject obj, int timeout) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); int fd; jint type; @@ -380,7 +380,7 @@ static jobject acceptNative(JNIEnv *env, jobject obj, int timeout) { static jint availableNative(JNIEnv *env, jobject obj) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); int available; struct asocket *s = get_socketData(env, obj); @@ -403,7 +403,7 @@ static jint availableNative(JNIEnv *env, jobject obj) { static jint readNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset, jint length) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); int ret; jbyte *b; @@ -446,7 +446,7 @@ static jint readNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset, static jint writeNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset, jint length) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); int ret; jbyte *b; @@ -488,7 +488,7 @@ static jint writeNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset, static void abortNative(JNIEnv *env, jobject obj) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); struct asocket *s = get_socketData(env, obj); if (!s) @@ -504,7 +504,7 @@ static void abortNative(JNIEnv *env, jobject obj) { static void destroyNative(JNIEnv *env, jobject obj) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); struct asocket *s = get_socketData(env, obj); int fd = s->fd; diff --git a/core/jni/android_bluetooth_HeadsetBase.cpp b/core/jni/android_bluetooth_HeadsetBase.cpp index 4e9fbaf1bd62..bbf1ae5f8e41 100644 --- a/core/jni/android_bluetooth_HeadsetBase.cpp +++ b/core/jni/android_bluetooth_HeadsetBase.cpp @@ -180,7 +180,7 @@ again: #endif static void classInitNative(JNIEnv* env, jclass clazz) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH field_mNativeData = get_field(env, clazz, "mNativeData", "I"); field_mAddress = get_field(env, clazz, "mAddress", "Ljava/lang/String;"); @@ -191,7 +191,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) { static void initializeNativeDataNative(JNIEnv* env, jobject object, jint socketFd) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t)); if (NULL == nat) { @@ -213,7 +213,7 @@ static void initializeNativeDataNative(JNIEnv* env, jobject object, } static void cleanupNativeDataNative(JNIEnv* env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = (native_data_t *)env->GetIntField(object, field_mNativeData); @@ -226,7 +226,7 @@ static void cleanupNativeDataNative(JNIEnv* env, jobject object) { static jboolean connectNative(JNIEnv *env, jobject obj) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH int lm; struct sockaddr_rc addr; @@ -278,7 +278,7 @@ static jboolean connectNative(JNIEnv *env, jobject obj) } static jint connectAsyncNative(JNIEnv *env, jobject obj) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH struct sockaddr_rc addr; native_data_t *nat = get_native_data(env, obj); @@ -357,7 +357,7 @@ static jint connectAsyncNative(JNIEnv *env, jobject obj) { static jint waitForAsyncConnectNative(JNIEnv *env, jobject obj, jint timeout_ms) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH struct sockaddr_rc addr; native_data_t *nat = get_native_data(env, obj); @@ -463,7 +463,7 @@ static jint waitForAsyncConnectNative(JNIEnv *env, jobject obj, } static void disconnectNative(JNIEnv *env, jobject obj) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, obj); if (nat->rfcomm_sock >= 0) { diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp index 8c795afe3ee4..1851ad69fc8b 100644 --- a/core/jni/android_server_BluetoothA2dpService.cpp +++ b/core/jni/android_server_BluetoothA2dpService.cpp @@ -61,7 +61,7 @@ static Properties sink_properties[] = { * Return false if dbus is down, or another serious error (out of memory) */ static bool initNative(JNIEnv* env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH nat = (native_data_t *)calloc(1, sizeof(native_data_t)); if (NULL == nat) { @@ -88,7 +88,7 @@ static bool initNative(JNIEnv* env, jobject object) { static void cleanupNative(JNIEnv* env, jobject object) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); if (nat) { dbus_connection_close(nat->conn); env->DeleteGlobalRef(nat->me); @@ -101,7 +101,7 @@ static void cleanupNative(JNIEnv* env, jobject object) { static jobjectArray getSinkPropertiesNative(JNIEnv *env, jobject object, jstring path) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); if (nat) { DBusMessage *msg, *reply; DBusError err; @@ -132,7 +132,7 @@ static jobjectArray getSinkPropertiesNative(JNIEnv *env, jobject object, static jboolean connectSinkNative(JNIEnv *env, jobject object, jstring path) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); if (nat) { const char *c_path = env->GetStringUTFChars(path, NULL); int len = env->GetStringLength(path) + 1; @@ -153,7 +153,7 @@ static jboolean connectSinkNative(JNIEnv *env, jobject object, jstring path) { static jboolean disconnectSinkNative(JNIEnv *env, jobject object, jstring path) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); if (nat) { const char *c_path = env->GetStringUTFChars(path, NULL); @@ -171,7 +171,7 @@ static jboolean disconnectSinkNative(JNIEnv *env, jobject object, static jboolean suspendSinkNative(JNIEnv *env, jobject object, jstring path) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); if (nat) { const char *c_path = env->GetStringUTFChars(path, NULL); bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, @@ -187,7 +187,7 @@ static jboolean suspendSinkNative(JNIEnv *env, jobject object, static jboolean resumeSinkNative(JNIEnv *env, jobject object, jstring path) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); if (nat) { const char *c_path = env->GetStringUTFChars(path, NULL); bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, @@ -203,7 +203,7 @@ static jboolean resumeSinkNative(JNIEnv *env, jobject object, static jboolean avrcpVolumeUpNative(JNIEnv *env, jobject object, jstring path) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); if (nat) { const char *c_path = env->GetStringUTFChars(path, NULL); bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, @@ -219,7 +219,7 @@ static jboolean avrcpVolumeUpNative(JNIEnv *env, jobject object, static jboolean avrcpVolumeDownNative(JNIEnv *env, jobject object, jstring path) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); if (nat) { const char *c_path = env->GetStringUTFChars(path, NULL); bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, @@ -278,7 +278,7 @@ DBusHandlerResult a2dp_event_filter(DBusMessage *msg, JNIEnv *env) { } void onConnectSinkResult(DBusMessage *msg, void *user, void *n) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = (native_data_t *)n; const char *path = (const char *)user; diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp index fd12c2d736f8..afaade8b21ee 100644 --- a/core/jni/android_server_BluetoothEventLoop.cpp +++ b/core/jni/android_server_BluetoothEventLoop.cpp @@ -88,7 +88,7 @@ native_data_t *get_EventLoop_native_data(JNIEnv *env, jobject object) { #endif static void classInitNative(JNIEnv* env, jclass clazz) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH method_onPropertyChanged = env->GetMethodID(clazz, "onPropertyChanged", @@ -147,7 +147,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) { } static void initializeNativeDataNative(JNIEnv* env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t)); if (NULL == nat) { @@ -175,7 +175,7 @@ static void initializeNativeDataNative(JNIEnv* env, jobject object) { } static void cleanupNativeDataNative(JNIEnv* env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = (native_data_t *)env->GetIntField(object, field_mNativeData); @@ -216,7 +216,7 @@ static short dbus_flags_to_unix_events(unsigned int flags) { } static jboolean setUpEventLoop(native_data_t *nat) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); if (nat != NULL && nat->conn != NULL) { dbus_threads_init_default(); @@ -395,7 +395,7 @@ static int register_agent(native_data_t *nat, } static void tearDownEventLoop(native_data_t *nat) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); if (nat != NULL && nat->conn != NULL) { DBusMessage *msg, *reply; @@ -1229,7 +1229,7 @@ success: #ifdef HAVE_BLUETOOTH void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *n) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = (native_data_t *)n; const char *address = (const char *)user; @@ -1298,7 +1298,7 @@ done: } void onCreateDeviceResult(DBusMessage *msg, void *user, void *n) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = (native_data_t *)n; const char *address= (const char *)user; @@ -1328,7 +1328,7 @@ void onCreateDeviceResult(DBusMessage *msg, void *user, void *n) { } void onDiscoverServicesResult(DBusMessage *msg, void *user, void *n) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = (native_data_t *)n; const char *path = (const char *)user; @@ -1354,7 +1354,7 @@ void onDiscoverServicesResult(DBusMessage *msg, void *user, void *n) { } void onGetDeviceServiceChannelResult(DBusMessage *msg, void *user, void *n) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); const char *address = (const char *) user; native_data_t *nat = (native_data_t *) n; @@ -1387,7 +1387,7 @@ done: } void onInputDeviceConnectionResult(DBusMessage *msg, void *user, void *n) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = (native_data_t *)n; const char *path = (const char *)user; @@ -1426,7 +1426,7 @@ void onInputDeviceConnectionResult(DBusMessage *msg, void *user, void *n) { } void onPanDeviceConnectionResult(DBusMessage *msg, void *user, void *n) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = (native_data_t *)n; const char *path = (const char *)user; diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp index bf0504f7c8cc..158e47573c52 100644 --- a/core/jni/android_server_BluetoothService.cpp +++ b/core/jni/android_server_BluetoothService.cpp @@ -1,16 +1,16 @@ /* ** Copyright 2006, The Android Open Source Project ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at ** -** http://www.apache.org/licenses/LICENSE-2.0 +** http://www.apache.org/licenses/LICENSE-2.0 ** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and ** limitations under the License. */ @@ -93,7 +93,7 @@ static inline native_data_t * get_native_data(JNIEnv *env, jobject object) { #endif static void classInitNative(JNIEnv* env, jclass clazz) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH field_mNativeData = get_field(env, clazz, "mNativeData", "I"); field_mEventLoop = get_field(env, clazz, "mEventLoop", @@ -105,7 +105,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) { * Return false if dbus is down, or another serious error (out of memory) */ static bool initializeNativeDataNative(JNIEnv* env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t)); if (NULL == nat) { @@ -144,7 +144,7 @@ static const char *get_adapter_path(JNIEnv* env, jobject object) { // This function is called when the adapter is enabled. static jboolean setupNativeDataNative(JNIEnv* env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = (native_data_t *)env->GetIntField(object, field_mNativeData); @@ -167,7 +167,7 @@ static jboolean setupNativeDataNative(JNIEnv* env, jobject object) { } static jboolean tearDownNativeDataNative(JNIEnv *env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = (native_data_t *)env->GetIntField(object, field_mNativeData); @@ -181,7 +181,7 @@ static jboolean tearDownNativeDataNative(JNIEnv *env, jobject object) { } static void cleanupNativeDataNative(JNIEnv* env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = (native_data_t *)env->GetIntField(object, field_mNativeData); @@ -193,7 +193,7 @@ static void cleanupNativeDataNative(JNIEnv* env, jobject object) { } static jstring getAdapterPathNative(JNIEnv *env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); if (nat) { @@ -205,7 +205,7 @@ static jstring getAdapterPathNative(JNIEnv *env, jobject object) { static jboolean startDiscoveryNative(JNIEnv *env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH DBusMessage *msg = NULL; DBusMessage *reply = NULL; @@ -251,7 +251,7 @@ done: } static void stopDiscoveryNative(JNIEnv *env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH DBusMessage *msg = NULL; DBusMessage *reply = NULL; @@ -297,7 +297,7 @@ done: } static jbyteArray readAdapterOutOfBandDataNative(JNIEnv *env, jobject object) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); DBusError err; @@ -338,7 +338,7 @@ static jbyteArray readAdapterOutOfBandDataNative(JNIEnv *env, jobject object) { static jboolean createPairedDeviceNative(JNIEnv *env, jobject object, jstring address, jint timeout_ms) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); jobject eventLoop = env->GetObjectField(object, field_mEventLoop); @@ -374,7 +374,7 @@ static jboolean createPairedDeviceNative(JNIEnv *env, jobject object, static jboolean createPairedDeviceOutOfBandNative(JNIEnv *env, jobject object, jstring address, jint timeout_ms) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); jobject eventLoop = env->GetObjectField(object, field_mEventLoop); @@ -411,7 +411,7 @@ static jint getDeviceServiceChannelNative(JNIEnv *env, jobject object, jstring path, jstring pattern, jint attr_id) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = get_native_data(env, object); jobject eventLoop = env->GetObjectField(object, field_mEventLoop); struct event_loop_native_data_t *eventLoopNat = @@ -437,7 +437,7 @@ static jint getDeviceServiceChannelNative(JNIEnv *env, jobject object, static jboolean cancelDeviceCreationNative(JNIEnv *env, jobject object, jstring address) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); jboolean result = JNI_FALSE; #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); @@ -469,7 +469,7 @@ static jboolean cancelDeviceCreationNative(JNIEnv *env, jobject object, } static jboolean removeDeviceNative(JNIEnv *env, jobject object, jstring object_path) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); if (nat) { @@ -492,7 +492,7 @@ static jboolean removeDeviceNative(JNIEnv *env, jobject object, jstring object_p static jint enableNative(JNIEnv *env, jobject object) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); return bt_enable(); #endif return -1; @@ -500,7 +500,7 @@ static jint enableNative(JNIEnv *env, jobject object) { static jint disableNative(JNIEnv *env, jobject object) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); return bt_disable(); #endif return -1; @@ -508,7 +508,7 @@ static jint disableNative(JNIEnv *env, jobject object) { static jint isEnabledNative(JNIEnv *env, jobject object) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); return bt_is_enabled(); #endif return -1; @@ -518,7 +518,7 @@ static jboolean setPairingConfirmationNative(JNIEnv *env, jobject object, jstring address, bool confirm, int nativeData) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = get_native_data(env, object); if (nat) { DBusMessage *msg = (DBusMessage *)nativeData; @@ -549,7 +549,7 @@ static jboolean setPairingConfirmationNative(JNIEnv *env, jobject object, static jboolean setPasskeyNative(JNIEnv *env, jobject object, jstring address, int passkey, int nativeData) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = get_native_data(env, object); if (nat) { DBusMessage *msg = (DBusMessage *)nativeData; @@ -576,7 +576,7 @@ static jboolean setPasskeyNative(JNIEnv *env, jobject object, jstring address, static jboolean setRemoteOutOfBandDataNative(JNIEnv *env, jobject object, jstring address, jbyteArray hash, jbyteArray randomizer, int nativeData) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = get_native_data(env, object); if (nat) { DBusMessage *msg = (DBusMessage *)nativeData; @@ -610,7 +610,7 @@ static jboolean setRemoteOutOfBandDataNative(JNIEnv *env, jobject object, jstrin static jboolean setPinNative(JNIEnv *env, jobject object, jstring address, jstring pin, int nativeData) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = get_native_data(env, object); if (nat) { DBusMessage *msg = (DBusMessage *)nativeData; @@ -640,7 +640,7 @@ static jboolean setPinNative(JNIEnv *env, jobject object, jstring address, static jboolean cancelPairingUserInputNative(JNIEnv *env, jobject object, jstring address, int nativeData) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = get_native_data(env, object); if (nat) { DBusMessage *msg = (DBusMessage *)nativeData; @@ -666,7 +666,7 @@ static jobjectArray getDevicePropertiesNative(JNIEnv *env, jobject object, jstring path) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = get_native_data(env, object); if (nat) { DBusMessage *msg, *reply; @@ -705,7 +705,7 @@ static jobjectArray getDevicePropertiesNative(JNIEnv *env, jobject object, static jobjectArray getAdapterPropertiesNative(JNIEnv *env, jobject object) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = get_native_data(env, object); if (nat) { DBusMessage *msg, *reply; @@ -741,7 +741,7 @@ static jobjectArray getAdapterPropertiesNative(JNIEnv *env, jobject object) { static jboolean setAdapterPropertyNative(JNIEnv *env, jobject object, jstring key, void *value, jint type) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = get_native_data(env, object); if (nat) { DBusMessage *msg; @@ -808,7 +808,7 @@ static jboolean setAdapterPropertyBooleanNative(JNIEnv *env, jobject object, jst static jboolean setDevicePropertyNative(JNIEnv *env, jobject object, jstring path, jstring key, void *value, jint type) { #ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); native_data_t *nat = get_native_data(env, object); if (nat) { DBusMessage *reply, *msg; @@ -863,7 +863,7 @@ static jboolean setDevicePropertyBooleanNative(JNIEnv *env, jobject object, static jboolean createDeviceNative(JNIEnv *env, jobject object, jstring address) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); jobject eventLoop = env->GetObjectField(object, field_mEventLoop); @@ -894,7 +894,7 @@ static jboolean createDeviceNative(JNIEnv *env, jobject object, static jboolean discoverServicesNative(JNIEnv *env, jobject object, jstring path, jstring pattern) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); jobject eventLoop = env->GetObjectField(object, field_mEventLoop); @@ -955,7 +955,7 @@ static jintArray extract_handles(JNIEnv *env, DBusMessage *reply) { static jintArray addReservedServiceRecordsNative(JNIEnv *env, jobject object, jintArray uuids) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH DBusMessage *reply = NULL; @@ -979,7 +979,7 @@ static jintArray addReservedServiceRecordsNative(JNIEnv *env, jobject object, static jboolean removeReservedServiceRecordsNative(JNIEnv *env, jobject object, jintArray handles) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); jint *values = env->GetIntArrayElements(handles, NULL); @@ -1002,7 +1002,7 @@ static jboolean removeReservedServiceRecordsNative(JNIEnv *env, jobject object, static jint addRfcommServiceRecordNative(JNIEnv *env, jobject object, jstring name, jlong uuidMsb, jlong uuidLsb, jshort channel) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); if (nat) { @@ -1027,7 +1027,7 @@ static jint addRfcommServiceRecordNative(JNIEnv *env, jobject object, } static jboolean removeServiceRecordNative(JNIEnv *env, jobject object, jint handle) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); if (nat) { @@ -1045,7 +1045,7 @@ static jboolean removeServiceRecordNative(JNIEnv *env, jobject object, jint hand static jboolean setLinkTimeoutNative(JNIEnv *env, jobject object, jstring object_path, jint num_slots) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); if (nat) { @@ -1064,7 +1064,7 @@ static jboolean setLinkTimeoutNative(JNIEnv *env, jobject object, jstring object } static jboolean connectInputDeviceNative(JNIEnv *env, jobject object, jstring path) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); jobject eventLoop = env->GetObjectField(object, field_mEventLoop); @@ -1092,7 +1092,7 @@ static jboolean connectInputDeviceNative(JNIEnv *env, jobject object, jstring pa static jboolean disconnectInputDeviceNative(JNIEnv *env, jobject object, jstring path) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); jobject eventLoop = env->GetObjectField(object, field_mEventLoop); @@ -1120,7 +1120,7 @@ static jboolean disconnectInputDeviceNative(JNIEnv *env, jobject object, static jboolean setBluetoothTetheringNative(JNIEnv *env, jobject object, jboolean value, jstring src_role, jstring bridge) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); if (nat) { @@ -1155,7 +1155,7 @@ static jboolean setBluetoothTetheringNative(JNIEnv *env, jobject object, jboolea static jboolean connectPanDeviceNative(JNIEnv *env, jobject object, jstring path, jstring dstRole) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH LOGE("connectPanDeviceNative"); native_data_t *nat = get_native_data(env, object); @@ -1187,7 +1187,7 @@ static jboolean connectPanDeviceNative(JNIEnv *env, jobject object, jstring path static jboolean disconnectPanDeviceNative(JNIEnv *env, jobject object, jstring path) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH LOGE("disconnectPanDeviceNative"); native_data_t *nat = get_native_data(env, object); @@ -1217,7 +1217,7 @@ static jboolean disconnectPanDeviceNative(JNIEnv *env, jobject object, static jboolean disconnectPanServerDeviceNative(JNIEnv *env, jobject object, jstring path, jstring address, jstring iface) { - LOGV(__FUNCTION__); + LOGV("%s", __FUNCTION__); #ifdef HAVE_BLUETOOTH LOGE("disconnectPanServerDeviceNative"); native_data_t *nat = get_native_data(env, object); diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 6f37dc097010..d9eccd6f2729 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2256,18 +2256,29 @@ <attr name="unselectedAlpha" format="float" /> </declare-styleable> <declare-styleable name="GridView"> + <!-- Defines the default horizontal spacing between columns. --> <attr name="horizontalSpacing" format="dimension" /> + <!-- Defines the default vertical spacing between rows. --> <attr name="verticalSpacing" format="dimension" /> + <!-- Defines how columns should stretch to fill the available empty space, if any. --> <attr name="stretchMode"> + <!-- Stretching is disabled. --> <enum name="none" value="0"/> + <!-- The spacing between each column is stretched. --> <enum name="spacingWidth" value="1" /> + <!-- Each column is stretched equally. --> <enum name="columnWidth" value="2" /> + <!-- The spacing between each column is uniformly stretched.. --> <enum name="spacingWidthUniform" value="3" /> </attr> + <!-- Specifies the fixed width for each column. --> <attr name="columnWidth" format="dimension" /> + <!-- Defines how many columns to show. --> <attr name="numColumns" format="integer" min="0"> + <!-- Display as many columns as possible to fill the available space. --> <enum name="auto_fit" value="-1" /> </attr> + <!-- Specifies the gravity within each cell. --> <attr name="gravity" /> </declare-styleable> <declare-styleable name="ImageSwitcher"> diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java index 96b028a02360..672f252388fd 100644 --- a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java +++ b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java @@ -250,8 +250,8 @@ public class BluetoothStressTest extends InstrumentationTestCase { for (int i = 0; i < iterations; i++) { mTestUtils.writeOutput("connectInput iteration " + (i + 1) + " of " + iterations); - mTestUtils.connectInput(adapter, device); - mTestUtils.disconnectInput(adapter, device); + mTestUtils.connectProfile(adapter, device, BluetoothProfile.INPUT_DEVICE); + mTestUtils.disconnectProfile(adapter, device, BluetoothProfile.INPUT_DEVICE); } mTestUtils.unpair(adapter, device); diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java index effed7676487..35210e5c7b3d 100644 --- a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java +++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java @@ -238,6 +238,9 @@ public class BluetoothTestUtils extends Assert { case BluetoothProfile.HEADSET: mConnectionAction = BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED; break; + case BluetoothProfile.INPUT_DEVICE: + mConnectionAction = BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED; + break; default: mConnectionAction = null; } @@ -270,47 +273,6 @@ public class BluetoothTestUtils extends Assert { } } - private class ConnectInputReceiver extends FlagReceiver { - private static final int STATE_DISCONNECTED_FLAG = 1; - private static final int STATE_CONNECTING_FLAG = 1 << 1; - private static final int STATE_CONNECTED_FLAG = 1 << 2; - private static final int STATE_DISCONNECTING_FLAG = 1 << 3; - - private BluetoothDevice mDevice; - - public ConnectInputReceiver(BluetoothDevice device, int expectedFlags) { - super(expectedFlags); - - mDevice = device; - } - - @Override - public void onReceive(Context context, Intent intent) { - if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))) { - return; - } - - if (BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED.equals(intent.getAction())) { - int state = intent.getIntExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, -1); - assertNotSame(-1, state); - switch (state) { - case BluetoothInputDevice.STATE_DISCONNECTED: - setFiredFlag(STATE_DISCONNECTED_FLAG); - break; - case BluetoothInputDevice.STATE_CONNECTING: - setFiredFlag(STATE_CONNECTING_FLAG); - break; - case BluetoothInputDevice.STATE_CONNECTED: - setFiredFlag(STATE_CONNECTED_FLAG); - break; - case BluetoothInputDevice.STATE_DISCONNECTING: - setFiredFlag(STATE_DISCONNECTING_FLAG); - break; - } - } - } - } - private class ConnectPanReceiver extends FlagReceiver { private static final int STATE_DISCONNECTED_FLAG = 1; private static final int STATE_CONNECTING_FLAG = 1 << 1; @@ -366,6 +328,9 @@ public class BluetoothTestUtils extends Assert { case BluetoothProfile.HEADSET: mHeadset = (BluetoothHeadset) proxy; break; + case BluetoothProfile.INPUT_DEVICE: + mInput = (BluetoothInputDevice) proxy; + break; } } } @@ -379,6 +344,9 @@ public class BluetoothTestUtils extends Assert { case BluetoothProfile.HEADSET: mHeadset = null; break; + case BluetoothProfile.INPUT_DEVICE: + mInput = null; + break; } } } @@ -393,6 +361,7 @@ public class BluetoothTestUtils extends Assert { private Context mContext; private BluetoothA2dp mA2dp; private BluetoothHeadset mHeadset; + private BluetoothInputDevice mInput; /** * Creates a utility instance for testing Bluetooth. @@ -1078,142 +1047,6 @@ public class BluetoothTestUtils extends Assert { } /** - * Connects the local device with a remote HID device and checks to make sure that the profile - * is connected and that the correct actions were broadcast. - * - * @param adapter The BT adapter. - * @param device The remote device. - */ - public void connectInput(BluetoothAdapter adapter, BluetoothDevice device) { - int mask = (ConnectInputReceiver.STATE_CONNECTING_FLAG - | ConnectInputReceiver.STATE_CONNECTED_FLAG); - long start = -1; - - if (!adapter.isEnabled()) { - fail(String.format("connectInput() bluetooth not enabled: device=%s", device)); - } - - if (!adapter.getBondedDevices().contains(device)) { - fail(String.format("connectInput() device not paired: device=%s", device)); - } - - BluetoothInputDevice inputDevice = new BluetoothInputDevice(mContext); - assertNotNull(inputDevice); - ConnectInputReceiver receiver = getConnectInputReceiver(device, mask); - - int state = inputDevice.getInputDeviceState(device); - switch (state) { - case BluetoothInputDevice.STATE_CONNECTED: - removeReceiver(receiver); - return; - case BluetoothInputDevice.STATE_CONNECTING: - mask = 0; // Don't check for received intents since we might have missed them. - break; - case BluetoothInputDevice.STATE_DISCONNECTED: - case BluetoothInputDevice.STATE_DISCONNECTING: - start = System.currentTimeMillis(); - assertTrue(inputDevice.connectInputDevice(device)); - break; - default: - removeReceiver(receiver); - fail(String.format("connectInput() invalid state: device=%s, state=%d", device, - state)); - } - - long s = System.currentTimeMillis(); - while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) { - state = inputDevice.getInputDeviceState(device); - if (state == BluetoothInputDevice.STATE_CONNECTED - && (receiver.getFiredFlags() & mask) == mask) { - long finish = receiver.getCompletedTime(); - if (start != -1 && finish != -1) { - writeOutput(String.format("connectInput() completed in %d ms: device=%s", - (finish - start), device)); - } else { - writeOutput(String.format("connectInput() completed: device=%s", device)); - } - removeReceiver(receiver); - return; - } - sleep(POLL_TIME); - } - - int firedFlags = receiver.getFiredFlags(); - removeReceiver(receiver); - fail(String.format("connectInput() timeout: device=%s, state=%d (expected %d), " - + "flags=0x%x (expected 0x%s)", device, state, BluetoothInputDevice.STATE_CONNECTED, - firedFlags, mask)); - } - - /** - * Disconnects the local device with a remote HID device and checks to make sure that the - * profile is connected and that the correct actions were broadcast. - * - * @param adapter The BT adapter. - * @param device The remote device. - */ - public void disconnectInput(BluetoothAdapter adapter, BluetoothDevice device) { - int mask = (ConnectInputReceiver.STATE_DISCONNECTING_FLAG - | ConnectInputReceiver.STATE_DISCONNECTED_FLAG); - long start = -1; - - if (!adapter.isEnabled()) { - fail(String.format("disconnectInput() bluetooth not enabled: device=%s", device)); - } - - if (!adapter.getBondedDevices().contains(device)) { - fail(String.format("disconnectInput() device not paired: device=%s", device)); - } - - BluetoothInputDevice inputDevice = new BluetoothInputDevice(mContext); - assertNotNull(inputDevice); - ConnectInputReceiver receiver = getConnectInputReceiver(device, mask); - - int state = inputDevice.getInputDeviceState(device); - switch (state) { - case BluetoothInputDevice.STATE_CONNECTED: - case BluetoothInputDevice.STATE_CONNECTING: - start = System.currentTimeMillis(); - assertTrue(inputDevice.disconnectInputDevice(device)); - break; - case BluetoothInputDevice.STATE_DISCONNECTED: - removeReceiver(receiver); - return; - case BluetoothInputDevice.STATE_DISCONNECTING: - mask = 0; // Don't check for received intents since we might have missed them. - break; - default: - removeReceiver(receiver); - fail(String.format("disconnectInput() invalid state: device=%s, state=%d", device, - state)); - } - - long s = System.currentTimeMillis(); - while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) { - state = inputDevice.getInputDeviceState(device); - if (state == BluetoothInputDevice.STATE_DISCONNECTED - && (receiver.getFiredFlags() & mask) == mask) { - long finish = receiver.getCompletedTime(); - if (start != -1 && finish != -1) { - writeOutput(String.format("disconnectInput() completed in %d ms: device=%s", - (finish - start), device)); - } else { - writeOutput(String.format("disconnectInput() completed: device=%s", device)); - } - removeReceiver(receiver); - return; - } - sleep(POLL_TIME); - } - - int firedFlags = receiver.getFiredFlags(); - removeReceiver(receiver); - fail(String.format("disconnectInput() timeout: device=%s, state=%d (expected %d), " - + "flags=0x%x (expected 0x%s)", device, state, - BluetoothInputDevice.STATE_DISCONNECTED, firedFlags, mask)); - } - - /** * Connects the PANU to a remote NAP and checks to make sure that the PANU is connected and that * the correct actions were broadcast. * @@ -1478,21 +1311,14 @@ public class BluetoothTestUtils extends Assert { int expectedFlags) { String[] actions = { BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED, - BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED}; + BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED, + BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED}; ConnectProfileReceiver receiver = new ConnectProfileReceiver(device, profile, expectedFlags); addReceiver(receiver, actions); return receiver; } - private ConnectInputReceiver getConnectInputReceiver(BluetoothDevice device, - int expectedFlags) { - String[] actions = {BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED}; - ConnectInputReceiver receiver = new ConnectInputReceiver(device, expectedFlags); - addReceiver(receiver, actions); - return receiver; - } - private ConnectPanReceiver getConnectPanReceiver(BluetoothDevice device, int role, int expectedFlags) { String[] actions = {BluetoothPan.ACTION_PAN_STATE_CHANGED}; @@ -1511,15 +1337,20 @@ public class BluetoothTestUtils extends Assert { long s = System.currentTimeMillis(); switch (profile) { case BluetoothProfile.A2DP: - while (mA2dp != null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) { + while (mA2dp == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) { sleep(POLL_TIME); } return mA2dp; case BluetoothProfile.HEADSET: - while (mHeadset != null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) { + while (mHeadset == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) { sleep(POLL_TIME); } return mHeadset; + case BluetoothProfile.INPUT_DEVICE: + while (mInput == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) { + sleep(POLL_TIME); + } + return mInput; default: return null; } diff --git a/media/java/android/media/videoeditor/Transition.java b/media/java/android/media/videoeditor/Transition.java index 95f002c442f2..3e8fe9412830 100755 --- a/media/java/android/media/videoeditor/Transition.java +++ b/media/java/android/media/videoeditor/Transition.java @@ -173,6 +173,7 @@ public abstract class Transition { mDurationMs = durationMs; invalidate(); + mNativeHelper.setGeneratePreview(true); } /** diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index fd575fef3b28..0100a1755327 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -298,6 +298,17 @@ status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length) return INVALID_OPERATION; } + // It appears that if an invalid file descriptor is passed through + // binder calls, the server-side of the inter-process function call + // is skipped. As a result, the check at the server-side to catch + // the invalid file descritpor never gets invoked. This is to workaround + // this issue by checking the file descriptor first before passing + // it through binder call. + if (fd < 0) { + LOGE("Invalid file descriptor: %d", fd); + return BAD_VALUE; + } + status_t ret = mMediaRecorder->setOutputFile(fd, offset, length); if (OK != ret) { LOGV("setOutputFile failed: %d", ret); diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java index eaaa798166ec..988b229474b6 100755 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java @@ -17,7 +17,8 @@ package com.android.mediaframeworktest; import com.android.mediaframeworktest.performance.MediaPlayerPerformance; - +/*Video Editor performance Test cases*/ +import com.android.mediaframeworktest.performance.VideoEditorPerformance; import junit.framework.TestSuite; import android.test.InstrumentationTestRunner; @@ -26,7 +27,7 @@ import android.test.InstrumentationTestSuite; /** * Instrumentation Test Runner for all MediaPlayer tests. - * + * * Running all tests: * * adb shell am instrument \ @@ -40,6 +41,8 @@ public class MediaFrameworkPerfTestRunner extends InstrumentationTestRunner { public TestSuite getAllTests() { TestSuite suite = new InstrumentationTestSuite(this); suite.addTestSuite(MediaPlayerPerformance.class); + /*Video Editor performance Test cases*/ + suite.addTestSuite(VideoEditorPerformance.class); return suite; } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java index 543806135f26..0cd784cbce77 100755 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java @@ -19,6 +19,8 @@ package com.android.mediaframeworktest; import android.test.InstrumentationTestRunner; import android.test.InstrumentationTestSuite; import com.android.mediaframeworktest.stress.MediaPlayerStressTest; +/** Import for Video Editor Stress Test cases*/ +import com.android.mediaframeworktest.stress.VideoEditorStressTest; import junit.framework.TestSuite; @@ -28,6 +30,8 @@ public class MediaPlayerStressTestRunner extends InstrumentationTestRunner { public TestSuite getAllTests() { TestSuite suite = new InstrumentationTestSuite(this); suite.addTestSuite(MediaPlayerStressTest.class); + /** Video Editor Stress Test cases*/ + suite.addTestSuite(VideoEditorStressTest.class); return suite; } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorPreviewTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorPreviewTest.java index bd0a83845777..9a7f4f2ee5c2 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorPreviewTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorPreviewTest.java @@ -95,7 +95,7 @@ public class VideoEditorPreviewTest extends private boolean previewStop; /* Minimum waiting time for Semaphore to wait for release */ - private final long minWaitingTime = 1000; + private final long minWaitingTime = 3000; // Declares the annotation for Preview Test Cases public @interface Preview { @@ -473,8 +473,8 @@ public class VideoEditorPreviewTest extends mVideoEditorHelper.checkProgressCBValues(progressValues); final SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder(); - - long waitingTime = minWaitingTime + 10000; + /* As transition takes more time buffer of 10 sec is added */ + long waitingTime = minWaitingTime + 10000 + 10000; blockTillPreviewCompletes.acquire(); try { @@ -691,31 +691,34 @@ public class VideoEditorPreviewTest extends long waitingTime = minWaitingTime + mVideoEditor.getDuration(); + blockTillPreviewCompletes.acquire(); + final String fileName = mVideoEditor.getPath() + "\test.3gp"; + final int height = MediaProperties.HEIGHT_480; + final int bitrate = MediaProperties.BITRATE_512K; + + try { + mVideoEditor.export(fileName, height, bitrate, + new ExportProgressListener() { + public void onProgress(VideoEditor ve, + String outFileName,int progress) { + + } + }); + } catch (IOException e) { + assertTrue("UnExpected Error in Export" + + e.toString(), false); + } final SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder(); try { + mVideoEditor.startPreview(surfaceHolder, 5000, -1, false, 1, new PreviewProgressListener() { - final String fileName = mVideoEditor.getPath() + "\test.3gp"; - final int height = MediaProperties.HEIGHT_360; - final int bitrate = MediaProperties.BITRATE_512K; + public void onProgress(VideoEditor videoEditor, long timeMs, OverlayData overlayData) { - if (timeMs >= 10000) - try { - videoEditor.export(fileName, height, bitrate, - new ExportProgressListener() { - public void onProgress(VideoEditor ve, - String outFileName,int progress) { - - } - }); - } catch (IOException e) { - assertTrue("UnExpected Error in Export" + - e.toString(), false); - } } public void onStart(VideoEditor videoEditor) { setPreviewStart(); @@ -725,10 +728,10 @@ public class VideoEditorPreviewTest extends blockTillPreviewCompletes.release(); } }); + } catch (Exception e) { blockTillPreviewCompletes.release(); } - blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS); mVideoEditor.stopPreview(); assertTrue("Preview Failed to start", previewStart); @@ -837,31 +840,7 @@ public class VideoEditorPreviewTest extends mVideoEditor.renderPreviewFrame(surfaceHolder, 7000, overlayData1)); - long waitingTime = minWaitingTime + (mVideoEditor.getDuration() - 5000); - - blockTillPreviewCompletes.acquire(); - try { - mVideoEditor.startPreview(surfaceHolder, 5000, -1, false, 1, - new PreviewProgressListener() { - public void onProgress(VideoEditor videoEditor, long timeMs, - OverlayData overlayData) { - } - public void onStart(VideoEditor videoEditor) { - setPreviewStart(); - } - public void onStop(VideoEditor videoEditor) { - setPreviewStop(); - blockTillPreviewCompletes.release(); - } - }); - } catch (Exception e) { - blockTillPreviewCompletes.release(); - } - blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS); - mVideoEditor.stopPreview(); - assertTrue("Preview Failed to start", previewStart); - assertTrue("Preview Failed to stop", previewStop); - blockTillPreviewCompletes.release(); + validatePreviewProgress(5000, -1, false, mVideoEditor.getDuration()); } /** @@ -1142,20 +1121,19 @@ public class VideoEditorPreviewTest extends duration = mVideoEditor.getDuration(); /* RenderPreviewFrame returns -1 to indicate last frame */ try { - assertEquals("Render preview Frame at item duration", -1, mVideoEditor.renderPreviewFrame(surfaceHolder, duration, - overlayData1)); - } catch ( Exception e) { - assertTrue (" Render Preview Frame without generate", false); + overlayData1); + } catch ( IllegalStateException e) { + flagForException = true; } + assertTrue (" Render Preview Frame without generate", flagForException); duration = mVideoEditor.getDuration() + 1000; try { mVideoEditor.renderPreviewFrame(surfaceHolder, duration, overlayData1); - } catch ( IllegalStateException e) { + } catch ( IllegalArgumentException e) { flagForException = true; } assertTrue (" Preview time greater than duration", flagForException); } - } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java new file mode 100644 index 000000000000..4481d0004156 --- /dev/null +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java @@ -0,0 +1,1086 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.mediaframeworktest.performance; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.Writer; + +import android.graphics.Bitmap; +import android.graphics.Rect; +import android.media.videoeditor.AudioTrack; +import android.media.videoeditor.EffectColor; +import android.media.videoeditor.EffectKenBurns; +import android.media.videoeditor.MediaImageItem; +import android.media.videoeditor.MediaItem; +import android.media.videoeditor.MediaProperties; +import android.media.videoeditor.MediaVideoItem; +import android.media.videoeditor.OverlayFrame; +import android.media.videoeditor.Transition; +import android.media.videoeditor.TransitionCrossfade; +import android.media.videoeditor.TransitionAlpha; +import android.media.videoeditor.TransitionFadeBlack; +import android.media.videoeditor.TransitionSliding; +import android.media.videoeditor.VideoEditor; +import android.os.Environment; +import android.test.ActivityInstrumentationTestCase; +import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener; +import android.os.Environment; +import android.os.SystemClock; +import android.test.ActivityInstrumentationTestCase; +import android.media.videoeditor.VideoEditor.ExportProgressListener; + +import android.util.Log; + +import com.android.mediaframeworktest.MediaFrameworkTest; +import android.test.suitebuilder.annotation.LargeTest; +import com.android.mediaframeworktest.VideoEditorHelper; + +/** + * Junit / Instrumentation - performance measurement for media player and + * recorder + */ +public class VideoEditorPerformance extends + ActivityInstrumentationTestCase<MediaFrameworkTest> { + + private final String TAG = "VideoEditorPerformance"; + + private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON; + + private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON; + + private final String VIDEOEDITOR_OUTPUT = PROJECT_LOCATION + + "VideoEditorPerformance.txt"; + + public VideoEditorPerformance() { + super("com.android.mediaframeworktest", MediaFrameworkTest.class); + } + + private final String PROJECT_CLASS_NAME = + "android.media.videoeditor.VideoEditorImpl"; + private VideoEditor mVideoEditor; + private VideoEditorHelper mVideoEditorHelper; + + @Override + protected void setUp() throws Exception { + // setup for each test case. + super.setUp(); + mVideoEditorHelper = new VideoEditorHelper(); + // Create a random String which will be used as project path, where all + // project related files will be stored. + final String projectPath = + mVideoEditorHelper.createRandomFile(PROJECT_LOCATION); + mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath); + } + + @Override + protected void tearDown() throws Exception { + mVideoEditorHelper.destroyVideoEditor(mVideoEditor); + // Clean the directory created as project path + mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath())); + System.gc(); + super.tearDown(); + } + + private void writeTimingInfo(String testCaseName, String[] information) + throws Exception { + File outFile = new File(VIDEOEDITOR_OUTPUT); + Writer output = new BufferedWriter(new FileWriter(outFile, true)); + output.write(testCaseName + "\n\t"); + for (int i = 0; i < information.length; i++) { + output.write(information[i]); + } + output.write("\n\n"); + output.close(); + } + + private final int NUM_OF_ITERATIONS=20; + + private float calculateTimeTaken(long beginTime, int numIterations) + throws Exception { + final long duration2 = SystemClock.uptimeMillis(); + final long durationToCreateMediaItem = (duration2 - beginTime); + final float timeTaken1 = (float)durationToCreateMediaItem * + 1.0f/(float)numIterations; + return (timeTaken1); + } + + private void createVideoItems(MediaVideoItem[] mediaVideoItem, + String videoItemFileName, int renderingMode, int startTime, int endTime) throws Exception { + for (int i = 0; i < NUM_OF_ITERATIONS; i++) { + try { + mediaVideoItem[i] = new MediaVideoItem(mVideoEditor, "m" + i, + videoItemFileName, renderingMode); + mediaVideoItem[i].setExtractBoundaries(startTime, endTime); + } catch (Exception e1) { + assertTrue( + "Can not create an object of Video Item with file name = " + + videoItemFileName + "------ID:m" + i + " Issue = " + + e1.toString(), false); + } + } + } + + private void addVideoItems(MediaVideoItem[] mediaVideoItem) throws Exception { + for (int i = 0; i < NUM_OF_ITERATIONS; i++) { + try { + mVideoEditor.addMediaItem(mediaVideoItem[i]); + } catch (Exception e1) { + assertTrue( + "Can not add an object of Video Item with ID:m" + i + + " Issue = " + e1.toString(), false); + } + } + } + + private void removeVideoItems(MediaVideoItem[] mediaVideoItem) throws Exception { + for (int i = 0; i < NUM_OF_ITERATIONS; i++) { + try { + mVideoEditor.removeMediaItem(mediaVideoItem[i].getId()); + } catch (Exception e1) { + assertTrue( + "Can not Remove an object of Video Item with ID:m" + i + + " Issue = " + e1.toString(), false); + } + } + } + + private void createImageItems(MediaImageItem[] mIi, + String imageItemFileName, int renderingMode, int duration) throws Exception { + for (int i = 0; i < NUM_OF_ITERATIONS; i++) { + try { + mIi[i] = new MediaImageItem(mVideoEditor, "m" + i, + imageItemFileName, duration, renderingMode); + } catch (Exception e1) { + assertTrue( " Cannot create Image Item", false); + } + } + } + + private void addImageItems(MediaImageItem[] mIi) throws Exception { + for (int i = 0; i < NUM_OF_ITERATIONS; i++) { + try { + mVideoEditor.addMediaItem(mIi[i]); + } catch (Exception e1) { + assertTrue("Cannot add Image item", false); + } + } + } + + private void removeImageItems(MediaImageItem[] mIi) throws Exception { + for (int i = 0; i < NUM_OF_ITERATIONS; i++) { + try { + mVideoEditor.removeMediaItem(mIi[i].getId()); + } catch (Exception e1) { + assertTrue("Cannot remove image item", false); + } + } + } + /** + * To test the performance of adding and removing the video media item + * + * @throws Exception + */ + // TODO : remove PRF_001 + @LargeTest + public void testPerformanceAddRemoveVideoItem() throws Exception { + final String videoItemFileName = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_800kbps_1_17.mp4"; + final int videoItemStartTime = 0; + final int videoItemEndTime = 5000; + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String[] loggingInfo = new String[3]; + final MediaVideoItem[] mediaVideoItem = + new MediaVideoItem[NUM_OF_ITERATIONS]; + float timeTaken = 0.0f; + long startTime = 0; + + /** Time Take for creation of Media Video Item */ + startTime = SystemClock.uptimeMillis(); + createVideoItems(mediaVideoItem, videoItemFileName, renderingMode, + videoItemStartTime, videoItemEndTime); + + timeTaken = calculateTimeTaken (startTime, NUM_OF_ITERATIONS); + loggingInfo[0] = "Time taken to Create Media Video Item\t" + + timeTaken; + + /** Time Take for Addition of Media Video Item */ + startTime = SystemClock.uptimeMillis(); + addVideoItems(mediaVideoItem); + timeTaken = calculateTimeTaken (startTime, NUM_OF_ITERATIONS); + loggingInfo[1] = "\n\tTime taken to Add Media Video Item\t" + + timeTaken; + + /** Time Take for Removal of Media Video Item */ + startTime = SystemClock.uptimeMillis(); + removeVideoItems(mediaVideoItem); + timeTaken = calculateTimeTaken (startTime, NUM_OF_ITERATIONS); + loggingInfo[2] = "\n\tTime taken to remove Media Video Item\t" + + timeTaken; + + writeTimingInfo("testPerformanceAddRemoveVideoItem (in mSec)", loggingInfo); + } + + /** + * To test the performance of adding and removing the image media item + * + * @throws Exception + */ + // TODO : remove PRF_002 + @LargeTest + public void testPerformanceAddRemoveImageItem() throws Exception { + final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg"; + final int imageItemDuration = 0; + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String[] loggingInfo = new String[3]; + final MediaImageItem[] mediaImageItem = + new MediaImageItem[NUM_OF_ITERATIONS]; + float timeTaken = 0.0f; + + long beginTime = SystemClock.uptimeMillis(); + createImageItems(mediaImageItem, imageItemFileName, renderingMode, + imageItemDuration); + timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS); + loggingInfo[0] = "Time taken to Create Media Image Item\t" + + timeTaken; + + beginTime = SystemClock.uptimeMillis(); + addImageItems(mediaImageItem); + timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS); + loggingInfo[1] = "\n\tTime taken to add Media Image Item\t" + + timeTaken; + + beginTime = SystemClock.uptimeMillis(); + removeImageItems(mediaImageItem); + timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS); + loggingInfo[2] = "\n\tTime taken to remove Media Image Item\t" + + timeTaken; + + writeTimingInfo("testPerformanceAddRemoveImageItem (in mSec)", + loggingInfo); + } + + /** + * To test the performance of adding and removing the transition + * + * @throws Exception + */ + // TODO : remove PRF_003 + @LargeTest + public void testPerformanceAddRemoveTransition() throws Exception { + final String videoItemFileName1 = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_800kbps_1_17.mp4"; + final int videoItemStartTime1 = 0; + final int videoItemEndTime1 = 20000; + final String videoItemFileName2 = INPUT_FILE_PATH + + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4"; + final int videoItemStartTime2 = 0; + final int videoItemEndTime2 = 20000; + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final int transitionDuration = 5000; + final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST; + final String[] loggingInfo = new String[3]; + float timeTaken = 0.0f; + + final MediaVideoItem[] mediaVideoItem = + new MediaVideoItem[(NUM_OF_ITERATIONS *10) + 1]; + + for (int i = 0; i < (NUM_OF_ITERATIONS *10); i+=2) { + try { + mediaVideoItem[i] = new MediaVideoItem(mVideoEditor, "m" + i, + videoItemFileName1, renderingMode); + mediaVideoItem[i+1] = new MediaVideoItem(mVideoEditor, + "m" + (i+1), videoItemFileName2, renderingMode); + mediaVideoItem[i].setExtractBoundaries(videoItemStartTime1, + videoItemEndTime1); + mediaVideoItem[i+1].setExtractBoundaries(videoItemStartTime2, + videoItemEndTime2); + } catch (Exception e1) { + assertTrue("Can not create Video Object Item with file name = " + + e1.toString(), false); + } + mVideoEditor.addMediaItem(mediaVideoItem[i]); + mVideoEditor.addMediaItem(mediaVideoItem[i+1]); + } + mediaVideoItem[(NUM_OF_ITERATIONS *10)] = new MediaVideoItem(mVideoEditor, + "m" + (NUM_OF_ITERATIONS *10), videoItemFileName1, renderingMode); + mediaVideoItem[(NUM_OF_ITERATIONS *10)].setExtractBoundaries( + videoItemStartTime1, videoItemEndTime1); + mVideoEditor.addMediaItem(mediaVideoItem[(NUM_OF_ITERATIONS *10)]); + final TransitionCrossfade tranCrossfade[] = + new TransitionCrossfade[(NUM_OF_ITERATIONS *10)]; + + long beginTime = SystemClock.uptimeMillis(); + for (int i = 0; i < (NUM_OF_ITERATIONS *10); i++) { + tranCrossfade[i] = new TransitionCrossfade("transition" + i, + mediaVideoItem[i], mediaVideoItem[i+1], transitionDuration, + transitionBehavior); + } + timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS * 10)); + loggingInfo[0] = "Time taken to Create CrossFade Transition\t" + + timeTaken; + + beginTime = SystemClock.uptimeMillis(); + for (int i = 0; i < (NUM_OF_ITERATIONS *10); i++) { + mVideoEditor.addTransition(tranCrossfade[i]); + } + timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS * 10)); + loggingInfo[1] = "\n\tTime taken to add CrossFade Transition\t" + + timeTaken; + + beginTime = SystemClock.uptimeMillis(); + for (int i = 0; i < (NUM_OF_ITERATIONS *10); i++) { + assertEquals("Removing Transitions", tranCrossfade[i], mVideoEditor + .removeTransition(tranCrossfade[i].getId())); + } + timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS * 10)); + loggingInfo[2] = "\n\tTime taken to remove CrossFade Transition\t" + + timeTaken; + + writeTimingInfo("testPerformanceAddRemoveTransition (in mSec)", loggingInfo); + } + + /** + * To test performance of Export + * + * @throws Exception + */ + // TODO : remove PRF_004 + @LargeTest + public void testPerformanceExport() throws Exception { + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final int outHeight = MediaProperties.HEIGHT_480; + final int outBitrate = MediaProperties.BITRATE_256K; + final int outVcodec = MediaProperties.VCODEC_H264BP; + final String[] loggingInfo = new String[1]; + final String outFilename = mVideoEditorHelper + .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp"; + final String videoItemFileName1 = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_12Mbps_AACLC_44.1khz_64kbps_s_1_17.mp4"; + final String imageItemFileName1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg"; + final String videoItemFileName2 = INPUT_FILE_PATH + + "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_32kbps_m_1_17.3gp"; + final String imageItemFileName2 = INPUT_FILE_PATH + "IMG_176x144.jpg"; + final String videoItemFileName3 = INPUT_FILE_PATH + + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_161kbps_s_0_26.mp4"; + final String overlayFile = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png"; + final String audioTrackFilename = INPUT_FILE_PATH + + "AMRNB_8KHz_12.2Kbps_m_1_17.3gp"; + final String maskFilename = INPUT_FILE_PATH + + "TransitionSpiral_QVGA.jpg"; + + final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor, + "m1", videoItemFileName1, renderingMode); + mediaItem1.setExtractBoundaries(0, 20000); + mVideoEditor.addMediaItem(mediaItem1); + + final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor, + "m2", imageItemFileName1, 10000, renderingMode); + mVideoEditor.addMediaItem(mediaItem2); + + final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor, + "m3", videoItemFileName2, renderingMode); + mediaItem3.setExtractBoundaries(0, 20000); + mVideoEditor.addMediaItem(mediaItem3); + + final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor, + "m4", imageItemFileName2, 10000, renderingMode); + mVideoEditor.addMediaItem(mediaItem4); + + final MediaVideoItem mediaItem5 = new MediaVideoItem(mVideoEditor, + "m5", videoItemFileName3, renderingMode); + mediaItem5.setExtractBoundaries(0, 20000); + mVideoEditor.addMediaItem(mediaItem5); + /** + * 7.Add TransitionAlpha, Apply this Transition as Begin for Media Item 1 + * with duration = 2 sec behavior = BEHAVIOR_LINEAR, mask file name = + * TransitionSpiral_QVGA.jpg , blending percent = 50%, invert = true; + * */ + final TransitionAlpha transition1 = + mVideoEditorHelper.createTAlpha("transition1", null, mediaItem1, + 2000, Transition.BEHAVIOR_LINEAR, maskFilename, 50, true); + mVideoEditor.addTransition(transition1); + + /** + * 8.Add Transition Sliding between MediaItem 2 and 3 , + * Sliding Direction = DIRECTION_RIGHT_OUT_LEFT_IN, + * behavior = BEHAVIOR_MIDDLE_FAST and duration = 4sec + * */ + final TransitionSliding transition2And3 = + mVideoEditorHelper.createTSliding("transition2", mediaItem2, + mediaItem3, 4000, Transition.BEHAVIOR_MIDDLE_FAST, + TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN); + mVideoEditor.addTransition(transition2And3); + + /** + * 9.Add Transition Crossfade between Media Item 3 and 4, + * behavior = BEHAVIOR_MIDDLE_SLOW, duration = 3.5 sec + * */ + final TransitionCrossfade transition3And4 = + mVideoEditorHelper.createTCrossFade("transition3", mediaItem3, + mediaItem4, 3500, Transition.BEHAVIOR_MIDDLE_SLOW); + mVideoEditor.addTransition(transition3And4); + + /** + * 10.Add Transition Fadeblack between Media Item 4 and 5, + * behavior = BEHAVIOR_SPEED_DOWN, duration = 3.5 sec + * */ + final TransitionFadeBlack transition4And5 = + mVideoEditorHelper.createTFadeBlack("transition4", mediaItem4, + mediaItem5, 3500, Transition.BEHAVIOR_SPEED_DOWN); + mVideoEditor.addTransition(transition4And5); + + /** + * 11.Add Effect 1 type="TYPE_SEPIA" to the MediaItem 1, + * start time=1sec and duration =4secs + * */ + final EffectColor effectColor1 = mVideoEditorHelper.createEffectItem( + mediaItem1, "effect1", 1000, 4000, EffectColor.TYPE_SEPIA, 0); + mediaItem1.addEffect(effectColor1); + + /** + * 12.Add Overlay 1 to the MediaItem 3: Frame Overlay with start time = 1 sec + * duration = 4 sec with item = IMG_640x480_Overlay1.png + * */ + final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFile, 640, + 480); + final OverlayFrame overlayFrame = + mVideoEditorHelper.createOverlay(mediaItem3, "overlay", + mBitmap, 1000, 4000); + mediaItem3.addOverlay(overlayFrame); + /** + * 13.Add Effect 2 type="TYPE_NEGATIVE" to the MediaItem 2, + * start time=8sec and duration =2secs + * */ + final EffectColor effectColor2 = mVideoEditorHelper.createEffectItem( + mediaItem2, "effect2", 8000, 2000, EffectColor.TYPE_NEGATIVE, 0); + mediaItem2.addEffect(effectColor2); + /** + * 14.Add Effect 3 type="TYPE_COLOR" to the MediaItem 3, color param = "PINK", + * start time=5 sec and duration =3secs + * */ + final EffectColor effectColor3 = mVideoEditorHelper.createEffectItem( + mediaItem3, "effect3", 5000, 3000, EffectColor.TYPE_COLOR, + EffectColor.PINK); + mediaItem3.addEffect(effectColor3); + /** + * 15.Add Effect 4 type="TYPE_FIFTIES" to the MediaItem 4, + * start time=2 sec and duration =1secs + * */ + final EffectColor effectColor4 = mVideoEditorHelper.createEffectItem( + mediaItem4, "effect4", 2000, 1000, EffectColor.TYPE_FIFTIES, 0); + mediaItem4.addEffect(effectColor4); + /** + * 16.Add KenBurnsEffect for MediaItem 4 with + * duration = 3 sec and startTime = 4 sec + * StartRect + * left = org_height/3 ; top = org_width/3 + * bottom = org_width/2 ; right = org_height/2 + * EndRect + * left = 0 ; top = 0 + * bottom = org_height; right = org_width + * */ + + final Rect startRect = new Rect((mediaItem4.getHeight() / 3), + (mediaItem4.getWidth() / 3), (mediaItem4.getHeight() / 2), + (mediaItem4.getWidth() / 2)); + final Rect endRect = new Rect(0, 0, mediaItem4.getWidth(), + mediaItem4.getHeight()); + final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns( + mediaItem4, "KBOnM2", startRect, endRect,4000 , 3000); + mediaItem4.addEffect(kbEffectOnMediaItem); + + /** 17.Add Audio Track,Set extract boundaries o to 10 sec. + * */ + final AudioTrack audioTrack = mVideoEditorHelper.createAudio( + mVideoEditor, "audioTrack", audioTrackFilename); + mVideoEditor.addAudioTrack(audioTrack); + /** 18.Enable Looping for Audio Track. + * */ + audioTrack.enableLoop(); + float timeTaken = 0.0f; + final long beginTime = SystemClock.uptimeMillis(); + try { + mVideoEditor.export(outFilename, outHeight, outBitrate, + new ExportProgressListener() { + public void onProgress(VideoEditor ve, + String outFileName, int progress) { + } + }); + } catch (Exception e) { + assertTrue("Error in Export" + e.toString(), false); + } + mVideoEditorHelper.checkDeleteExistingFile(outFilename); + + timeTaken = calculateTimeTaken(beginTime, 1); + loggingInfo[0] = "Time taken to do ONE export of storyboard duration\t" + + mVideoEditor.getDuration() + " is :\t" + timeTaken; + + writeTimingInfo("testPerformanceExport (in mSec)", loggingInfo); + mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath())); + } + + + /** + * To test the performance of thumbnail extraction + * + * @throws Exception + */ + // TODO : remove PRF_005 + @LargeTest + public void testPerformanceThumbnailVideoItem() throws Exception { + final String videoItemFileName = INPUT_FILE_PATH + + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4"; + final int videoItemStartTime = 0; + final int videoItemEndTime = 20000; + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String[] loggingInfo = new String[1]; + + final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor, + "m1", videoItemFileName, renderingMode); + mediaVideoItem.setExtractBoundaries(videoItemStartTime, + videoItemEndTime); + + float timeTaken = 0.0f; + long beginTime = SystemClock.uptimeMillis(); + for (int i = 0; i < NUM_OF_ITERATIONS; i++) { + mediaVideoItem.getThumbnail(mediaVideoItem.getWidth() / 2, + mediaVideoItem.getHeight() / 2, i); + } + timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS); + loggingInfo[0] = "Duration taken to get Video Thumbnails\t" + + timeTaken; + + writeTimingInfo("testPerformanceThumbnailVideoItem (in mSec)", loggingInfo); + } + + /** + * To test the performance of adding and removing the overlay to media item + * + * @throws Exception + */ + // TODO : remove PRF_006 + @LargeTest + public void testPerformanceOverlayVideoItem() throws Exception { + final String videoItemFileName1 = INPUT_FILE_PATH + + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4"; + final int videoItemStartTime1 = 0; + final int videoItemEndTime1 = 10000; + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String overlayFilename = INPUT_FILE_PATH + + "IMG_640x480_Overlay1.png"; + final int overlayStartTime = 1000; + final int overlayDuration = 5000; + + final String[] loggingInfo = new String[2]; + MediaVideoItem mediaVideoItem = null; + + try { + mediaVideoItem = new MediaVideoItem(mVideoEditor, "m0", + videoItemFileName1, renderingMode); + mediaVideoItem.setExtractBoundaries(videoItemStartTime1, + videoItemEndTime1); + } catch (Exception e1) { + assertTrue("Can not create Video Item with file name = " + + e1.toString(), false); + } + final OverlayFrame overlayFrame[] = new OverlayFrame[NUM_OF_ITERATIONS]; + final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFilename, + 640, 480); + float timeTaken = 0.0f; + long beginTime = SystemClock.uptimeMillis(); + for (int i = 0; i < NUM_OF_ITERATIONS; i++) { + overlayFrame[i] = new OverlayFrame(mediaVideoItem, "overlay" + i, + mBitmap, overlayStartTime, overlayDuration); + mediaVideoItem.addOverlay(overlayFrame[i]); + } + timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS); + loggingInfo[0] = "Time taken to add & create Overlay\t" + timeTaken; + + beginTime = SystemClock.uptimeMillis(); + for (int i = 0; i < NUM_OF_ITERATIONS; i++) { + assertEquals("Removing Overlays", overlayFrame[i], + mediaVideoItem.removeOverlay((overlayFrame[i].getId()))); + } + timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS); + loggingInfo[1] = "\n\tTime taken to remove Overlay\t" + + timeTaken; + + writeTimingInfo("testPerformanceOverlayVideoItem (in mSec)", loggingInfo); + } + + /** + * To test the performance of get properties of a Video media item + * + * @throws Exception + */ + // TODO : remove PRF_007 + @LargeTest + public void testPerformanceVideoItemProperties() throws Exception { + final String videoItemFileName1 = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_800kbps_1_17.mp4"; + final int videoItemStartTime1 = 0; + final int videoItemEndTime1 = 10100; + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2; + final int fileType = MediaProperties.FILE_MP4; + final int videoCodecType = MediaProperties.VCODEC_H264BP; + final int duration = 77366; + final int videoBitrate = 3169971; + final int fps = 30; + final int videoProfile = MediaProperties.H264_PROFILE_0_LEVEL_1_3; + final int width = 1080; + final int height = MediaProperties.HEIGHT_720; + float timeTaken = 0.0f; + final String[] loggingInfo = new String[1]; + final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor, + "m0", videoItemFileName1, renderingMode); + mediaVideoItem.setExtractBoundaries(videoItemStartTime1, + videoItemEndTime1); + long beginTime = SystemClock.uptimeMillis(); + for (int i = 0; i < (NUM_OF_ITERATIONS*10); i++) { + try { + assertEquals("Aspect Ratio Mismatch", + aspectRatio, mediaVideoItem.getAspectRatio()); + assertEquals("File Type Mismatch", + fileType, mediaVideoItem.getFileType()); + assertEquals("VideoCodec Mismatch", + videoCodecType, mediaVideoItem.getVideoType()); + assertEquals("duration Mismatch", + duration, mediaVideoItem.getDuration()); + assertEquals("Video Profile ", + videoProfile, mediaVideoItem.getVideoProfile()); + assertEquals("Video height ", + height, mediaVideoItem.getHeight()); + assertEquals("Video width ", + width, mediaVideoItem.getWidth()); + } catch (Exception e1) { + assertTrue("Can not create Video Item with file name = " + + e1.toString(), false); + } + } + timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS*10)); + loggingInfo[0] = "Time taken to get Media Properties\t" + + timeTaken; + writeTimingInfo("testPerformanceVideoItemProperties:", loggingInfo); + } + + /** + * To test the performance of generatePreview : with Transitions + * + * @throws Exception + */ + // TODO : remove PRF_008 + @LargeTest + public void testPerformanceGeneratePreviewWithTransitions() + throws Exception { + final String videoItemFileName = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_800kbps_1_17.mp4"; + final String imageItemFileName = INPUT_FILE_PATH + + "IMG_1600x1200.jpg"; + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST; + long averageTime = 0; + final String[] loggingInfo = new String[1]; + + final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor, + "mediaItem1", videoItemFileName, renderingMode); + mediaVideoItem.setExtractBoundaries(0, 10000); + mVideoEditor.addMediaItem(mediaVideoItem); + + final MediaImageItem mediaImageItem = new MediaImageItem(mVideoEditor, + "mediaItem2", imageItemFileName, 10000, renderingMode); + mVideoEditor.addMediaItem(mediaImageItem); + + final TransitionCrossfade transitionCrossFade = new TransitionCrossfade( + "transitionCrossFade", mediaVideoItem, mediaImageItem, + 5000, transitionBehavior); + mVideoEditor.addTransition(transitionCrossFade); + + for (int i = 0; i < NUM_OF_ITERATIONS; i++) { + final long duration1 = SystemClock.uptimeMillis(); + mVideoEditor.generatePreview(new MediaProcessingProgressListener() { + public void onProgress(Object item, int action, int progress) { + } + }); + final long duration2 = SystemClock.uptimeMillis(); + mVideoEditor.removeTransition(transitionCrossFade.getId()); + mVideoEditor.addTransition(transitionCrossFade); + averageTime += (duration2 - duration1); + } + final long durationToAddObjects = averageTime; + final float timeTaken = (float)durationToAddObjects * + 1.0f/(float)NUM_OF_ITERATIONS; + loggingInfo[0] = "Time taken to Generate Preview with transition\t" + + timeTaken; + writeTimingInfo("testPerformanceGeneratePreviewWithTransitions:", + loggingInfo); + } + + /** + * To test the performance of generatePreview : with KenBurn + * + * @throws Exception + */ + // TODO : remove PRF_009 + @LargeTest + public void testPerformanceWithKenBurn() throws Exception { + final String videoItemFileName = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_800kbps_1_17.mp4"; + final String imageItemFileName = INPUT_FILE_PATH + + "IMG_1600x1200.jpg"; + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + long averageTime = 0; + final String[] loggingInfo = new String[1]; + final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor, + "mediaItem1", videoItemFileName, renderingMode); + mediaVideoItem.setExtractBoundaries(0, 10000); + mVideoEditor.addMediaItem(mediaVideoItem); + + final MediaImageItem mediaImageItem = new MediaImageItem(mVideoEditor, + "mediaItem2", imageItemFileName, 10000, renderingMode); + mVideoEditor.addMediaItem(mediaImageItem); + + final Rect startRect = new Rect((mediaImageItem.getHeight() / 3), + (mediaImageItem.getWidth() / 3), (mediaImageItem.getHeight() / 2), + (mediaImageItem.getWidth() / 2)); + final Rect endRect = new Rect(0, 0, mediaImageItem.getWidth(), + mediaImageItem.getHeight()); + final EffectKenBurns kbEffectOnMediaItem = + new EffectKenBurns(mediaImageItem, "KBOnM2", startRect, endRect, + 500, 3000); + mediaImageItem.addEffect(kbEffectOnMediaItem); + + for (int i = 0; i < NUM_OF_ITERATIONS; i++) { + final long duration1 = SystemClock.uptimeMillis(); + mVideoEditor.generatePreview(new MediaProcessingProgressListener() { + public void onProgress(Object item, int action, int progress) { + } + }); + final long duration2 = SystemClock.uptimeMillis(); + mediaImageItem.removeEffect(kbEffectOnMediaItem.getId()); + mediaImageItem.addEffect(kbEffectOnMediaItem); + averageTime += duration2 - duration1; + } + + final long durationToAddObjects = (averageTime); + final float timeTaken = (float)durationToAddObjects * + 1.0f/(float)NUM_OF_ITERATIONS; + loggingInfo[0] = "Time taken to Generate KenBurn Effect \t" + + timeTaken; + writeTimingInfo("testPerformanceWithKenBurn", loggingInfo); + } + + /** + * To test the performance of generatePreview : with Transitions and + * Effect,Overlapping scenario + * + * @throws Exception + */ + // TODO : remove PRF_010 + @LargeTest + public void testPerformanceEffectOverlappingTransition() throws Exception { + final String videoItemFileName1 = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_800kbps_1_17.mp4"; + final String videoItemFileName2 = INPUT_FILE_PATH + + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4"; + final int videoStartTime1 = 0; + final int videoEndTime1 = 10000; + final int videoStartTime2 = 0; + final int videoEndTime2 = 10000; + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final int transitionDuration = 5000; + final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST; + final int effectItemStartTime = 5000; + final int effectItemDurationTime = 5000; + final int effectType = EffectColor.TYPE_COLOR; + final int effectColorType = EffectColor.GREEN; + long averageDuration = 0; + + final String[] loggingInfo = new String[1]; + final MediaVideoItem mediaVideoItem1 = new MediaVideoItem(mVideoEditor, + "mediaItem1", videoItemFileName1, renderingMode); + mediaVideoItem1.setExtractBoundaries(videoStartTime1, videoEndTime1); + mVideoEditor.addMediaItem(mediaVideoItem1); + + final MediaVideoItem mediaVideoItem2 = new MediaVideoItem(mVideoEditor, + "mediaItem2", videoItemFileName2, renderingMode); + mediaVideoItem2.setExtractBoundaries(videoStartTime2, videoEndTime2); + mVideoEditor.addMediaItem(mediaVideoItem2); + + final TransitionCrossfade transitionCrossFade = new TransitionCrossfade( + "transitionCrossFade", mediaVideoItem1, mediaVideoItem2, + transitionDuration, transitionBehavior); + mVideoEditor.addTransition(transitionCrossFade); + + final EffectColor effectColor = new EffectColor(mediaVideoItem1, + "effect", effectItemStartTime, effectItemDurationTime, effectType, + effectColorType); + mediaVideoItem1.addEffect(effectColor); + + for (int i = 0; i < NUM_OF_ITERATIONS; i++) { + final long duration1 = SystemClock.uptimeMillis(); + mVideoEditor.generatePreview(new MediaProcessingProgressListener() { + public void onProgress(Object item, int action, int progress) { + } + }); + final long duration2 = SystemClock.uptimeMillis(); + mVideoEditor.removeTransition(transitionCrossFade.getId()); + mVideoEditor.addTransition(transitionCrossFade); + averageDuration += (duration2 - duration1); + } + SystemClock.uptimeMillis(); + final long durationToAddObjects = (averageDuration); + final float timeTaken = (float)durationToAddObjects * + 1.0f/(float)NUM_OF_ITERATIONS; + loggingInfo[0] = + "Time taken to testPerformanceEffectOverlappingTransition\t" + + timeTaken; + writeTimingInfo("testPerformanceEffectOverlappingTransition:", + loggingInfo); + } + + /** + * To test creation of story board with Transition and Two Effects, Effect + * overlapping transitions + * + * @throws Exception + */ + // TODO : remove PRF_011 + @LargeTest + public void testPerformanceTransitionWithEffectOverlapping() throws Exception { + final String videoItemFileName1 = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_800kbps_1_17.mp4"; + final String videoItemFileName2 = INPUT_FILE_PATH + + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4"; + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final int transitionDuration = 5000; + final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST; + final int effectItemStartTime1 = 5000; + final int effectItemDurationTime1 = 5000; + final int effectType1 = EffectColor.TYPE_COLOR; + final int effectColorType1 = EffectColor.GREEN; + final int effectItemStartTime2 = 5000; + final int effectItemDurationTime2 = 5000; + final int effectType2 = EffectColor.TYPE_COLOR; + final int effectColorType2 = EffectColor.GREEN; + int averageTime = 0; + final String[] loggingInfo = new String[1]; + + final MediaVideoItem mediaVideoItem1 = new MediaVideoItem(mVideoEditor, + "mediaItem1", videoItemFileName1, renderingMode); + mVideoEditor.addMediaItem(mediaVideoItem1); + + final MediaVideoItem mediaVideoItem2 = new MediaVideoItem(mVideoEditor, + "mediaItem2", videoItemFileName2, renderingMode); + mVideoEditor.addMediaItem(mediaVideoItem2); + + final TransitionCrossfade transitionCrossFade = new TransitionCrossfade( + "transitionCrossFade", mediaVideoItem1, mediaVideoItem2, + transitionDuration, transitionBehavior); + mVideoEditor.addTransition(transitionCrossFade); + + final EffectColor effectColor1 = new EffectColor(mediaVideoItem1, + "effect1", effectItemStartTime1, effectItemDurationTime1, + effectType1, effectColorType1); + mediaVideoItem1.addEffect(effectColor1); + + final EffectColor effectColor2 = new EffectColor(mediaVideoItem2, + "effect2", effectItemStartTime2, effectItemDurationTime2, + effectType2, effectColorType2); + mediaVideoItem2.addEffect(effectColor2); + + for (int i = 0; i < NUM_OF_ITERATIONS; i++) { + final long duration1 = SystemClock.uptimeMillis(); + mVideoEditor.generatePreview(new MediaProcessingProgressListener() { + public void onProgress(Object item, int action, int progress) { + } + }); + final long duration2 = SystemClock.uptimeMillis(); + mVideoEditor.removeTransition(transitionCrossFade.getId()); + mVideoEditor.addTransition(transitionCrossFade); + averageTime += duration2 - duration1; + } + final long durationToAddObjects = (averageTime); + final float timeTaken = (float)durationToAddObjects * + 1.0f/(float)NUM_OF_ITERATIONS; + loggingInfo[0] = "Time taken to TransitionWithEffectOverlapping\t" + + timeTaken; + writeTimingInfo("testPerformanceTransitionWithEffectOverlapping", + loggingInfo); + } + + /** + *To test ThumbnailList for H264 + */ + // TODO : TC_PRF_12 + @LargeTest + public void testThumbnailH264NonIFrame() throws Exception { + final String videoItemFilename = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_800kbps_1_17.mp4"; + final int outWidth = 1080; + final int outHeight = 720; + final int atTime = 2400; + long durationToAddObjects = 0; + int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String[] loggingInfo = new String[1]; + final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor, + "m1", videoItemFilename, renderingMode); + assertNotNull("MediaVideoItem", mediaVideoItem); + + for (int i = 0; i < NUM_OF_ITERATIONS; i++) { + final long duration1 = SystemClock.uptimeMillis(); + mediaVideoItem.getThumbnail(outWidth, outHeight, atTime + i); + final long duration2 = SystemClock.uptimeMillis(); + durationToAddObjects += (duration2 - duration1); + } + final float timeTaken = (float)durationToAddObjects * + 1.0f/(float)NUM_OF_ITERATIONS; + loggingInfo[0] = "Time taken for Thumbnail generation \t" + + timeTaken; + writeTimingInfo("testThumbnailH264NonIFrame", loggingInfo); + } + + /** + *To test ThumbnailList for H264 + */ + // TODO : TC_PRF_13 + @LargeTest + public void testThumbnailH264AnIFrame() throws Exception { + final String videoItemFilename = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_800kbps_1_17.mp4"; + final int outWidth = 1080; + final int outHeight = 720; + final int atTime = 3000; + int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String[] loggingInfo = new String[1]; + long durationToAddObjects = 0; + + final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor, + "m1", videoItemFilename, renderingMode); + assertNotNull("MediaVideoItem", mediaVideoItem); + + for (int i = 0; i < NUM_OF_ITERATIONS; i++) { + final long duration1 = SystemClock.uptimeMillis(); + mediaVideoItem.getThumbnail(outWidth, outHeight, atTime + i); + final long duration2 = SystemClock.uptimeMillis(); + durationToAddObjects += (duration2 - duration1); + } + final float timeTaken = (float)durationToAddObjects * + 1.0f/(float)NUM_OF_ITERATIONS; + loggingInfo[0] = "Time taken Thumbnail generation \t" + + timeTaken; + writeTimingInfo("testThumbnailH264AnIFrame", loggingInfo); + } + + /** + * To test the performance : With an audio track + * + * @throws Exception + */ + // TODO : remove PRF_014 + @LargeTest + public void testPerformanceWithAudioTrack() throws Exception { + final String videoItemFileName1 = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_800kbps_1_17.mp4"; + final String audioFilename1 = INPUT_FILE_PATH + + "AACLC_44.1kHz_256kbps_s_1_17.mp4"; + final String audioFilename2 = INPUT_FILE_PATH + + "AMRNB_8KHz_12.2Kbps_m_1_17.3gp"; + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final int audioVolume = 50; + final String[] loggingInfo = new String[2]; + float timeTaken = 0.0f; + + final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor, + "mediaItem1", videoItemFileName1, renderingMode); + mVideoEditor.addMediaItem(mediaVideoItem); + + final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor, + "Audio Track1", audioFilename1); + audioTrack1.disableDucking(); + audioTrack1.setVolume(audioVolume); + mVideoEditor.addAudioTrack(audioTrack1); + + long beginTime = SystemClock.uptimeMillis(); + mVideoEditor.generatePreview(new MediaProcessingProgressListener() { + public void onProgress(Object item, int action, int progress) { + } + }); + timeTaken = calculateTimeTaken(beginTime, 1); + loggingInfo[0] = "Time taken for 1st Audio Track (AACLC)\t" + + timeTaken; + + final AudioTrack audioTrack2 = new AudioTrack(mVideoEditor, + "Audio Track2", audioFilename2); + audioTrack2.enableLoop(); + + beginTime = SystemClock.uptimeMillis(); + mVideoEditor.generatePreview(new MediaProcessingProgressListener() { + public void onProgress(Object item, int action, int progress) { + } + }); + timeTaken = calculateTimeTaken(beginTime, 1); + loggingInfo[1] = "\n\tTime taken for 2nd Audio Track(AMRNB)\t" + + timeTaken; + + writeTimingInfo("testPerformanceWithAudioTrack", loggingInfo); + } + + /** + * To test the performance of adding and removing the + * image media item with 640 x 480 + * + * @throws Exception + */ + // TODO : remove PRF_015 + @LargeTest + public void testPerformanceAddRemoveImageItem640x480() throws Exception { + final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg"; + final int imageItemDuration = 0; + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String[] loggingInfo = new String[3]; + + float timeTaken = 0.0f; + + final MediaImageItem[] mediaImageItem = + new MediaImageItem[NUM_OF_ITERATIONS]; + long beginTime = SystemClock.uptimeMillis(); + createImageItems(mediaImageItem, imageItemFileName, renderingMode, + imageItemDuration); + timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS); + loggingInfo[0] = "Time taken to Create Media Image Item (640x480)\t" + + timeTaken; + + beginTime = SystemClock.uptimeMillis(); + addImageItems(mediaImageItem); + timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS); + loggingInfo[1] = "\n\tTime taken to add Media Image Item (640x480)\t" + + timeTaken; + + beginTime = SystemClock.uptimeMillis(); + removeImageItems(mediaImageItem); + timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS); + loggingInfo[2] = "\n\tTime taken to remove Media Image Item (640x480)\t" + + timeTaken; + writeTimingInfo("testPerformanceAddRemoveImageItem640x480 (in mSec)", loggingInfo); + } + + +} diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/VideoEditorStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/VideoEditorStressTest.java new file mode 100755 index 000000000000..0e70dd3fd368 --- /dev/null +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/VideoEditorStressTest.java @@ -0,0 +1,1317 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.mediaframeworktest.stress; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.Writer; +import java.util.List; + +import android.graphics.Bitmap; +import android.graphics.Rect; +import android.media.videoeditor.AudioTrack; +import android.media.videoeditor.EffectColor; +import android.media.videoeditor.EffectKenBurns; +import android.media.videoeditor.MediaImageItem; +import android.media.videoeditor.MediaItem; +import android.media.videoeditor.MediaProperties; +import android.media.videoeditor.MediaVideoItem; +import android.media.videoeditor.OverlayFrame; +import android.media.videoeditor.Transition; +import android.media.videoeditor.TransitionCrossfade; +import android.media.videoeditor.TransitionAlpha; +import android.media.videoeditor.TransitionFadeBlack; +import android.media.videoeditor.TransitionSliding; +import android.media.videoeditor.VideoEditor; +import android.os.Environment; +import android.test.ActivityInstrumentationTestCase; +import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener; +import android.os.Environment; +import android.os.SystemClock; +import android.test.ActivityInstrumentationTestCase; +import android.media.videoeditor.VideoEditor.ExportProgressListener; +import android.media.videoeditor.VideoEditorFactory; +import android.media.videoeditor.ExtractAudioWaveformProgressListener; + +import android.os.Debug; +import android.util.Log; + +import com.android.mediaframeworktest.MediaFrameworkTest; +import android.test.suitebuilder.annotation.LargeTest; +import com.android.mediaframeworktest.VideoEditorHelper; + +/** + * Junit / Instrumentation - performance measurement for media player and + * recorder + */ +public class VideoEditorStressTest + extends ActivityInstrumentationTestCase<MediaFrameworkTest> { + + private final String TAG = "VideoEditorPerformance"; + + private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON; + + private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON; + + private final String VIDEOEDITOR_OUTPUT = PROJECT_LOCATION + + "VideoEditorStressMemOutput.txt"; + + private long BeginJavaMemory; + private long AfterJavaMemory; + + private long BeginNativeMemory; + private long AfterNativeMemory; + + public VideoEditorStressTest() { + super("com.android.mediaframeworktest", MediaFrameworkTest.class); + new File(VIDEOEDITOR_OUTPUT).delete(); + } + + private final String PROJECT_CLASS_NAME = + "android.media.videoeditor.VideoEditorImpl"; + private VideoEditor mVideoEditor; + private VideoEditorHelper mVideoEditorHelper; + + @Override + protected void setUp() throws Exception { + // setup for each test case. + super.setUp(); + mVideoEditorHelper = new VideoEditorHelper(); + // Create a random String which will be used as project path, where all + // project related files will be stored. + final String projectPath = + mVideoEditorHelper.createRandomFile(PROJECT_LOCATION); + mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath); + } + + @Override + protected void tearDown() throws Exception { + mVideoEditorHelper.destroyVideoEditor(mVideoEditor); + // Clean the directory created as project path + mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath())); + System.gc(); + super.tearDown(); + } + + private void writeTimingInfo(String[] information) + throws Exception { + File outFile = new File(VIDEOEDITOR_OUTPUT); + Writer output = new BufferedWriter(new FileWriter(outFile, true)); + for (int i = 0; i < information.length; i++) { + output.write(information[i]); + } + output.close(); + } + + private void writeTestCaseHeader(String testCaseName) + throws Exception { + File outFile = new File(VIDEOEDITOR_OUTPUT); + Writer output = new BufferedWriter(new FileWriter(outFile, true)); + output.write("\n\n" + testCaseName + "\n"); + output.close(); + } + + private void getBeginMemory() throws Exception { + System.gc(); + Thread.sleep(2500); + BeginNativeMemory = Debug.getNativeHeapAllocatedSize(); + } + private void getAfterMemory_updateLog(String[] loggingInfo, boolean when, + int iteration) + throws Exception { + System.gc(); + Thread.sleep(2500); + AfterNativeMemory = Debug.getNativeHeapAllocatedSize(); + if(when == false){ + loggingInfo[0] = "\n Before Remove: iteration No.= " + iteration + + "\t " + (AfterNativeMemory - BeginNativeMemory); + } else { + loggingInfo[0] = "\n After Remove: iteration No.= " + iteration + + "\t " + (AfterNativeMemory - BeginNativeMemory); + } + writeTimingInfo(loggingInfo); + } + + /** + * To stress test MediaItem(Video Item) adding functionality + * + * @throws Exception + */ + // TODO : remove TC_STR_001 + @LargeTest + public void testStressAddRemoveVideoItem() throws Exception { + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + + final String videoItemFileName1 = INPUT_FILE_PATH + + "H264_BP_176x144_15fps_144kbps_AMRNB_8kHz_12.2kbps_m_1_17.3gp"; + final String videoItemFileName2 = INPUT_FILE_PATH + + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4"; + final String videoItemFileName3 = INPUT_FILE_PATH + + "H263_profile0_176x144_15fps_128kbps_1_35.3gp"; + final String videoItemFileName4 = INPUT_FILE_PATH + + "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp"; + final String[] loggingInfo = new String[1]; + writeTestCaseHeader("testStressAddRemoveVideoItem"); + int i = 0; + getBeginMemory(); + + for ( i = 0; i < 50; i++) { + if (i % 4 == 0) { + final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor, + "m1" + i, videoItemFileName1, renderingMode); + mediaItem1.setExtractBoundaries(0, 5000); + mVideoEditor.addMediaItem(mediaItem1); + } + if (i % 4 == 1) { + final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor, + "m2" + i, videoItemFileName2, renderingMode); + mediaItem2.setExtractBoundaries(0, 10000); + mVideoEditor.addMediaItem(mediaItem2); + } + if (i % 4 == 2) { + final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor, + "m3" + i, videoItemFileName3, renderingMode); + mediaItem3.setExtractBoundaries(30000, 45000); + mVideoEditor.addMediaItem(mediaItem3); + } + if (i % 4 == 3) { + final MediaVideoItem mediaItem4 = new MediaVideoItem(mVideoEditor, + "m4" + i, videoItemFileName4, renderingMode); + mediaItem4.setExtractBoundaries(10000, 30000); + mVideoEditor.addMediaItem(mediaItem4); + } + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, false, i); + } + } + getAfterMemory_updateLog(loggingInfo, false, i); + + /** Remove items and check for memory leak if any */ + getBeginMemory(); + for ( i = 0; i < 50; i++) { + if (i % 4 == 0) { + mVideoEditor.removeMediaItem("m1" + i); + } + if (i % 4 == 1) { + mVideoEditor.removeMediaItem("m2" + i); + } + if (i % 4 == 2) { + mVideoEditor.removeMediaItem("m3" + i); + } + if (i % 4 == 3) { + mVideoEditor.removeMediaItem("m4" + i); + } + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, true, i); + } + } + getAfterMemory_updateLog(loggingInfo, true, i); + } + + /** + * To stress test MediaItem(Image Item) adding functionality + * + * @throws Exception + */ + // TODO : remove TC_STR_002 + @LargeTest + public void testStressAddRemoveImageItem() throws Exception { + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String ImageItemFileName1 = INPUT_FILE_PATH + + "IMG_1600x1200.jpg"; + final String ImageItemFileName2 = INPUT_FILE_PATH + + "IMG_640x480.jpg"; + final String ImageItemFileName3 = INPUT_FILE_PATH + + "IMG_320x240.jpg"; + final String ImageItemFileName4 = INPUT_FILE_PATH + + "IMG_176x144.jpg"; + final String[] loggingInfo = new String[1]; + int i = 0; + writeTestCaseHeader("testStressAddRemoveImageItem"); + getBeginMemory(); + for ( i = 0; i < 50; i++) { + if (i % 4 == 0) { + final MediaImageItem mediaItem1 = new MediaImageItem(mVideoEditor, + "m1"+ i, ImageItemFileName1, 5000, renderingMode); + mVideoEditor.addMediaItem(mediaItem1); + } + if (i % 4 == 1) { + final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor, + "m2"+ i, ImageItemFileName2, 10000, renderingMode); + mVideoEditor.addMediaItem(mediaItem2); + } + if (i % 4 == 2) { + final MediaImageItem mediaItem3 = new MediaImageItem(mVideoEditor, + "m3"+ i, ImageItemFileName3, 15000, renderingMode); + mVideoEditor.addMediaItem(mediaItem3); + } + if (i % 4 == 3) { + final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor, + "m4"+ i, ImageItemFileName4, 20000, renderingMode); + mVideoEditor.addMediaItem(mediaItem4); + } + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, false, i); + } + } + getAfterMemory_updateLog(loggingInfo, false, i); + + /** Remove items and check for memory leak if any */ + getBeginMemory(); + for ( i = 0; i < 50; i++) { + if (i % 4 == 0) { + mVideoEditor.removeMediaItem("m1"+i); + } + if (i % 4 == 1) { + mVideoEditor.removeMediaItem("m2"+i); + } + if (i % 4 == 2) { + mVideoEditor.removeMediaItem("m3"+i); + } + if (i % 4 == 3) { + mVideoEditor.removeMediaItem("m4"+i); + } + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, true, i); + } + } + getAfterMemory_updateLog(loggingInfo, true, i); + } + + /** + * To stress test transition + * + * @throws Exception + */ + // TODO : remove TC_STR_003 + @LargeTest + public void testStressAddRemoveTransition() throws Exception { + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String VideoItemFileName1 = INPUT_FILE_PATH + + "H264_BP_800x480_15fps_512kbps_1_17.mp4"; + final String ImageItemFileName2 = INPUT_FILE_PATH + + "IMG_1600x1200.jpg"; + final String VideoItemFileName3 = INPUT_FILE_PATH + + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4"; + final String maskFilename = INPUT_FILE_PATH + + "TransitionSpiral_QVGA.jpg"; + final String[] loggingInfo = new String[1]; + int i = 0; + writeTestCaseHeader("testStressAddRemoveTransition"); + getBeginMemory(); + for ( i = 0; i < 50; i++) { + if (i % 4 == 0) { + final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor, + "m1"+i, VideoItemFileName1, renderingMode); + mVideoEditor.addMediaItem(mediaItem1); + mediaItem1.setExtractBoundaries(0, 10000); + final TransitionCrossfade tranCrossfade = + new TransitionCrossfade("transCF" + i, null, + mediaItem1, 5000, Transition.BEHAVIOR_MIDDLE_FAST); + mVideoEditor.addTransition(tranCrossfade); + } + if (i % 4 == 1) { + final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor, + "m1"+i, VideoItemFileName1, renderingMode); + mVideoEditor.addMediaItem(mediaItem1); + mediaItem1.setExtractBoundaries(0, 10000); + + final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor, + "m2" +i, ImageItemFileName2, 10000, renderingMode); + mVideoEditor.addMediaItem(mediaItem2); + + final TransitionAlpha transitionAlpha = + mVideoEditorHelper.createTAlpha("transAlpha" + i, mediaItem1, + mediaItem2, 5000, Transition.BEHAVIOR_SPEED_UP, + maskFilename, 10, false); + transitionAlpha.setDuration(4000); + mVideoEditor.addTransition(transitionAlpha); + } + if (i % 4 == 2) { + final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor, + "m2" + i, ImageItemFileName2, 10000, renderingMode); + mVideoEditor.addMediaItem(mediaItem2); + + final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor, + "m3" + i, VideoItemFileName3, renderingMode); + mVideoEditor.addMediaItem(mediaItem3); + + mediaItem3.setExtractBoundaries(0, 10000); + final TransitionAlpha transitionAlpha = + mVideoEditorHelper.createTAlpha("transAlpha" + i, mediaItem2, + mediaItem3, 5000, Transition.BEHAVIOR_SPEED_UP, + maskFilename, 10, false); + transitionAlpha.setDuration(4000); + mVideoEditor.addTransition(transitionAlpha); + + mediaItem3.setExtractBoundaries(0, 6000); + + final TransitionSliding transition2And3 = + mVideoEditorHelper.createTSliding("transSlide" +i, mediaItem2, + mediaItem3, 3000, Transition.BEHAVIOR_MIDDLE_FAST, + TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN); + mVideoEditor.addTransition(transition2And3); + } + if (i % 4 == 3) { + final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor, + "m3" + i, VideoItemFileName3, renderingMode); + mVideoEditor.addMediaItem(mediaItem3); + mediaItem3.setExtractBoundaries(0, 5000); + + final TransitionFadeBlack transition3 = + mVideoEditorHelper.createTFadeBlack("transFB" +i, mediaItem3, + null, 2500, Transition.BEHAVIOR_SPEED_UP); + transition3.setDuration(500); + mVideoEditor.addTransition(transition3); + } + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, false, i); + } + } + getAfterMemory_updateLog(loggingInfo, false, i); + + /** Remove items and check for memory leak if any */ + getBeginMemory(); + for ( i = 0; i < 50; i++) { + if (i % 4 == 0) { + mVideoEditor.removeTransition("transCF" + i); + mVideoEditor.removeMediaItem("m1" + i); + } + if (i % 4 == 1) { + mVideoEditor.removeTransition("transAlpha" + i); + mVideoEditor.removeMediaItem("m1" + i); + mVideoEditor.removeMediaItem("m2" + i); + } + if (i % 4 == 2) { + mVideoEditor.removeTransition("transSlide" +i); + mVideoEditor.removeMediaItem("m2" + i); + mVideoEditor.removeMediaItem("m3" + i); + } + if (i % 4 == 3) { + mVideoEditor.removeMediaItem("m3" + i); + } + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, true, i); + } + } + getAfterMemory_updateLog(loggingInfo, true, i); + } + + /** + * To stress test overlay + * + * @throws Exception + */ + // TODO : remove TC_STR_004 + @LargeTest + public void testStressAddRemoveOverlay() throws Exception { + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String VideoItemFileName1 = INPUT_FILE_PATH + + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4"; + final String ImageItemFileName2 = INPUT_FILE_PATH + + "IMG_640x480.jpg"; + final String OverlayFile3 = INPUT_FILE_PATH + + "IMG_640x480_Overlay1.png"; + final String OverlayFile4 = INPUT_FILE_PATH + + "IMG_640x480_Overlay2.png"; + final String[] loggingInfo = new String[1]; + int i = 0; + final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor, + "m1", VideoItemFileName1, renderingMode); + mVideoEditor.addMediaItem(mediaItem1); + + final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor, + "m2", ImageItemFileName2, 10000, renderingMode); + mVideoEditor.addMediaItem(mediaItem2); + writeTestCaseHeader("testStressAddRemoveOverlay"); + getBeginMemory(); + for ( i = 0; i < 50; i++) { + if (i % 3 == 0) { + mediaItem1.setExtractBoundaries(0, 10000); + final Bitmap mBitmap = mVideoEditorHelper.getBitmap( + OverlayFile3, 640, 480); + final OverlayFrame overlayFrame = + mVideoEditorHelper.createOverlay(mediaItem1, "overlay" + i, + mBitmap, 1000, 5000); + mediaItem1.addOverlay(overlayFrame); + mediaItem1.removeOverlay("overlay"+i); + } + if (i % 3 == 1) { + final Bitmap mBitmap = mVideoEditorHelper.getBitmap( + OverlayFile4, 640, 480); + final OverlayFrame overlayFrame = + mVideoEditorHelper.createOverlay(mediaItem2, "overlay" + i, + mBitmap, 1000, 5000); + mediaItem2.addOverlay(overlayFrame); + mediaItem2.removeOverlay("overlay"+i); + } + if (i % 3 == 2) { + mediaItem1.setExtractBoundaries(0, 10000); + final Bitmap mBitmap = mVideoEditorHelper.getBitmap( + OverlayFile4, 640, 480); + final OverlayFrame overlayFrame = + mVideoEditorHelper.createOverlay(mediaItem1, "overlay" + i, + mBitmap, 0, mediaItem1.getDuration()); + mediaItem1.addOverlay(overlayFrame); + mediaItem1.removeOverlay("overlay"+i); + } + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, false, i); + } + } + getAfterMemory_updateLog(loggingInfo, false, i); + } + + /** + * To stress test Effects + * + * @throws Exception + */ + // TODO : remove TC_STR_005 + @LargeTest + public void testStressAddRemoveEffects() throws Exception { + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String VideoItemFileName1 = INPUT_FILE_PATH + + "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp"; + final String ImageItemFileName2 = INPUT_FILE_PATH + + "IMG_1600x1200.jpg"; + final String[] loggingInfo = new String[1]; + final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor, + "m1", VideoItemFileName1, renderingMode); + mVideoEditor.addMediaItem(mediaItem1); + final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor, + "m2", ImageItemFileName2, 10000, renderingMode); + int i = 0; + mVideoEditor.addMediaItem(mediaItem2); + writeTestCaseHeader("testStressAddRemoveEffects"); + getBeginMemory(); + for ( i = 0; i < 50; i++) { + if (i % 5 == 0) { + mediaItem1.setExtractBoundaries(10000, 30000); + final EffectColor effectColor1 = + mVideoEditorHelper.createEffectItem(mediaItem1, "effect1"+i, + 10000, (mediaItem1.getTimelineDuration()-1000), + EffectColor.TYPE_COLOR, EffectColor.GREEN); + mediaItem1.addEffect(effectColor1); + } + if (i % 5 == 1) { + mediaItem2.setDuration(20000); + final EffectColor effectColor1 = + mVideoEditorHelper.createEffectItem(mediaItem2, "effect1"+i, + 0, 4000, EffectColor.TYPE_GRADIENT, EffectColor.GRAY); + mediaItem2.addEffect(effectColor1); + } + if (i % 5 == 2) { + mediaItem1.setExtractBoundaries(10000, 30000); + final EffectColor effectColor1 = + mVideoEditorHelper.createEffectItem(mediaItem1, "effect1"+i, + (mediaItem1.getTimelineDuration() - 4000), 4000, + EffectColor.TYPE_SEPIA, 0); + mediaItem1.addEffect(effectColor1); + } + if (i % 5 == 3) { + mediaItem2.setDuration(20000); + final EffectColor effectColor1 = + mVideoEditorHelper.createEffectItem(mediaItem2, "effect1"+i, + 10000, 4000, EffectColor.TYPE_NEGATIVE, 0); + mediaItem2.addEffect(effectColor1); + } + if (i % 5 == 4) { + mediaItem2.setDuration(20000); + final Rect startRect = new Rect((mediaItem2.getHeight() / 3), + (mediaItem2.getWidth() / 3), (mediaItem2.getHeight() / 2), + (mediaItem2.getWidth() / 2)); + final Rect endRect = new Rect(0, 0, mediaItem2.getWidth(), + mediaItem2.getHeight()); + final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns( + mediaItem2, "KBOnM2" + i, startRect, endRect, 500, + (mediaItem2.getDuration() - 500)); + mediaItem2.addEffect(kbEffectOnMediaItem); + } + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, false, i); + } + } + getAfterMemory_updateLog(loggingInfo, false, i); + + /** Remove items and check for memory leak if any */ + getBeginMemory(); + for ( i = 0; i < 50; i++) { + if (i % 5 == 0) { + mediaItem1.removeEffect("effect1"+i); + } + if (i % 5 == 1) { + mediaItem1.removeEffect("effect1"+i); + } + if (i % 5 == 2) { + mediaItem1.removeEffect("effect1"+i); + } + if (i % 5 == 3) { + mediaItem1.removeEffect("effect1"+i); + } + if (i % 5 == 4) { + mediaItem1.removeEffect("KBOnM2"+i); + } + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, true, i); + } + } + getAfterMemory_updateLog(loggingInfo, true, i); + } + + /** + * This method will test thumbnail list extraction in a loop = 200 for Video + * Item + * + * @throws Exception + */ + // TODO : remove TC_STR_006 + @LargeTest + public void testStressThumbnailVideoItem() throws Exception { + final String videoItemFileName = INPUT_FILE_PATH + + "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_64kps_m_0_27.3gp"; + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String[] loggingInfo = new String[1]; + int i = 0; + final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor, + "m1", videoItemFileName, renderingMode); + writeTestCaseHeader("testStressThumbnailVideoItem"); + getBeginMemory(); + for ( i = 0; i < 50; i++) { + if (i % 4 == 0) { + final Bitmap[] thumbNails = + mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth()*3, + mediaVideoItem.getHeight()*2, i, 5000, 2); + // Recycle this Bitmap array + for (int i1 = 0; i1 < thumbNails.length; i1++) { + thumbNails[i1].recycle(); + } + } + if (i % 4 == 1) { + final Bitmap[] thumbNails = + mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth()/2, + mediaVideoItem.getHeight() * 3, i, 5000, 2); + // Recycle this Bitmap array + for (int i1 = 0; i1 < thumbNails.length; i1++) { + thumbNails[i1].recycle(); + } + } + if (i % 4 == 2) { + final Bitmap[] thumbNails = + mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth()*2, + mediaVideoItem.getHeight() / 3, i, 5000, 2); + // Recycle this Bitmap array + for (int i1 = 0; i1 < thumbNails.length; i1++) { + thumbNails[i1].recycle(); + } + } + if (i % 4 == 3) { + final Bitmap[] thumbNails = + mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth(), + mediaVideoItem.getHeight(), i, 5000, 2); + // Recycle this Bitmap array + for (int i1 = 0; i1 < thumbNails.length; i1++) { + thumbNails[i1].recycle(); + } + } + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, false, i); + } + } + getAfterMemory_updateLog(loggingInfo, false, i); + } + + /** + * To stress test media properties + * + * @throws Exception + */ + // TODO : remove TC_STR_007 + @LargeTest + public void testStressMediaProperties() throws Exception { + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String VideoItemFileName1 = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_800kbps_1_17.mp4"; + final String ImageItemFileName2 = INPUT_FILE_PATH + + "IMG_640x480.jpg"; + final String AudioItemFileName3 = INPUT_FILE_PATH + + "AACLC_44.1kHz_256kbps_s_1_17.mp4"; + final String[] loggingInfo = new String[1]; + int i = 0; + final int videoAspectRatio = MediaProperties.ASPECT_RATIO_3_2; + final int videoFileType = MediaProperties.FILE_MP4; + final int videoCodecType = MediaProperties.VCODEC_H264BP; + final int videoDuration = 77366; + final int videoProfile = MediaProperties.H264_PROFILE_0_LEVEL_1_3; + final int videoHeight = MediaProperties.HEIGHT_720; + final int videoWidth = 1080; + + final int imageAspectRatio = MediaProperties.ASPECT_RATIO_4_3; + final int imageFileType = MediaProperties.FILE_JPEG; + final int imageWidth = 640; + final int imageHeight = MediaProperties.HEIGHT_480; + + final int audioDuration = 77554; + final int audioCodecType = MediaProperties.ACODEC_AAC_LC; + final int audioSamplingFrequency = 44100; + final int audioChannel = 2; + writeTestCaseHeader("testStressMediaProperties"); + getBeginMemory(); + for ( i = 0; i < 50; i++) { + if (i % 3 == 0) { + final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor, + "m1" + i, VideoItemFileName1, renderingMode); + mVideoEditor.addMediaItem(mediaItem1); + mediaItem1.setExtractBoundaries(0, 20000); + assertEquals("Aspect Ratio Mismatch", + videoAspectRatio, mediaItem1.getAspectRatio()); + assertEquals("File Type Mismatch", + videoFileType, mediaItem1.getFileType()); + assertEquals("VideoCodec Mismatch", + videoCodecType, mediaItem1.getVideoType()); + assertEquals("duration Mismatch", + videoDuration, mediaItem1.getDuration()); + assertEquals("Video Profile ", + videoProfile, mediaItem1.getVideoProfile()); + assertEquals("Video height ", + videoHeight, mediaItem1.getHeight()); + assertEquals("Video width ", + videoWidth, mediaItem1.getWidth()); + mVideoEditor.removeMediaItem("m1" + i); + } + if (i % 3 == 1) { + final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor, + "m2" + i, ImageItemFileName2, 10000, renderingMode); + mVideoEditor.addMediaItem(mediaItem2); + assertEquals("Aspect Ratio Mismatch", + imageAspectRatio, mediaItem2.getAspectRatio()); + assertEquals("File Type Mismatch", + imageFileType, mediaItem2.getFileType()); + assertEquals("Image height", + imageHeight, mediaItem2.getHeight()); + assertEquals("Image width", + imageWidth, mediaItem2.getWidth()); + mVideoEditor.removeMediaItem("m2" + i); + } + if (i % 3 == 2) { + final AudioTrack mediaItem3 = new AudioTrack(mVideoEditor, + "m3" + i, AudioItemFileName3); + mVideoEditor.addAudioTrack(mediaItem3); + assertEquals("AudioType Mismatch", audioCodecType, + mediaItem3.getAudioType()); + assertEquals("Audio Sampling", audioSamplingFrequency, + mediaItem3.getAudioSamplingFrequency()); + assertEquals("Audio Channels", + audioChannel, mediaItem3.getAudioChannels()); + assertEquals("duration Mismatch", audioDuration, + mediaItem3.getDuration()); + mVideoEditor.removeAudioTrack("m3" + i); + } + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, false, i); + } + } + getAfterMemory_updateLog(loggingInfo, false, i); + } + + /** + * To stress test insert and move of mediaitems + * + * @throws Exception + */ + // TODO : remove TC_STR_008 + @LargeTest + public void testStressInsertMovieItems() throws Exception { + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String VideoItemFileName1 = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_800kbps_1_17.mp4"; + final String VideoItemFileName2 = INPUT_FILE_PATH + + "H264_BP_800x480_15fps_512kbps_1_17.mp4"; + final String VideoItemFileName3 = INPUT_FILE_PATH + + "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp"; + final String[] loggingInfo = new String[1]; + int i = 0; + writeTestCaseHeader("testStressInsertMoveItems"); + + final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor, + "m1", VideoItemFileName1, renderingMode); + mVideoEditor.addMediaItem(mediaItem1); + mediaItem1.setExtractBoundaries(0, 10000); + + final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor, + "m2", VideoItemFileName2, renderingMode); + mVideoEditor.addMediaItem(mediaItem2); + mediaItem2.setExtractBoundaries(0, 15000); + + getBeginMemory(); + for ( i = 0; i < 50; i++) { + final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor, + "m3" + i, VideoItemFileName3, renderingMode); + mediaItem3.setExtractBoundaries(0, 15000); + mVideoEditor.insertMediaItem(mediaItem3, "m1"); + mVideoEditor.moveMediaItem("m2", "m3" + i); + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, false, i); + } + } + getAfterMemory_updateLog(loggingInfo, false, i); + + /** Remove items and check for memory leak if any */ + getBeginMemory(); + for ( i = 0; i < 50; i++) { + mVideoEditor.removeMediaItem("m3" + i); + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, true, i); + } + } + mVideoEditor.removeMediaItem("m2"); + mVideoEditor.removeMediaItem("m1"); + getAfterMemory_updateLog(loggingInfo, true, i); + } + + /** + * To stress test : load and save + * + * @throws Exception + */ + // TODO : remove TC_STR_009 + @LargeTest + public void testStressLoadAndSave() throws Exception { + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String VideoItemFileName1 = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_800kbps_1_17.mp4"; + final String VideoItemFileName2 = INPUT_FILE_PATH + + "H264_BP_800x480_15fps_512kbps_1_17.mp4"; + final String VideoItemFileName3 = INPUT_FILE_PATH + + "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp"; + final String ImageItemFileName4 = INPUT_FILE_PATH + + "IMG_640x480.jpg"; + final String ImageItemFileName5 = INPUT_FILE_PATH + + "IMG_176x144.jpg"; + final String OverlayFile6 = INPUT_FILE_PATH + + "IMG_640x480_Overlay1.png"; + final String[] loggingInfo = new String[1]; + int i = 0; + final String[] projectPath = new String[10]; + writeTestCaseHeader("testStressLoadAndSave"); + getBeginMemory(); + for( i=0; i < 10; i++){ + + projectPath[i] = + mVideoEditorHelper.createRandomFile(PROJECT_LOCATION); + final VideoEditor mVideoEditor1 = + mVideoEditorHelper.createVideoEditor(projectPath[i]); + + final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor1, + "m1", VideoItemFileName1, renderingMode); + mVideoEditor1.addMediaItem(mediaItem1); + mediaItem1.setExtractBoundaries(0, 10000); + + final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor1, + "m2", VideoItemFileName2, renderingMode); + mVideoEditor1.addMediaItem(mediaItem2); + mediaItem2.setExtractBoundaries(mediaItem2.getDuration()/4, + mediaItem2.getDuration()/2); + + final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor1, + "m3", VideoItemFileName3, renderingMode); + mVideoEditor1.addMediaItem(mediaItem3); + mediaItem3.setExtractBoundaries(mediaItem3.getDuration()/2, + mediaItem3.getDuration()); + + final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor1, + "m4", ImageItemFileName4, 5000, renderingMode); + mVideoEditor1.addMediaItem(mediaItem4); + + final MediaImageItem mediaItem5 = new MediaImageItem(mVideoEditor1, + "m5", ImageItemFileName5, 5000, renderingMode); + mVideoEditor1.addMediaItem(mediaItem5); + + final EffectColor effectColor1 = + mVideoEditorHelper.createEffectItem(mediaItem3, "effect1", + 10000, 2000, EffectColor.TYPE_COLOR, EffectColor.GREEN); + mediaItem3.addEffect(effectColor1); + + final Bitmap mBitmap = mVideoEditorHelper.getBitmap(OverlayFile6, + 640, 480); + final OverlayFrame overlayFrame = + mVideoEditorHelper.createOverlay(mediaItem4, "overlay", + mBitmap, 4000, 1000); + mediaItem4.addOverlay(overlayFrame); + + final TransitionCrossfade tranCrossfade = + new TransitionCrossfade("transCF", mediaItem1, + mediaItem2, 5000, Transition.BEHAVIOR_MIDDLE_FAST); + mVideoEditor1.addTransition(tranCrossfade); + + final EffectColor effectColor2 = + mVideoEditorHelper.createEffectItem(mediaItem4, "effect2", 0, + mediaItem4.getDuration(), EffectColor.TYPE_COLOR, + EffectColor.PINK); + mediaItem4.addEffect(effectColor2); + + mVideoEditor1.generatePreview(new MediaProcessingProgressListener() { + public void onProgress(Object item, int action, int progress) { + } + }); + + mVideoEditor1.save(); + mVideoEditor1.release(); + + getAfterMemory_updateLog(loggingInfo, false, i); + } + getAfterMemory_updateLog(loggingInfo, false, i); + + /** Remove items and check for memory leak if any */ + getBeginMemory(); + for( i=0; i<10; i++){ + final VideoEditor mVideoEditor1b = + VideoEditorFactory.load(projectPath[i], true); + List<MediaItem> mediaList = mVideoEditor1b.getAllMediaItems(); + assertEquals("Media Item List Size", 5, mediaList.size()); + + mediaList.get(3).removeEffect("effect1"); + mediaList.get(3).removeEffect("effect2"); + mediaList.get(2).removeOverlay("overlay"); + mVideoEditor1b.removeTransition("transCF"); + mVideoEditor1b.removeMediaItem("m5"); + mVideoEditor1b.removeMediaItem("m4"); + mVideoEditor1b.removeMediaItem("m3"); + mVideoEditor1b.removeMediaItem("m2"); + mVideoEditor1b.removeMediaItem("m1"); + mVideoEditor1b.release(); + getAfterMemory_updateLog(loggingInfo, true, i); + } + getAfterMemory_updateLog(loggingInfo, true, i); + } + + /** + * To stress test : Multiple Export + * + * @throws Exception + */ + // TODO : remove TC_STR_010 + @LargeTest + public void testStressMultipleExport() throws Exception { + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String VideoItemFileName1 = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_800kbps_1_17.mp4"; + final String VideoItemFileName2 = INPUT_FILE_PATH + + "H264_BP_800x480_15fps_512kbps_1_17.mp4"; + final String[] loggingInfo = new String[1]; + final String outFilename = mVideoEditorHelper.createRandomFile( + mVideoEditor.getPath() + "/") + ".3gp"; + int i = 0; + writeTestCaseHeader("testStressMultipleExport"); + getBeginMemory(); + final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor, + "m1", VideoItemFileName1, renderingMode); + mVideoEditor.addMediaItem(mediaItem1); + mediaItem1.setExtractBoundaries(0, 10000); + + final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor, + "m2", VideoItemFileName2, renderingMode); + mVideoEditor.addMediaItem(mediaItem2); + mediaItem2.setExtractBoundaries(0, 15000); + + for ( i = 0; i < 50; i++) { + if(i%4 ==0){ + final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3; + mVideoEditor.setAspectRatio(aspectRatio); + mVideoEditor.export(outFilename, MediaProperties.HEIGHT_480, + MediaProperties.BITRATE_256K,MediaProperties.ACODEC_AAC_LC, + MediaProperties.VCODEC_H263, + new ExportProgressListener() { + public void onProgress(VideoEditor ve, String outFileName, + int progress) { + } + }); + } + if(i%4 ==1){ + final int aspectRatio = MediaProperties.ASPECT_RATIO_5_3; + mVideoEditor.setAspectRatio(aspectRatio); + mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144, + MediaProperties.BITRATE_384K,MediaProperties.ACODEC_AAC_LC, + MediaProperties.VCODEC_MPEG4, + new ExportProgressListener() { + public void onProgress(VideoEditor ve, String outFileName, + int progress) { + } + }); + } + if(i%4 ==2){ + final int aspectRatio = MediaProperties.ASPECT_RATIO_11_9; + mVideoEditor.setAspectRatio(aspectRatio); + mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144, + MediaProperties.BITRATE_512K,MediaProperties.ACODEC_AAC_LC, + MediaProperties.VCODEC_H264BP, + new ExportProgressListener() { + public void onProgress(VideoEditor ve, String outFileName, + int progress) { + } + }); + } + if(i%4 ==3){ + final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2; + mVideoEditor.setAspectRatio(aspectRatio); + mVideoEditor.export(outFilename, MediaProperties.HEIGHT_480, + MediaProperties.BITRATE_800K,MediaProperties.ACODEC_AAC_LC, + MediaProperties.VCODEC_H264BP, + new ExportProgressListener() { + public void onProgress(VideoEditor ve, String outFileName, + int progress) { + } + }); + } + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, false, i); + } + } + getAfterMemory_updateLog(loggingInfo, false, i); + + /** Remove items and check for memory leak if any */ + getBeginMemory(); + mVideoEditor.removeMediaItem("m2"); + mVideoEditor.removeMediaItem("m1"); + + getAfterMemory_updateLog(loggingInfo, true, i); + } + + /** + * To stress test Media Item,Overlays,Transitions and Ken Burn + * + * @throws Exception + */ + // TODO : remove TC_STR_011 + @LargeTest + public void testStressOverlayTransKenBurn() throws Exception { + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String VideoItemFileName1 = INPUT_FILE_PATH + + "H264_BP_640x480_30fps_256kbps_1_17.mp4"; + final String ImageItemFileName2 = INPUT_FILE_PATH + + "IMG_640x480.jpg"; + final String OverlayFile3 = INPUT_FILE_PATH + + "IMG_640x480_Overlay1.png"; + final String audioFilename4 = INPUT_FILE_PATH + + "AACLC_44.1kHz_256kbps_s_1_17.mp4"; + int i = 0; + final String[] loggingInfo = new String[1]; + writeTestCaseHeader("testStressOverlayTransKenBurn"); + getBeginMemory(); + for ( i = 0; i < 10; i++) { + final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor, + "m1" + i, VideoItemFileName1, renderingMode); + mVideoEditor.addMediaItem(mediaItem1); + mediaItem1.setExtractBoundaries(0, 10000); + + final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor, + "m2" + i, ImageItemFileName2, 10000, renderingMode); + mVideoEditor.addMediaItem(mediaItem2); + + final EffectColor effectColor1 = + mVideoEditorHelper.createEffectItem(mediaItem1, "effect1"+i, + (mediaItem1.getDuration() - 4000), 4000, + EffectColor.TYPE_SEPIA, 0); + mediaItem1.addEffect(effectColor1); + + final TransitionCrossfade tranCrossfade = + new TransitionCrossfade("transCF" + i, mediaItem1, + mediaItem2, 4000, Transition.BEHAVIOR_MIDDLE_FAST); + mVideoEditor.addTransition(tranCrossfade); + + final Bitmap mBitmap = mVideoEditorHelper.getBitmap(OverlayFile3, + 640, 480); + final OverlayFrame overlayFrame = + mVideoEditorHelper.createOverlay(mediaItem1, "overlay" + i, + mBitmap, 1000, 5000); + mediaItem1.addOverlay(overlayFrame); + + final Rect startRect = new Rect((mediaItem2.getHeight() / 3), + (mediaItem2.getWidth() / 3), (mediaItem2.getHeight() / 2), + (mediaItem2.getWidth() / 2)); + final Rect endRect = new Rect(0, 0, mediaItem2.getWidth(), + mediaItem2.getHeight()); + + final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns( + mediaItem2, "KBOnM2" + i, startRect, endRect, 500, + (mediaItem2.getDuration()-500)); + mediaItem2.addEffect(kbEffectOnMediaItem); + + if(i == 5) { + final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor, + "Audio Track1", audioFilename4); + mVideoEditor.addAudioTrack(audioTrack1); + } + getAfterMemory_updateLog(loggingInfo, false, i); + } + getAfterMemory_updateLog(loggingInfo, false, i); + + /** Remove items and check for memory leak if any */ + getBeginMemory(); + for ( i = 0; i < 10; i++) { + MediaImageItem m2 = (MediaImageItem)mVideoEditor.getMediaItem("m2"+i); + MediaVideoItem m1 = (MediaVideoItem)mVideoEditor.getMediaItem("m1"+i); + m2.removeEffect("KBOnM2" + i); + m1.removeOverlay("overlay" + i); + mVideoEditor.removeTransition("transCF" + i); + m1.removeEffect("effect1" + i); + mVideoEditor.removeMediaItem("m2" + i); + mVideoEditor.removeMediaItem("m1" + i); + if(i == 5) { + mVideoEditor.removeAudioTrack("Audio Track1"); + } + getAfterMemory_updateLog(loggingInfo, true, i); + } + getAfterMemory_updateLog(loggingInfo, true, i); + } + + /** + * To test the performance : With an audio track with Video + * + * @throws Exception + */ + // TODO : remove TC_STR_012 + @LargeTest + public void testStressAudioTrackVideo() throws Exception { + final String videoItemFileName1 = INPUT_FILE_PATH + + "H264_BP_1080x720_30fps_800kbps_1_17.mp4"; + final String audioFilename1 = INPUT_FILE_PATH + + "AACLC_44.1kHz_256kbps_s_1_17.mp4"; + final String audioFilename2 = INPUT_FILE_PATH + + "AMRNB_8KHz_12.2Kbps_m_1_17.3gp"; + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final int audioVolume = 50; + final String[] loggingInfo = new String[1]; + int i = 1; + writeTestCaseHeader("testStressAudioTrackVideo"); + getBeginMemory(); + final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor, + "mediaItem1", videoItemFileName1, renderingMode); + mVideoEditor.addMediaItem(mediaVideoItem); + + final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor, + "Audio Track1", audioFilename1); + audioTrack1.disableDucking(); + audioTrack1.setVolume(audioVolume); + mVideoEditor.addAudioTrack(audioTrack1); + + mVideoEditor.generatePreview(new MediaProcessingProgressListener() { + public void onProgress(Object item, int action, int progress) { + } + }); + + mVideoEditor.removeAudioTrack("Audio Track1"); + + final AudioTrack audioTrack2 = new AudioTrack(mVideoEditor, + "Audio Track2", audioFilename2); + audioTrack2.enableLoop(); + + mVideoEditor.generatePreview(new MediaProcessingProgressListener() { + public void onProgress(Object item, int action, int progress) { + } + }); + getAfterMemory_updateLog(loggingInfo, false, i); + + /** Remove items and check for memory leak if any */ + getBeginMemory(); + mVideoEditor.removeMediaItem("mediaItem1"); + + getAfterMemory_updateLog(loggingInfo, true, i); + } + + /** + * To Test Stress : Story Board creation with out preview or export + * + * @throws Exception + */ + // TODO : remove TC_STR_013 + @LargeTest + public void testStressStoryBoard() throws Exception { + final String videoItemFileName1 = INPUT_FILE_PATH + + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_161kbps_s_0_26.mp4"; + final String videoItemFileName2 = INPUT_FILE_PATH + + "MPEG4_SP_854x480_15fps_256kbps_AACLC_16khz_48kbps_s_0_26.mp4"; + final String videoItemFileName3= INPUT_FILE_PATH + + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4"; + final String imageItemFileName4 = INPUT_FILE_PATH + + "IMG_1600x1200.jpg"; + final String imageItemFileName5 = INPUT_FILE_PATH + + "IMG_176x144.jpg"; + final String audioFilename6 = INPUT_FILE_PATH + + "AMRNB_8KHz_12.2Kbps_m_1_17.3gp"; + final String audioFilename7 = INPUT_FILE_PATH + + "AACLC_44.1kHz_256kbps_s_1_17.mp4"; + + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final int audioVolume = 50; + final String[] loggingInfo = new String[1]; + int i = 1; + + writeTestCaseHeader("testStressStoryBoard"); + getBeginMemory(); + final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor, + "m1", videoItemFileName1, renderingMode); + mediaItem1.setExtractBoundaries(0, 10000); + mVideoEditor.addMediaItem(mediaItem1); + + final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor, + "m2", videoItemFileName2, renderingMode); + mediaItem2.setExtractBoundaries(mediaItem2.getDuration()/4, + mediaItem2.getDuration()/2); + mVideoEditor.addMediaItem(mediaItem2); + + final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor, + "m3", videoItemFileName3, renderingMode); + mediaItem3.setExtractBoundaries(mediaItem3.getDuration()/2, + mediaItem3.getDuration()); + mVideoEditor.addMediaItem(mediaItem3); + + final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor, + "m4", imageItemFileName4, 5000, renderingMode); + mVideoEditor.addMediaItem(mediaItem4); + + final MediaImageItem mediaItem5 = new MediaImageItem(mVideoEditor, + "m5", imageItemFileName5, 5000, renderingMode); + mVideoEditor.addMediaItem(mediaItem5); + + final TransitionCrossfade tranCrossfade = + new TransitionCrossfade("transCF", mediaItem2, mediaItem3, 2500, + Transition.BEHAVIOR_MIDDLE_FAST); + mVideoEditor.addTransition(tranCrossfade); + + final TransitionCrossfade tranCrossfade1 = + new TransitionCrossfade("transCF1", mediaItem3, mediaItem4, 2500, + Transition.BEHAVIOR_MIDDLE_FAST); + mVideoEditor.addTransition(tranCrossfade1); + + final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor, + "Audio Track1", audioFilename6); + mVideoEditor.addAudioTrack(audioTrack1); + + mVideoEditor.removeAudioTrack("Audio Track1"); + final AudioTrack audioTrack2 = new AudioTrack(mVideoEditor, + "Audio Track2", audioFilename7); + mVideoEditor.addAudioTrack(audioTrack2); + audioTrack2.enableLoop(); + getAfterMemory_updateLog(loggingInfo, false, i); + + /** Remove items and check for memory leak if any */ + getBeginMemory(); + mVideoEditor.removeAudioTrack("Audio Track2"); + mVideoEditor.removeTransition("transCF"); + mVideoEditor.removeTransition("transCF1"); + mVideoEditor.removeMediaItem("m5"); + mVideoEditor.removeMediaItem("m4"); + mVideoEditor.removeMediaItem("m3"); + mVideoEditor.removeMediaItem("m2"); + mVideoEditor.removeMediaItem("m1"); + + getAfterMemory_updateLog(loggingInfo, true, i); + } + + /** + * To test the performance : With an audio track Only + * + * @throws Exception + */ + // TODO : remove TC_STR_014 + @LargeTest + public void testStressAudioTrackOnly() throws Exception { + + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String AudioItemFileName1 = INPUT_FILE_PATH + + "AACLC_44.1kHz_256kbps_s_1_17.mp4"; + final String[] loggingInfo = new String[1]; + int i = 0; + writeTestCaseHeader("testStressAudioTrackOnly"); + getBeginMemory(); + for ( i = 0; i < 50; i++) { + final AudioTrack mediaItem1 = new AudioTrack(mVideoEditor, + "m1" + i, AudioItemFileName1); + mVideoEditor.addAudioTrack(mediaItem1); + mediaItem1.enableLoop(); + mVideoEditor.removeAudioTrack("m1" + i); + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, false, i); + } + } + getAfterMemory_updateLog(loggingInfo, false, i); + } + + /** + * This method will test thumbnail list extraction in a loop = 200 for Image + * Item + * + * @throws Exception + */ + // TODO : remove TC_STR_016 -- New Test Case + @LargeTest + public void testStressThumbnailImageItem() throws Exception { + final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg"; + final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER; + final String[] loggingInfo = new String[1]; + int i = 0; + final MediaImageItem mediaImageItem = new MediaImageItem(mVideoEditor, + "m1", imageItemFileName, 5000, renderingMode); + writeTestCaseHeader("testStressThumbnailImageItem"); + getBeginMemory(); + for ( i = 0; i < 50; i++) { + if (i % 4 == 0) { + final Bitmap[] thumbNails = mediaImageItem.getThumbnailList( + mediaImageItem.getWidth() / 2 , + mediaImageItem.getHeight() / 2, i, 5000, 2); + // Recycle this Bitmap array + for (int i1 = 0; i1 < thumbNails.length; i1++) { + thumbNails[i1].recycle(); + } + } + if (i % 4 == 1) { + final Bitmap[] thumbNails = mediaImageItem.getThumbnailList( + mediaImageItem.getWidth() / 2, + mediaImageItem.getHeight() * 3, i, 5000, 2); + // Recycle this Bitmap array + for (int i1 = 0; i1 < thumbNails.length; i1++) { + thumbNails[i1].recycle(); + } + } + if (i % 4 == 2) { + final Bitmap[] thumbNails = mediaImageItem.getThumbnailList( + mediaImageItem.getWidth() * 2, + mediaImageItem.getHeight() / 3, i, 5000, 2); + // Recycle this Bitmap array + for (int i1 = 0; i1 < thumbNails.length; i1++) { + thumbNails[i1].recycle(); + } + } + if (i % 4 == 3) { + final Bitmap[] thumbNails = mediaImageItem.getThumbnailList( + mediaImageItem.getWidth(), + mediaImageItem.getHeight(), i, 5000, 2); + // Recycle this Bitmap array + for (int i1 = 0; i1 < thumbNails.length; i1++) { + thumbNails[i1].recycle(); + } + } + if (i % 10 == 0) { + getAfterMemory_updateLog(loggingInfo, false, i); + } + } + getAfterMemory_updateLog(loggingInfo, false, i); + } +} diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 156391e2aac9..84588b78c2a8 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -2438,6 +2438,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { return mKeyguardMediator.isShowingAndNotHidden(); } + + /** {@inheritDoc} */ + public boolean isKeyguardLocked() { + return keyguardOn(); + } + + /** {@inheritDoc} */ + public boolean isKeyguardSecure() { + return mKeyguardMediator.isSecure(); + } + /** {@inheritDoc} */ public boolean inKeyguardRestrictedKeyInputMode() { return mKeyguardMediator.isInputRestricted(); @@ -2463,6 +2474,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { public int rotationForOrientationLw(int orientation, int lastRotation, boolean displayEnabled) { + if (false) { + Slog.v(TAG, "rotationForOrientationLw(orient=" + + orientation + ", last=" + lastRotation + + "); user=" + mUserRotation + " " + + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) + ? "USER_ROTATION_LOCKED" : "") + ); + } + if (mPortraitRotation < 0) { // Initialize the rotation angles for each orientation once. Display d = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) @@ -2581,15 +2601,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { // User rotation: to be used when all else fails in assigning an orientation to the device public void setUserRotationMode(int mode, int rot) { ContentResolver res = mContext.getContentResolver(); - mUserRotationMode = mode; + + // mUserRotationMode and mUserRotation will be assigned by the content observer if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) { - mUserRotation = rot; - Settings.System.putInt(res, - Settings.System.ACCELEROMETER_ROTATION, - 0); Settings.System.putInt(res, Settings.System.USER_ROTATION, rot); + Settings.System.putInt(res, + Settings.System.ACCELEROMETER_ROTATION, + 0); } else { Settings.System.putInt(res, Settings.System.ACCELEROMETER_ROTATION, @@ -2907,7 +2927,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); pw.print(" mUserRotation="); pw.print(mUserRotation); - pw.print("mAllowAllRotations="); pw.println(mAllowAllRotations); + pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations); pw.print(prefix); pw.print("mAccelerometerDefault="); pw.print(mAccelerometerDefault); pw.print(" mCurrentAppOrientation="); pw.println(mCurrentAppOrientation); pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); diff --git a/services/java/com/android/server/UsbService.java b/services/java/com/android/server/UsbService.java index af4c425c24e7..1bc203ef0a5b 100644 --- a/services/java/com/android/server/UsbService.java +++ b/services/java/com/android/server/UsbService.java @@ -44,7 +44,11 @@ import java.util.ArrayList; import java.util.HashMap; /** - * <p>UsbService monitors for changes to USB state. + * UsbService monitors for changes to USB state. + * This includes code for both USB host support (where the android device is the host) + * as well as USB device support (android device is connected to a USB host). + * Accessory mode is a special case of USB device mode, where the android device is + * connected to a USB host that supports the android accessory protocol. */ class UsbService extends IUsbManager.Stub { private static final String TAG = UsbService.class.getSimpleName(); @@ -63,7 +67,9 @@ class UsbService extends IUsbManager.Stub { private static final String USB_COMPOSITE_CLASS_PATH = "/sys/class/usb_composite"; - private static final int MSG_UPDATE = 0; + private static final int MSG_UPDATE_STATE = 0; + private static final int MSG_FUNCTION_ENABLED = 1; + private static final int MSG_FUNCTION_DISABLED = 2; // Delay for debouncing USB disconnects. // We often get rapid connect/disconnect events when enabling USB functions, @@ -79,7 +85,6 @@ class UsbService extends IUsbManager.Stub { private int mLastConfiguration = -1; // lists of enabled and disabled USB functions (for USB device mode) - // synchronize on mEnabledFunctions when using either of these lists private final ArrayList<String> mEnabledFunctions = new ArrayList<String>(); private final ArrayList<String> mDisabledFunctions = new ArrayList<String>(); @@ -90,26 +95,48 @@ class UsbService extends IUsbManager.Stub { private final String[] mHostBlacklist; private boolean mSystemReady; + private UsbAccessory mCurrentAccessory; + // functions to restore after exiting accessory mode + private final ArrayList<String> mAccessoryRestoreFunctions = new ArrayList<String>(); private final Context mContext; - - private final void functionEnabled(String function, boolean enabled) { - synchronized (mEnabledFunctions) { - if (enabled) { - if (!mEnabledFunctions.contains(function)) { - mEnabledFunctions.add(function); - } - mDisabledFunctions.remove(function); - } else { - if (!mDisabledFunctions.contains(function)) { - mDisabledFunctions.add(function); + private final Object mLock = new Object(); + + /* + * Handles USB function enable/disable events (device mode) + */ + private final void functionEnabledLocked(String function, boolean enabled) { + boolean enteringAccessoryMode = + (enabled && UsbManager.USB_FUNCTION_ACCESSORY.equals(function)); + + if (enteringAccessoryMode) { + // keep a list of functions to reenable after exiting accessory mode + mAccessoryRestoreFunctions.clear(); + int count = mEnabledFunctions.size(); + for (int i = 0; i < count; i++) { + String f = mEnabledFunctions.get(i); + // RNDIS should not be restored and adb is handled automatically + if (!UsbManager.USB_FUNCTION_RNDIS.equals(f) && + !UsbManager.USB_FUNCTION_ADB.equals(f) && + !UsbManager.USB_FUNCTION_ACCESSORY.equals(f)) { + mAccessoryRestoreFunctions.add(f); } - mEnabledFunctions.remove(function); } } + if (enabled) { + if (!mEnabledFunctions.contains(function)) { + mEnabledFunctions.add(function); + } + mDisabledFunctions.remove(function); + } else { + if (!mDisabledFunctions.contains(function)) { + mDisabledFunctions.add(function); + } + mEnabledFunctions.remove(function); + } - if (enabled && UsbManager.USB_FUNCTION_ACCESSORY.equals(function)) { + if (enteringAccessoryMode) { String[] strings = nativeGetAccessoryStrings(); if (strings != null) { Log.d(TAG, "entering USB accessory mode"); @@ -136,6 +163,9 @@ class UsbService extends IUsbManager.Stub { } } + /* + * Listens for uevent messages from the kernel to monitor the USB state (device mode) + */ private final UEventObserver mUEventObserver = new UEventObserver() { @Override public void onUEvent(UEventObserver.UEvent event) { @@ -143,7 +173,7 @@ class UsbService extends IUsbManager.Stub { Slog.v(TAG, "USB UEVENT: " + event.toString()); } - synchronized (this) { + synchronized (mLock) { String name = event.get("SWITCH_NAME"); String state = event.get("SWITCH_STATE"); if (name != null && state != null) { @@ -172,8 +202,11 @@ class UsbService extends IUsbManager.Stub { if (function != null && enabledStr != null) { // Note: we do not broadcast a change when a function is enabled or disabled. // We just record the state change for the next broadcast. - boolean enabled = "1".equals(enabledStr); - functionEnabled(function, enabled); + int what = ("1".equals(enabledStr) ? + MSG_FUNCTION_ENABLED : MSG_FUNCTION_DISABLED); + Message msg = Message.obtain(mHandler, what); + msg.obj = function; + mHandler.sendMessage(msg); } } } @@ -197,6 +230,7 @@ class UsbService extends IUsbManager.Stub { private final void init() { char[] buffer = new char[1024]; + // Read initial USB state (device mode) mConfiguration = -1; try { FileReader file = new FileReader(USB_CONNECTED_PATH); @@ -217,21 +251,20 @@ class UsbService extends IUsbManager.Stub { if (mConfiguration < 0) return; + // Read initial list of enabled and disabled functions (device mode) try { - synchronized (mEnabledFunctions) { - File[] files = new File(USB_COMPOSITE_CLASS_PATH).listFiles(); - for (int i = 0; i < files.length; i++) { - File file = new File(files[i], "enable"); - FileReader reader = new FileReader(file); - int len = reader.read(buffer, 0, 1024); - reader.close(); - int value = Integer.valueOf((new String(buffer, 0, len)).trim()); - String functionName = files[i].getName(); - if (value == 1) { - mEnabledFunctions.add(functionName); - } else { - mDisabledFunctions.add(functionName); - } + File[] files = new File(USB_COMPOSITE_CLASS_PATH).listFiles(); + for (int i = 0; i < files.length; i++) { + File file = new File(files[i], "enable"); + FileReader reader = new FileReader(file); + int len = reader.read(buffer, 0, 1024); + reader.close(); + int value = Integer.valueOf((new String(buffer, 0, len)).trim()); + String functionName = files[i].getName(); + if (value == 1) { + mEnabledFunctions.add(functionName); + } else { + mDisabledFunctions.add(functionName); } } } catch (FileNotFoundException e) { @@ -251,6 +284,7 @@ class UsbService extends IUsbManager.Stub { return false; } + /* returns true if the USB device should not be accessible by applications (host mode) */ private boolean isBlackListed(int clazz, int subClass, int protocol) { // blacklist hubs if (clazz == UsbConstants.USB_CLASS_HUB) return true; @@ -264,7 +298,7 @@ class UsbService extends IUsbManager.Stub { return false; } - // called from JNI in monitorUsbHostBus() + /* Called from JNI in monitorUsbHostBus() to report new USB devices (host mode) */ private void usbDeviceAdded(String deviceName, int vendorID, int productID, int deviceClass, int deviceSubclass, int deviceProtocol, /* array of quintuples containing id, class, subclass, protocol @@ -279,7 +313,7 @@ class UsbService extends IUsbManager.Stub { return; } - synchronized (mDevices) { + synchronized (mLock) { if (mDevices.get(deviceName) != null) { Log.w(TAG, "device already on mDevices list: " + deviceName); return; @@ -338,9 +372,9 @@ class UsbService extends IUsbManager.Stub { } } - // called from JNI in monitorUsbHostBus() + /* Called from JNI in monitorUsbHostBus to report USB device removal (host mode) */ private void usbDeviceRemoved(String deviceName) { - synchronized (mDevices) { + synchronized (mLock) { UsbDevice device = mDevices.remove(deviceName); if (device != null) { Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED); @@ -363,7 +397,7 @@ class UsbService extends IUsbManager.Stub { } void systemReady() { - synchronized (this) { + synchronized (mLock) { if (mContext.getResources().getBoolean( com.android.internal.R.bool.config_hasUsbHostSupport)) { // start monitoring for connected USB devices @@ -375,21 +409,27 @@ class UsbService extends IUsbManager.Stub { } } + /* + * Sends a message to update the USB connected and configured state (device mode). + * If delayed is true, then we add a small delay in sending the message to debounce + * the USB connection when enabling USB tethering. + */ private final void update(boolean delayed) { - mHandler.removeMessages(MSG_UPDATE); - mHandler.sendEmptyMessageDelayed(MSG_UPDATE, delayed ? UPDATE_DELAY : 0); + mHandler.removeMessages(MSG_UPDATE_STATE); + mHandler.sendEmptyMessageDelayed(MSG_UPDATE_STATE, delayed ? UPDATE_DELAY : 0); } - /* Returns a list of all currently attached USB devices */ + /* Returns a list of all currently attached USB devices (host mdoe) */ public void getDeviceList(Bundle devices) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null); - synchronized (mDevices) { + synchronized (mLock) { for (String name : mDevices.keySet()) { devices.putParcelable(name, mDevices.get(name)); } } } + /* Opens the specified USB device (host mode) */ public ParcelFileDescriptor openDevice(String deviceName) { if (isBlackListed(deviceName)) { throw new SecurityException("USB device is on a restricted bus"); @@ -403,34 +443,37 @@ class UsbService extends IUsbManager.Stub { return nativeOpenDevice(deviceName); } + /* returns the currently attached USB accessory (device mode) */ public UsbAccessory getCurrentAccessory() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null); return mCurrentAccessory; } + /* opens the currently attached USB accessory (device mode) */ public ParcelFileDescriptor openAccessory() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null); return nativeOpenAccessory(); } + /* + * This handler is for deferred handling of events related to device mode and accessories. + */ private final Handler mHandler = new Handler() { - private void addEnabledFunctions(Intent intent) { - synchronized (mEnabledFunctions) { + private void addEnabledFunctionsLocked(Intent intent) { // include state of all USB functions in our extras - for (int i = 0; i < mEnabledFunctions.size(); i++) { - intent.putExtra(mEnabledFunctions.get(i), UsbManager.USB_FUNCTION_ENABLED); - } - for (int i = 0; i < mDisabledFunctions.size(); i++) { - intent.putExtra(mDisabledFunctions.get(i), UsbManager.USB_FUNCTION_DISABLED); - } + for (int i = 0; i < mEnabledFunctions.size(); i++) { + intent.putExtra(mEnabledFunctions.get(i), UsbManager.USB_FUNCTION_ENABLED); + } + for (int i = 0; i < mDisabledFunctions.size(); i++) { + intent.putExtra(mDisabledFunctions.get(i), UsbManager.USB_FUNCTION_DISABLED); } } @Override public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_UPDATE: - synchronized (this) { + synchronized (mLock) { + switch (msg.what) { + case MSG_UPDATE_STATE: if (mConnected != mLastConnected || mConfiguration != mLastConfiguration) { if (mConnected == 0 && mCurrentAccessory != null) { // turn off accessory mode when we are disconnected @@ -438,6 +481,14 @@ class UsbService extends IUsbManager.Stub { UsbManager.USB_FUNCTION_ACCESSORY, false)) { Log.d(TAG, "exited USB accessory mode"); + // restore previously enabled functions + for (String function : mAccessoryRestoreFunctions) { + if (UsbManager.setFunctionEnabled(function, true)) { + Log.e(TAG, "could not reenable function " + function); + } + } + mAccessoryRestoreFunctions.clear(); + Intent intent = new Intent( UsbManager.ACTION_USB_ACCESSORY_DETACHED); intent.putExtra(UsbManager.EXTRA_ACCESSORY, mCurrentAccessory); @@ -468,17 +519,23 @@ class UsbService extends IUsbManager.Stub { intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); intent.putExtra(UsbManager.USB_CONNECTED, mConnected != 0); intent.putExtra(UsbManager.USB_CONFIGURATION, mConfiguration); - addEnabledFunctions(intent); + addEnabledFunctionsLocked(intent); mContext.sendStickyBroadcast(intent); } - } - break; + break; + case MSG_FUNCTION_ENABLED: + case MSG_FUNCTION_DISABLED: + functionEnabledLocked((String)msg.obj, msg.what == MSG_FUNCTION_ENABLED); + break; + } } } }; + // host support private native void monitorUsbHostBus(); private native ParcelFileDescriptor nativeOpenDevice(String deviceName); + // accessory support private native String[] nativeGetAccessoryStrings(); private native ParcelFileDescriptor nativeOpenAccessory(); } diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java index 34f36184ba63..b1833c45d9f3 100644 --- a/services/java/com/android/server/wm/InputMonitor.java +++ b/services/java/com/android/server/wm/InputMonitor.java @@ -1,6 +1,19 @@ -/** - * +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ + package com.android.server.wm; import android.graphics.Rect; diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index a598ce9ebcd6..b7cc3243255a 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -4410,6 +4410,14 @@ public class WindowManagerService extends IWindowManager.Stub return mPolicy.inKeyguardRestrictedKeyInputMode(); } + public boolean isKeyguardLocked() { + return mPolicy.isKeyguardLocked(); + } + + public boolean isKeyguardSecure() { + return mPolicy.isKeyguardSecure(); + } + public void closeSystemDialogs(String reason) { synchronized(mWindowMap) { for (int i=mWindows.size()-1; i>=0; i--) { @@ -4822,21 +4830,25 @@ public class WindowManagerService extends IWindowManager.Stub public void freezeRotation() { if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, - "setRotation()")) { + "freezeRotation()")) { throw new SecurityException("Requires SET_ORIENTATION permission"); } + if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); + mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, mRotation); setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0); } public void thawRotation() { if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, - "setRotation()")) { + "thawRotation()")) { throw new SecurityException("Requires SET_ORIENTATION permission"); } - mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 0); + if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); + + mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 777); // rot not used setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0); } |