diff options
201 files changed, 3384 insertions, 3045 deletions
diff --git a/api/current.txt b/api/current.txt index e0e7565433e8..1b449c86fe84 100644 --- a/api/current.txt +++ b/api/current.txt @@ -607,7 +607,7 @@ package android { field public static final int layout_centerInParent = 16843151; // 0x101018f field public static final int layout_centerVertical = 16843153; // 0x1010191 field public static final int layout_column = 16843084; // 0x101014c - field public static final int layout_columnFlexibility = 16843644; // 0x101037c + field public static final deprecated int layout_columnFlexibility = 16843644; // 0x101037c field public static final int layout_columnSpan = 16843643; // 0x101037b field public static final int layout_gravity = 16842931; // 0x10100b3 field public static final int layout_height = 16842997; // 0x10100f5 @@ -617,7 +617,7 @@ package android { field public static final int layout_marginRight = 16843001; // 0x10100f9 field public static final int layout_marginTop = 16843000; // 0x10100f8 field public static final int layout_row = 16843640; // 0x1010378 - field public static final int layout_rowFlexibility = 16843642; // 0x101037a + field public static final deprecated int layout_rowFlexibility = 16843642; // 0x101037a field public static final int layout_rowSpan = 16843641; // 0x1010379 field public static final int layout_scale = 16843155; // 0x1010193 field public static final int layout_span = 16843085; // 0x101014d @@ -1828,6 +1828,7 @@ package android.accessibilityservice { method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; field public static final int DEFAULT = 1; // 0x1 + field public static final int FEEDBACK_ALL_MASK = -1; // 0xffffffff field public static final int FEEDBACK_AUDIBLE = 4; // 0x4 field public static final int FEEDBACK_GENERIC = 16; // 0x10 field public static final int FEEDBACK_HAPTIC = 2; // 0x2 @@ -16060,6 +16061,7 @@ package android.provider { field public static final java.lang.String ATTACH_IMAGE = "com.android.contacts.action.ATTACH_IMAGE"; field public static final java.lang.String EXTRA_CREATE_DESCRIPTION = "com.android.contacts.action.CREATE_DESCRIPTION"; field public static final java.lang.String EXTRA_FORCE_CREATE = "com.android.contacts.action.FORCE_CREATE"; + field public static final java.lang.String INVITE_CONTACT = "com.android.contacts.action.INVITE_CONTACT"; field public static final java.lang.String SEARCH_SUGGESTION_CLICKED = "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED"; field public static final java.lang.String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED = "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED"; field public static final java.lang.String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED = "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED"; @@ -16710,7 +16712,7 @@ package android.provider { field public static final java.lang.String SELECTED_INPUT_METHOD_SUBTYPE = "selected_input_method_subtype"; field public static final java.lang.String SETTINGS_CLASSNAME = "settings_classname"; field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version"; - field public static final java.lang.String TOUCH_EXPLORATION_REQUESTED = "touch_exploration_requested"; + field public static final java.lang.String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled"; field public static final java.lang.String TTS_DEFAULT_COUNTRY = "tts_default_country"; field public static final java.lang.String TTS_DEFAULT_LANG = "tts_default_lang"; field public static final java.lang.String TTS_DEFAULT_PITCH = "tts_default_pitch"; @@ -22232,6 +22234,7 @@ package android.view { method public final android.view.View findViewWithTag(java.lang.Object); method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence); method protected boolean fitSystemWindows(android.graphics.Rect); + method public boolean fitsSystemWindows(); method public android.view.View focusSearch(int); method public void forceLayout(); method public float getAlpha(); @@ -22473,6 +22476,7 @@ package android.view { method public void setEnabled(boolean); method public void setFadingEdgeLength(int); method public void setFilterTouchesWhenObscured(boolean); + method public void setFitsSystemWindows(boolean); method public void setFocusable(boolean); method public void setFocusableInTouchMode(boolean); method public void setHapticFeedbackEnabled(boolean); @@ -25435,15 +25439,14 @@ package android.widget { method public void setRowCount(int); method public void setRowOrderPreserved(boolean); method public void setUseDefaultMargins(boolean); - method public static android.widget.GridLayout.Spec spec(int, int, android.widget.GridLayout.Alignment, int); - method public static android.widget.GridLayout.Spec spec(int, android.widget.GridLayout.Alignment, int); method public static android.widget.GridLayout.Spec spec(int, int, android.widget.GridLayout.Alignment); method public static android.widget.GridLayout.Spec spec(int, android.widget.GridLayout.Alignment); + method public static android.widget.GridLayout.Spec spec(int, int); + method public static android.widget.GridLayout.Spec spec(int); field public static final int ALIGN_BOUNDS = 0; // 0x0 field public static final int ALIGN_MARGINS = 1; // 0x1 field public static final android.widget.GridLayout.Alignment BASELINE; field public static final android.widget.GridLayout.Alignment BOTTOM; - field public static final int CAN_STRETCH = 2; // 0x2 field public static final android.widget.GridLayout.Alignment CENTER; field public static final android.widget.GridLayout.Alignment FILL; field public static final int HORIZONTAL = 0; // 0x0 @@ -26198,7 +26201,7 @@ package android.widget { method public int timePassed(); } - public class SearchView extends android.widget.LinearLayout { + public class SearchView extends android.widget.LinearLayout implements android.view.CollapsibleActionView { ctor public SearchView(android.content.Context); ctor public SearchView(android.content.Context, android.util.AttributeSet); method public java.lang.CharSequence getQuery(); @@ -26207,6 +26210,8 @@ package android.widget { method public boolean isIconified(); method public boolean isQueryRefinementEnabled(); method public boolean isSubmitButtonEnabled(); + method public void onActionViewCollapsed(); + method public void onActionViewExpanded(); method public void setIconified(boolean); method public void setIconifiedByDefault(boolean); method public void setMaxWidth(int); diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java index a09607a7f9ad..41a3eacaafc6 100644 --- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java @@ -75,6 +75,17 @@ public class AccessibilityServiceInfo implements Parcelable { public static final int FEEDBACK_GENERIC = 0x0000010; /** + * Mask for all feedback types. + * + * @see #FEEDBACK_SPOKEN + * @see #FEEDBACK_HAPTIC + * @see #FEEDBACK_AUDIBLE + * @see #FEEDBACK_VISUAL + * @see #FEEDBACK_GENERIC + */ + public static final int FEEDBACK_ALL_MASK = 0xFFFFFFFF; + + /** * If an {@link AccessibilityService} is the default for a given type. * Default service is invoked only if no package specific one exists. In case of * more than one package specific service only the earlier registered is notified. diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index aeb16f4756a4..8d03ac70f802 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -1593,10 +1593,10 @@ public class Activity extends ContextThemeWrapper //Log.v(TAG, "invalidateFragmentIndex: index=" + index); if (mAllLoaderManagers != null) { LoaderManagerImpl lm = mAllLoaderManagers.get(index); - if (lm != null) { + if (lm != null && !lm.mRetaining) { lm.doDestroy(); + mAllLoaderManagers.remove(index); } - mAllLoaderManagers.remove(index); } } diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java index e5a7980b0c8c..93330a798901 100644 --- a/core/java/android/app/BackStackRecord.java +++ b/core/java/android/app/BackStackRecord.java @@ -224,6 +224,12 @@ final class BackStackRecord extends FragmentTransaction implements writer.print(" mExitAnim=#"); writer.println(Integer.toHexString(mExitAnim)); } + if (mPopEnterAnim != 0 || mPopExitAnim !=0) { + writer.print(prefix); writer.print("mPopEnterAnim=#"); + writer.print(Integer.toHexString(mPopEnterAnim)); + writer.print(" mPopExitAnim=#"); + writer.println(Integer.toHexString(mPopExitAnim)); + } if (mBreadCrumbTitleRes != 0 || mBreadCrumbTitleText != null) { writer.print(prefix); writer.print("mBreadCrumbTitleRes=#"); writer.print(Integer.toHexString(mBreadCrumbTitleRes)); @@ -248,13 +254,16 @@ final class BackStackRecord extends FragmentTransaction implements writer.print(innerPrefix); writer.print("cmd="); writer.print(op.cmd); writer.print(" fragment="); writer.println(op.fragment); if (op.enterAnim != 0 || op.exitAnim != 0) { - writer.print(prefix); writer.print("enterAnim="); writer.print(op.enterAnim); - writer.print(" exitAnim="); writer.println(op.exitAnim); + writer.print(prefix); writer.print("enterAnim=#"); + writer.print(Integer.toHexString(op.enterAnim)); + writer.print(" exitAnim=#"); + writer.println(Integer.toHexString(op.exitAnim)); } if (op.popEnterAnim != 0 || op.popExitAnim != 0) { - writer.print(prefix); - writer.print("popEnterAnim="); writer.print(op.popEnterAnim); - writer.print(" popExitAnim="); writer.println(op.popExitAnim); + writer.print(prefix); writer.print("popEnterAnim=#"); + writer.print(Integer.toHexString(op.popEnterAnim)); + writer.print(" popExitAnim=#"); + writer.println(Integer.toHexString(op.popExitAnim)); } if (op.removed != null && op.removed.size() > 0) { for (int i=0; i<op.removed.size(); i++) { @@ -695,11 +704,13 @@ final class BackStackRecord extends FragmentTransaction implements } break; case OP_DETACH: { Fragment f = op.fragment; + f.mNextAnim = op.popEnterAnim; mManager.attachFragment(f, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); } break; case OP_ATTACH: { Fragment f = op.fragment; + f.mNextAnim = op.popExitAnim; mManager.detachFragment(f, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); } break; diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java index d4e5cc13b1c1..b32664eefc3c 100644 --- a/core/java/android/content/pm/Signature.java +++ b/core/java/android/content/pm/Signature.java @@ -45,16 +45,23 @@ public class Signature implements Parcelable { * {@link #toChars} or {@link #toCharsString()}. */ public Signature(String text) { - final int N = text.length()/2; - byte[] sig = new byte[N]; - for (int i=0; i<N; i++) { - char c = text.charAt(i*2); - byte b = (byte)( - (c >= 'a' ? (c - 'a' + 10) : (c - '0'))<<4); - c = text.charAt(i*2 + 1); - b |= (byte)(c >= 'a' ? (c - 'a' + 10) : (c - '0')); - sig[i] = b; + final byte[] input = text.getBytes(); + final int N = input.length; + final byte[] sig = new byte[N / 2]; + int sigIndex = 0; + + for (int i = 0; i < N;) { + int b; + + final int hi = input[i++]; + b = (hi >= 'a' ? (hi - 'a' + 10) : (hi - '0')) << 4; + + final int lo = input[i++]; + b |= (lo >= 'a' ? (lo - 'a' + 10) : (lo - '0')) & 0x0F; + + sig[sigIndex++] = (byte) (b & 0xFF); } + mSignature = sig; } diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 76534ef3d8a7..e289fc15d0bb 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -20,6 +20,7 @@ import java.net.InetAddress; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.UnknownHostException; +import java.util.Collection; import android.util.Log; @@ -235,4 +236,18 @@ public class NetworkUtils { throw new IllegalArgumentException(e); } } + + /** + * Create a string array of host addresses from a collection of InetAddresses + * @param addrs a Collection of InetAddresses + * @return an array of Strings containing their host addresses + */ + public static String[] makeStrings(Collection<InetAddress> addrs) { + String[] result = new String[addrs.size()]; + int i = 0; + for (InetAddress addr : addrs) { + result[i++] = addr.getHostAddress(); + } + return result; + } } diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index 382fcf34757c..e23d6f357506 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -184,6 +184,16 @@ public class CallLog { public static final String VOICEMAIL_URI = "voicemail_uri"; /** + * Whether this item has been read or otherwise consumed by the user. + * <p> + * Unlike the {@link #NEW} field, which requires the user to have acknowledged the + * existence of the entry, this implies the user has interacted with the entry. + * <P>Type: INTEGER (boolean)</P> + * @hide + */ + public static final String IS_READ = "is_read"; + + /** * Adds a call to the call log. * * @param ci the CallerInfo object to get the target contact from. Can be null diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index a0f1eece6367..b2c1386ef00b 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -7413,6 +7413,16 @@ public final class ContactsContract { "com.android.contacts.action.ATTACH_IMAGE"; /** + * This is the intent that is fired when the user clicks the "invite to the network" button + * on a contact. Only sent to an activity which is explicitly registered by a contact + * provider which supports the "invite to the network" feature. + * <p> + * {@link Intent#getData()} contains the lookup URI for the contact. + */ + public static final String INVITE_CONTACT = + "com.android.contacts.action.INVITE_CONTACT"; + + /** * Takes as input a data URI with a mailto: or tel: scheme. If a single * contact exists with the given data it will be shown. If no contact * exists, a dialog will ask the user if they want to create a new diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 1cd46dedd2d2..cd4e32e8ce32 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2688,11 +2688,9 @@ public final class Settings { public static final String ACCESSIBILITY_ENABLED = "accessibility_enabled"; /** - * If touch exploration is requested. Touch exploration is enabled if it is - * requested by this setting, accessibility is enabled and there is at least - * one enabled accessibility serivce that provides spoken feedback. + * If touch exploration is enabled. */ - public static final String TOUCH_EXPLORATION_REQUESTED = "touch_exploration_requested"; + public static final String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled"; /** * List of the enabled accessibility providers. @@ -3935,6 +3933,10 @@ public final class Settings { /** Timeout in milliseconds to wait for NTP server. {@hide} */ public static final String NTP_TIMEOUT = "ntp_timeout"; + /** Autofill server address (Used in WebView/browser). {@hide} */ + public static final String WEB_AUTOFILL_QUERY_URL = + "web_autofill_query_url"; + /** * @hide */ diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java index 2ad7395866fa..2e5a495a282d 100644 --- a/core/java/android/provider/VoicemailContract.java +++ b/core/java/android/provider/VoicemailContract.java @@ -128,6 +128,12 @@ public class VoicemailContract { */ public static final String NEW = Calls.NEW; /** + * Whether this item has been read or otherwise consumed by the user. + * <P>Type: INTEGER (boolean)</P> + * @hide + */ + public static final String IS_READ = Calls.IS_READ; + /** * The mail box state of the voicemail. This field is currently not used by the system. * <P> Possible values: {@link #STATE_INBOX}, {@link #STATE_DELETED}, * {@link #STATE_UNDELETED}. diff --git a/core/java/android/server/BluetoothAdapterStateMachine.java b/core/java/android/server/BluetoothAdapterStateMachine.java new file mode 100644 index 000000000000..ae9146593e0e --- /dev/null +++ b/core/java/android/server/BluetoothAdapterStateMachine.java @@ -0,0 +1,513 @@ +/* + * 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 android.server; + +import android.bluetooth.BluetoothAdapter; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.os.Binder; +import android.os.Message; +import android.provider.Settings; +import android.util.Log; + +import com.android.internal.util.IState; +import com.android.internal.util.State; +import com.android.internal.util.StateMachine; + +import java.io.PrintWriter; + +/** + * Bluetooth Adapter StateMachine + * All the states are at the same level, ie, no hierarchy. + * (BluetootOn) + * | ^ + * TURN_OFF | | BECOME_PAIRABLE + * AIRPLANE_MODE_ON | | + * V | + * (Switching) + * | ^ + * BECOME_NON_PAIRABLE& | | TURN_ON(_CONTINUE)/TURN_ON_FOR_PRIVILEGED + * ALL_DEVICES_DISCONNECTED | | + * V | + * (HotOff) + * / ^ + * / | SERVICE_RECORD_LOADED + * | | + * TURN_COLD | (Warmup) + * \ ^ + * \ | TURN_HOT/TURN_ON + * | | AIRPLANE_MODE_OFF(when Bluetooth was on before) + * V | + * (PowerOff) <----- initial state + * + */ +final class BluetoothAdapterStateMachine extends StateMachine { + private static final String TAG = "BluetoothAdapterStateMachine"; + private static final boolean DBG = false; + + // Message(what) to take an action + // + // We get this message when user tries to turn on BT + public static final int USER_TURN_ON = 1; + // We get this message when user tries to turn off BT + public static final int USER_TURN_OFF = 2; + + // Message(what) to report a event that the state machine need to respond to + // + // Event indicates sevice records have been loaded + public static final int SERVICE_RECORD_LOADED = 51; + // Event indicates all the remote Bluetooth devices has been disconnected + public static final int ALL_DEVICES_DISCONNECTED = 52; + // Event indicates the Bluetooth is connectable + public static final int BECOME_PAIRABLE = 53; + // Event indicates the Bluetooth is non-connectable. + public static final int BECOME_NON_PAIRABLE = 54; + // Event indicates airplane mode is turned on + public static final int AIRPLANE_MODE_ON = 55; + // Event indicates airplane mode is turned off + public static final int AIRPLANE_MODE_OFF = 56; + + // private internal messages + // + // Turn on Bluetooth Module, Load firmware, and do all the preparation + // needed to get the Bluetooth Module ready but keep it not discoverable + // and not connectable. This way the Bluetooth Module can be quickly + // switched on if needed + private static final int TURN_HOT = 101; + // USER_TURN_ON is changed to TURN_ON_CONTINUE after we broadcast the + // state change intent so that we will not broadcast the intent again in + // other state + private static final int TURN_ON_CONTINUE = 102; + // Unload firmware, turning off Bluetooth module power + private static final int TURN_COLD = 103; + // For NFC, turn on bluetooth for certain process + private static final int TURN_ON_FOR_PRIVILEGED = 104; + + private Context mContext; + private BluetoothService mBluetoothService; + private BluetoothEventLoop mEventLoop; + + private BluetoothOn mBluetoothOn; + private Switching mSwitching; + private HotOff mHotOff; + private WarmUp mWarmUp; + private PowerOff mPowerOff; + + // this is the BluetoothAdapter state that reported externally + private int mPublicState; + + BluetoothAdapterStateMachine(Context context, BluetoothService bluetoothService, + BluetoothAdapter bluetoothAdapter) { + super(TAG); + mContext = context; + mBluetoothService = bluetoothService; + mEventLoop = new BluetoothEventLoop(context, bluetoothAdapter, bluetoothService, this); + + mBluetoothOn = new BluetoothOn(); + mSwitching = new Switching(); + mHotOff = new HotOff(); + mWarmUp = new WarmUp(); + mPowerOff = new PowerOff(); + + addState(mBluetoothOn); + addState(mSwitching); + addState(mHotOff); + addState(mWarmUp); + addState(mPowerOff); + setInitialState(mPowerOff); + mPublicState = BluetoothAdapter.STATE_OFF; + + if (mContext.getResources().getBoolean + (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) { + sendMessage(TURN_HOT); + } + } + + /** + * Bluetooth module's power is off, firmware is not loaded. + */ + private class PowerOff extends State { + private boolean mPersistSwitchOn = false; + + @Override + public void enter() { + if (DBG) log("Enter PowerOff: " + mPersistSwitchOn); + mPersistSwitchOn = false; + } + @Override + public boolean processMessage(Message message) { + if (DBG) log("PowerOff process message: " + message.what); + + boolean retValue = HANDLED; + switch(message.what) { + case USER_TURN_ON: + // starts turning on BT module, broadcast this out + transitionTo(mWarmUp); + broadcastState(BluetoothAdapter.STATE_TURNING_ON); + if (prepareBluetooth()) { + // this is user request, save the setting + if ((Boolean) message.obj) { + mPersistSwitchOn = true; + } + // We will continue turn the BT on all the way to the BluetoothOn state + deferMessage(obtainMessage(TURN_ON_CONTINUE)); + } else { + Log.e(TAG, "failed to prepare bluetooth, abort turning on"); + transitionTo(mPowerOff); + broadcastState(BluetoothAdapter.STATE_OFF); + } + break; + case TURN_HOT: + if (prepareBluetooth()) { + transitionTo(mWarmUp); + } + break; + case AIRPLANE_MODE_OFF: + if (getBluetoothPersistedSetting()) { + // starts turning on BT module, broadcast this out + transitionTo(mWarmUp); + broadcastState(BluetoothAdapter.STATE_TURNING_ON); + if (prepareBluetooth()) { + // We will continue turn the BT on all the way to the BluetoothOn state + deferMessage(obtainMessage(TURN_ON_CONTINUE)); + transitionTo(mWarmUp); + } else { + Log.e(TAG, "failed to prepare bluetooth, abort turning on"); + transitionTo(mPowerOff); + broadcastState(BluetoothAdapter.STATE_OFF); + } + } + break; + case AIRPLANE_MODE_ON: // ignore + case USER_TURN_OFF: // ignore + break; + default: + return NOT_HANDLED; + } + return retValue; + } + + /** + * Turn on Bluetooth Module, Load firmware, and do all the preparation + * needed to get the Bluetooth Module ready but keep it not discoverable + * and not connectable. + * The last step of this method sets up the local service record DB. + * There will be a event reporting the status of the SDP setup. + */ + private boolean prepareBluetooth() { + if (mBluetoothService.enableNative() != 0) { + return false; + } + + // try to start event loop, give 2 attempts + int retryCount = 2; + boolean eventLoopStarted = false; + while ((retryCount-- > 0) && !eventLoopStarted) { + mEventLoop.start(); + // it may take a moment for the other thread to do its + // thing. Check periodically for a while. + int pollCount = 5; + while ((pollCount-- > 0) && !eventLoopStarted) { + if (mEventLoop.isEventLoopRunning()) { + eventLoopStarted = true; + break; + } + try { + Thread.sleep(100); + } catch (InterruptedException e) { + break; + } + } + } + + if (!eventLoopStarted) { + mBluetoothService.disableNative(); + return false; + } + + // get BluetoothService ready + if (!mBluetoothService.prepareBluetooth()) { + mEventLoop.stop(); + mBluetoothService.disableNative(); + return false; + } + + return true; + } + } + + /** + * Turning on Bluetooth module's power, loading firmware, starting + * event loop thread to listen on Bluetooth module event changes. + */ + private class WarmUp extends State { + + @Override + public void enter() { + if (DBG) log("Enter WarmUp"); + } + + @Override + public boolean processMessage(Message message) { + if (DBG) log("WarmUp process message: " + message.what); + + boolean retValue = HANDLED; + switch(message.what) { + case SERVICE_RECORD_LOADED: + transitionTo(mHotOff); + break; + case USER_TURN_ON: // handle this at HotOff state + case TURN_ON_CONTINUE: // Once in HotOff state, continue turn bluetooth + // on to the BluetoothOn state + case AIRPLANE_MODE_ON: + case AIRPLANE_MODE_OFF: + deferMessage(message); + break; + case USER_TURN_OFF: // ignore + break; + default: + return NOT_HANDLED; + } + return retValue; + } + + } + + /** + * Bluetooth Module has powered, firmware loaded, event loop started, + * SDP loaded, but the modules stays non-discoverable and + * non-connectable. + */ + private class HotOff extends State { + private boolean mPersistSwitchOn = false; + + @Override + public void enter() { + if (DBG) log("Enter HotOff: " + mPersistSwitchOn); + mPersistSwitchOn = false; + } + + @Override + public boolean processMessage(Message message) { + if (DBG) log("HotOff process message: " + message.what); + + boolean retValue = HANDLED; + switch(message.what) { + case USER_TURN_ON: + if ((Boolean) message.obj) { + mPersistSwitchOn = true; + } + // let it fall to TURN_ON_CONTINUE: + case TURN_ON_CONTINUE: + mBluetoothService.switchConnectable(true); + transitionTo(mSwitching); + broadcastState(BluetoothAdapter.STATE_TURNING_ON); + break; + case AIRPLANE_MODE_ON: + case TURN_COLD: + mBluetoothService.shutoffBluetooth(); + mEventLoop.stop(); + transitionTo(mPowerOff); + // ASSERT no support of config_bluetooth_adapter_quick_switch + broadcastState(BluetoothAdapter.STATE_OFF); + break; + case AIRPLANE_MODE_OFF: + if (getBluetoothPersistedSetting()) { + mBluetoothService.switchConnectable(true); + transitionTo(mSwitching); + broadcastState(BluetoothAdapter.STATE_TURNING_ON); + } + break; + case USER_TURN_OFF: // ignore + break; + default: + return NOT_HANDLED; + } + return retValue; + } + + } + + private class Switching extends State { + + @Override + public void enter() { + int what = getCurrentMessage().what; + if (DBG) log("Enter Switching: " + what); + } + @Override + public boolean processMessage(Message message) { + if (DBG) log("Switching process message: " + message.what); + + boolean retValue = HANDLED; + switch(message.what) { + case BECOME_PAIRABLE: + if (mPowerOff.mPersistSwitchOn || mHotOff.mPersistSwitchOn) { + persistSwitchSetting(true); + mPowerOff.mPersistSwitchOn = mHotOff.mPersistSwitchOn = false; + } + String[] propVal = {"Pairable", mBluetoothService.getProperty("Pairable")}; + mEventLoop.onPropertyChanged(propVal); + + // run bluetooth now that it's turned on + mBluetoothService.runBluetooth(); + transitionTo(mBluetoothOn); + broadcastState(BluetoothAdapter.STATE_ON); + break; + case BECOME_NON_PAIRABLE: + if (mBluetoothService.getAdapterConnectionState() == + BluetoothAdapter.STATE_DISCONNECTED) { + transitionTo(mHotOff); + finishSwitchingOff(); + } + break; + case ALL_DEVICES_DISCONNECTED: + if (mBluetoothService.getScanMode() == BluetoothAdapter.SCAN_MODE_NONE) { + transitionTo(mHotOff); + finishSwitchingOff(); + } + break; + case USER_TURN_ON: + case AIRPLANE_MODE_OFF: + case AIRPLANE_MODE_ON: + case USER_TURN_OFF: + deferMessage(message); + break; + default: + return NOT_HANDLED; + } + return retValue; + } + + private void finishSwitchingOff() { + if (mBluetoothOn.mPersistBluetoothOff) { + persistSwitchSetting(false); + mBluetoothOn.mPersistBluetoothOff = false; + } + mBluetoothService.finishDisable(); + if (mContext.getResources().getBoolean + (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) { + broadcastState(BluetoothAdapter.STATE_OFF); + } else { + deferMessage(obtainMessage(TURN_COLD)); + } + } + } + + private class BluetoothOn extends State { + private boolean mPersistBluetoothOff = false; + + @Override + public void enter() { + if (DBG) log("Enter BluetoothOn: " + mPersistBluetoothOff); + mPersistBluetoothOff = false; + } + @Override + public boolean processMessage(Message message) { + if (DBG) log("BluetoothOn process message: " + message.what); + + boolean retValue = HANDLED; + switch(message.what) { + case USER_TURN_OFF: + if ((Boolean) message.obj) { + mPersistBluetoothOff = true; + } + // let it fall through to AIRPLANE_MODE_ON + case AIRPLANE_MODE_ON: + transitionTo(mSwitching); + broadcastState(BluetoothAdapter.STATE_TURNING_OFF); + mBluetoothService.switchConnectable(false); + mBluetoothService.disconnectDevices(); + // we turn all the way to PowerOff with AIRPLANE_MODE_ON + if (message.what == AIRPLANE_MODE_ON) { + deferMessage(obtainMessage(AIRPLANE_MODE_ON)); + } + break; + case AIRPLANE_MODE_OFF: // ignore + case USER_TURN_ON: // ignore + break; + default: + return NOT_HANDLED; + } + return retValue; + } + + } + + /** + * Return the public BluetoothAdapter state + */ + int getBluetoothAdapterState() { + return mPublicState; + } + + BluetoothEventLoop getBluetoothEventLoop() { + return mEventLoop; + } + + private void persistSwitchSetting(boolean setOn) { + long origCallerIdentityToken = Binder.clearCallingIdentity(); + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.BLUETOOTH_ON, + setOn ? 1 : 0); + Binder.restoreCallingIdentity(origCallerIdentityToken); + } + + private boolean getBluetoothPersistedSetting() { + ContentResolver contentResolver = mContext.getContentResolver(); + return (Settings.Secure.getInt(contentResolver, + Settings.Secure.BLUETOOTH_ON, 0) > 0); + } + + private void broadcastState(int newState) { + + if (DBG) log("Bluetooth state " + mPublicState + " -> " + newState); + if (mPublicState == newState) { + return; + } + + Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); + intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mPublicState); + intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + mPublicState = newState; + + mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM); + } + + private void dump(PrintWriter pw) { + IState currentState = getCurrentState(); + if (currentState == mPowerOff) { + pw.println("Bluetooth OFF - power down\n"); + } else if (currentState == mWarmUp) { + pw.println("Bluetooth OFF - warm up\n"); + } else if (currentState == mHotOff) { + pw.println("Bluetooth OFF - hot but off\n"); + } else if (currentState == mSwitching) { + pw.println("Bluetooth Switching\n"); + } else if (currentState == mBluetoothOn) { + pw.println("Bluetooth ON\n"); + } else { + pw.println("ERROR: Bluetooth UNKNOWN STATE "); + } + } + + private static void log(String msg) { + Log.d(TAG, msg); + } +} diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index f345a6a953d8..107a2a9cf16d 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -52,6 +52,7 @@ class BluetoothEventLoop { private final HashMap<String, Integer> mAuthorizationAgentRequestData; private final BluetoothService mBluetoothService; private final BluetoothAdapter mAdapter; + private final BluetoothAdapterStateMachine mBluetoothState; private BluetoothA2dp mA2dp; private BluetoothInputDevice mInputDevice; private final Context mContext; @@ -107,9 +108,11 @@ class BluetoothEventLoop { private static native void classInitNative(); /* package */ BluetoothEventLoop(Context context, BluetoothAdapter adapter, - BluetoothService bluetoothService) { + BluetoothService bluetoothService, + BluetoothAdapterStateMachine bluetoothState) { mBluetoothService = bluetoothService; mContext = context; + mBluetoothState = bluetoothState; mPasskeyAgentRequestData = new HashMap<String, Integer>(); mAuthorizationAgentRequestData = new HashMap<String, Integer>(); mAdapter = adapter; @@ -299,8 +302,8 @@ class BluetoothEventLoop { /** * Called by native code on a PropertyChanged signal from - * org.bluez.Adapter. This method is also called from Java at - * {@link BluetoothService.EnableThread#run()} to set the "Pairable" + * org.bluez.Adapter. This method is also called from + * {@link BluetoothAdapterStateMachine} to set the "Pairable" * property when Bluetooth is enabled. * * @param propValues a string array containing the key and one or more @@ -334,6 +337,15 @@ class BluetoothEventLoop { return; adapterProperties.setProperty(name, propValues[1]); + + if (name.equals("Pairable")) { + if (pairable.equals("true")) { + mBluetoothState.sendMessage(BluetoothAdapterStateMachine.BECOME_PAIRABLE); + } else { + mBluetoothState.sendMessage(BluetoothAdapterStateMachine.BECOME_NON_PAIRABLE); + } + } + int mode = BluetoothService.bluezStringToScanMode( pairable.equals("true"), discoverable.equals("true")); diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java index d68d8ba1e5b9..34f1971a265c 100755 --- a/core/java/android/server/BluetoothService.java +++ b/core/java/android/server/BluetoothService.java @@ -91,7 +91,7 @@ public class BluetoothService extends IBluetooth.Stub { private BluetoothPan mPan; private boolean mIsAirplaneSensitive; private boolean mIsAirplaneToggleable; - private int mBluetoothState; + private BluetoothAdapterStateMachine mBluetoothState; private boolean mRestart = false; // need to call enable() after disable() private boolean mIsDiscovering; private int[] mAdapterSdpHandles; @@ -111,9 +111,8 @@ public class BluetoothService extends IBluetooth.Stub { private static final String SHARED_PREFERENCE_DOCK_ADDRESS = "dock_bluetooth_address"; private static final String SHARED_PREFERENCES_NAME = "bluetooth_service_settings"; - private static final int MESSAGE_FINISH_DISABLE = 1; - private static final int MESSAGE_UUID_INTENT = 2; - private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3; + private static final int MESSAGE_UUID_INTENT = 1; + private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 2; // The time (in millisecs) to delay the pairing attempt after the first // auto pairing attempt fails. We use an exponential delay with @@ -206,7 +205,6 @@ public class BluetoothService extends IBluetooth.Stub { disableNative(); } - mBluetoothState = BluetoothAdapter.STATE_OFF; mIsDiscovering = false; mBondState = new BluetoothBondState(context, this); @@ -306,7 +304,9 @@ public class BluetoothService extends IBluetooth.Stub { public synchronized void initAfterRegistration() { mAdapter = BluetoothAdapter.getDefaultAdapter(); - mEventLoop = new BluetoothEventLoop(mContext, mAdapter, this); + mBluetoothState = new BluetoothAdapterStateMachine(mContext, this, mAdapter); + mBluetoothState.start(); + mEventLoop = mBluetoothState.getBluetoothEventLoop(); } public synchronized void initAfterA2dpRegistration() { @@ -329,16 +329,16 @@ public class BluetoothService extends IBluetooth.Stub { } private boolean isEnabledInternal() { - return mBluetoothState == BluetoothAdapter.STATE_ON; + return (getBluetoothStateInternal() == BluetoothAdapter.STATE_ON); } public int getBluetoothState() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - return mBluetoothState; + return getBluetoothStateInternal(); } int getBluetoothStateInternal() { - return mBluetoothState; + return mBluetoothState.getBluetoothAdapterState(); } /** @@ -356,7 +356,9 @@ public class BluetoothService extends IBluetooth.Stub { public synchronized boolean disable(boolean saveSetting) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); - switch (mBluetoothState) { + int adapterState = getBluetoothStateInternal(); + + switch (adapterState) { case BluetoothAdapter.STATE_OFF: return true; case BluetoothAdapter.STATE_ON: @@ -364,27 +366,12 @@ public class BluetoothService extends IBluetooth.Stub { default: return false; } - if (mEnableThread != null && mEnableThread.isAlive()) { - return false; - } - - setBluetoothState(BluetoothAdapter.STATE_TURNING_OFF); - - if (mAdapterSdpHandles != null) removeReservedServiceRecordsNative(mAdapterSdpHandles); - setBluetoothTetheringNative(false, BluetoothPanProfileHandler.NAP_ROLE, - BluetoothPanProfileHandler.NAP_BRIDGE); - - // Allow 3 seconds for profiles to gracefully disconnect - // TODO: Introduce a callback mechanism so that each profile can notify - // BluetoothService when it is done shutting down - disconnectDevices(); - mHandler.sendMessageDelayed( - mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000); + mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_OFF, saveSetting); return true; } - private synchronized void disconnectDevices() { + synchronized void disconnectDevices() { // Disconnect devices handled by BluetoothService. for (BluetoothDevice device: getConnectedInputDevices()) { disconnectInputDevice(device); @@ -395,14 +382,11 @@ public class BluetoothService extends IBluetooth.Stub { } } - private synchronized void finishDisable(boolean saveSetting) { - if (mBluetoothState != BluetoothAdapter.STATE_TURNING_OFF) { - return; - } - mEventLoop.stop(); - tearDownNativeDataNative(); - disableNative(); - + /** + * The Bluetooth has been turned off, but hot. Do bonding, profile, + * and internal cleanup + */ + synchronized void finishDisable() { // mark in progress bondings as cancelled for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) { mBondState.setBondState(address, BluetoothDevice.BOND_NONE, @@ -430,12 +414,6 @@ public class BluetoothService extends IBluetooth.Stub { mAdapterUuids = null; mAdapterSdpHandles = null; - if (saveSetting) { - persistBluetoothOnSetting(false); - } - - setBluetoothState(BluetoothAdapter.STATE_OFF); - // Log bluetooth off to battery stats. long ident = Binder.clearCallingIdentity(); try { @@ -451,6 +429,18 @@ public class BluetoothService extends IBluetooth.Stub { } } + /** + * power off Bluetooth + */ + synchronized void shutoffBluetooth() { + tearDownNativeDataNative(); + disableNative(); + if (mRestart) { + mRestart = false; + enable(); + } + } + /** Bring up BT and persist BT on in settings */ public boolean enable() { return enable(true); @@ -471,21 +461,29 @@ public class BluetoothService extends IBluetooth.Stub { if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { return false; } - if (mBluetoothState != BluetoothAdapter.STATE_OFF) { - return false; - } - if (mEnableThread != null && mEnableThread.isAlive()) { + mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_ON, saveSetting); + return true; + } + + /** + * Turn on Bluetooth Module, Load firmware, and do all the preparation + * needed to get the Bluetooth Module ready but keep it not discoverable + * and not connectable. + */ + /* package */ synchronized boolean prepareBluetooth() { + if (!setupNativeDataNative()) { return false; } - setBluetoothState(BluetoothAdapter.STATE_TURNING_ON); - mEnableThread = new EnableThread(saveSetting); - mEnableThread.start(); + mIsDiscovering = false; + + switchConnectable(false); + updateSdpRecords(); return true; } /** Forcibly restart Bluetooth if it is on */ /* package */ synchronized void restart() { - if (mBluetoothState != BluetoothAdapter.STATE_ON) { + if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) { return; } mRestart = true; @@ -494,30 +492,10 @@ public class BluetoothService extends IBluetooth.Stub { } } - private synchronized void setBluetoothState(int state) { - if (state == mBluetoothState) { - return; - } - - if (DBG) Log.d(TAG, "Bluetooth state " + mBluetoothState + " -> " + state); - - Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); - intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mBluetoothState); - intent.putExtra(BluetoothAdapter.EXTRA_STATE, state); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - - mBluetoothState = state; - - mContext.sendBroadcast(intent, BLUETOOTH_PERM); - } - private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { - case MESSAGE_FINISH_DISABLE: - finishDisable(msg.arg1 != 0); - break; case MESSAGE_UUID_INTENT: String address = (String)msg.obj; if (address != null) { @@ -545,65 +523,6 @@ public class BluetoothService extends IBluetooth.Stub { } }; - private EnableThread mEnableThread; - - private class EnableThread extends Thread { - private final boolean mSaveSetting; - public EnableThread(boolean saveSetting) { - mSaveSetting = saveSetting; - } - public void run() { - boolean res = (enableNative() == 0); - if (res) { - int retryCount = 2; - boolean running = false; - while ((retryCount-- > 0) && !running) { - mEventLoop.start(); - // it may take a moment for the other thread to do its - // thing. Check periodically for a while. - int pollCount = 5; - while ((pollCount-- > 0) && !running) { - if (mEventLoop.isEventLoopRunning()) { - running = true; - break; - } - try { - Thread.sleep(100); - } catch (InterruptedException e) {} - } - } - if (!running) { - Log.e(TAG, "bt EnableThread giving up"); - res = false; - disableNative(); - } - } - - if (res) { - if (!setupNativeDataNative()) { - return; - } - if (mSaveSetting) { - persistBluetoothOnSetting(true); - } - - mIsDiscovering = false; - mBondState.readAutoPairingData(); - mBondState.initBondState(); - initProfileState(); - - // This should be the last step of the the enable thread. - // Because this adds SDP records which asynchronously - // broadcasts the Bluetooth On State in updateBluetoothState. - // So we want all internal state setup before this. - updateSdpRecords(); - } else { - setBluetoothState(BluetoothAdapter.STATE_OFF); - } - mEnableThread = null; - } - } - private synchronized void addReservedSdpRecords(final ArrayList<ParcelUuid> uuids) { //Register SDP records. int[] svcIdentifiers = new int[uuids.size()]; @@ -650,38 +569,37 @@ public class BluetoothService extends IBluetooth.Stub { * for adapter comes in with UUID property. * @param uuidsThe uuids of adapter as reported by Bluez. */ - synchronized void updateBluetoothState(String uuids) { - if (mBluetoothState == BluetoothAdapter.STATE_TURNING_ON) { - ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids); - - if (mAdapterUuids != null && - BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) { - setBluetoothState(BluetoothAdapter.STATE_ON); - autoConnect(); - String[] propVal = {"Pairable", getProperty("Pairable")}; - mEventLoop.onPropertyChanged(propVal); - - // Log bluetooth on to battery stats. - long ident = Binder.clearCallingIdentity(); - try { - mBatteryStats.noteBluetoothOn(); - } catch (RemoteException e) { - } finally { - Binder.restoreCallingIdentity(ident); - } + /*package*/ synchronized void updateBluetoothState(String uuids) { + ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids); - if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { - disable(false); - } - } + if (mAdapterUuids != null && + BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) { + mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SERVICE_RECORD_LOADED); } } - private void persistBluetoothOnSetting(boolean bluetoothOn) { - long origCallerIdentityToken = Binder.clearCallingIdentity(); - Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.BLUETOOTH_ON, - bluetoothOn ? 1 : 0); - Binder.restoreCallingIdentity(origCallerIdentityToken); + /** + * This method is called immediately after Bluetooth module is turned on. + * It starts auto-connection and places bluetooth on sign onto the battery + * stats + */ + /*package*/ void runBluetooth() { + mIsDiscovering = false; + mBondState.readAutoPairingData(); + mBondState.initBondState(); + initProfileState(); + + autoConnect(); + + // Log bluetooth on to battery stats. + long ident = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteBluetoothOn(); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + Binder.restoreCallingIdentity(ident); + } } /*package*/ synchronized boolean attemptAutoPair(String address) { @@ -818,6 +736,26 @@ public class BluetoothService extends IBluetooth.Stub { public synchronized boolean setScanMode(int mode, int duration) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS, "Need WRITE_SECURE_SETTINGS permission"); + return setScanMode(mode, duration, true); + } + + /** + * @param on true set the local Bluetooth module to be connectable + * but not dicoverable + * false set the local Bluetooth module to be not connectable + * and not dicoverable + */ + /*package*/ synchronized void switchConnectable(boolean on) { + if (on) { + // 0 is a dummy value, does not apply for SCAN_MODE_CONNECTABLE + setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE, 0, false); + } else { + // 0 is a dummy value, does not apply for SCAN_MODE_NONE + setScanMode(BluetoothAdapter.SCAN_MODE_NONE, 0, false); + } + } + + private synchronized boolean setScanMode(int mode, int duration, boolean allowOnlyInOnState) { boolean pairable; boolean discoverable; @@ -839,9 +777,15 @@ public class BluetoothService extends IBluetooth.Stub { Log.w(TAG, "Requested invalid scan mode " + mode); return false; } - setPropertyBoolean("Pairable", pairable); - setPropertyBoolean("Discoverable", discoverable); + if (allowOnlyInOnState) { + setPropertyBoolean("Pairable", pairable); + setPropertyBoolean("Discoverable", discoverable); + } else { + // allowed to set the property through native layer directly + setAdapterPropertyBooleanNative("Pairable", pairable ? 1 : 0); + setAdapterPropertyBooleanNative("Discoverable", discoverable ? 1 : 0); + } return true; } @@ -1569,14 +1513,10 @@ public class BluetoothService extends IBluetooth.Stub { ContentResolver resolver = context.getContentResolver(); // Query the airplane mode from Settings.System just to make sure that // some random app is not sending this intent and disabling bluetooth - boolean enabled = !isAirplaneModeOn(); - // If bluetooth is currently expected to be on, then enable or disable bluetooth - if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) { - if (enabled) { - enable(false); - } else { - disable(false); - } + if (isAirplaneModeOn()) { + mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_ON); + } else { + mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_OFF); } } else if (Intent.ACTION_DOCK_EVENT.equals(action)) { int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, @@ -1650,8 +1590,7 @@ public class BluetoothService extends IBluetooth.Stub { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - dumpBluetoothState(pw); - if (mBluetoothState != BluetoothAdapter.STATE_ON) { + if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) { return; } @@ -1840,25 +1779,6 @@ public class BluetoothService extends IBluetooth.Stub { } } - private void dumpBluetoothState(PrintWriter pw) { - switch(mBluetoothState) { - case BluetoothAdapter.STATE_OFF: - pw.println("Bluetooth OFF\n"); - break; - case BluetoothAdapter.STATE_TURNING_ON: - pw.println("Bluetooth TURNING ON\n"); - break; - case BluetoothAdapter.STATE_TURNING_OFF: - pw.println("Bluetooth TURNING OFF\n"); - break; - case BluetoothAdapter.STATE_ON: - pw.println("Bluetooth ON\n"); - break; - default: - pw.println("Bluetooth UNKNOWN STATE " + mBluetoothState); - } - } - private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { @@ -2389,7 +2309,7 @@ public class BluetoothService extends IBluetooth.Stub { public synchronized void sendConnectionStateChange(BluetoothDevice device, int state, int prevState) { // Since this is a binder call check if Bluetooth is on still - if (mBluetoothState == BluetoothAdapter.STATE_OFF) return; + if (getBluetoothStateInternal() == BluetoothAdapter.STATE_OFF) return; if (updateCountersAndCheckForConnectionStateChange(state, prevState)) { if (!validateProfileConnectionState(state) || @@ -2405,6 +2325,10 @@ public class BluetoothService extends IBluetooth.Stub { mAdapterConnectionState = state; + if (state == BluetoothProfile.STATE_DISCONNECTED) { + mBluetoothState.sendMessage(BluetoothAdapterStateMachine.ALL_DEVICES_DISCONNECTED); + } + Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, @@ -2598,8 +2522,8 @@ public class BluetoothService extends IBluetooth.Stub { /*package*/ native String getAdapterPathNative(); private native int isEnabledNative(); - private native int enableNative(); - private native int disableNative(); + /*package*/ native int enableNative(); + /*package*/ native int disableNative(); /*package*/ native Object[] getAdapterPropertiesNative(); private native Object[] getDevicePropertiesNative(String objectPath); diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java index c6ffe580753f..5926db3713db 100644 --- a/core/java/android/text/format/Time.java +++ b/core/java/android/text/format/Time.java @@ -281,10 +281,29 @@ public class Time { } /** - * return a negative number if a is less than b, a positive number if a is - * greater than b, and 0 if they are equal. - */ - native public static int compare(Time a, Time b); + * Compare two {@code Time} objects and return a negative number if {@code + * a} is less than {@code b}, a positive number if {@code a} is greater than + * {@code b}, or 0 if they are equal. + * + * @param a first {@code Time} instance to compare + * @param b second {@code Time} instance to compare + * @throws NullPointerException if either argument is {@code null} + * @throws IllegalArgumentException if {@link #allDay} is true but {@code + * hour}, {@code minute}, and {@code second} are not 0. + * @return a negative result if {@code a} is earlier, a positive result if + * {@code a} is earlier, or 0 if they are equal. + */ + public static int compare(Time a, Time b) { + if (a == null) { + throw new NullPointerException("a == null"); + } else if (b == null) { + throw new NullPointerException("b == null"); + } + + return nativeCompare(a, b); + } + + private static native int nativeCompare(Time a, Time b); /** * Print the current value given the format string provided. See man diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 503b54bd437d..14a77b40415f 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -33,6 +33,8 @@ import javax.microedition.khronos.egl.EGLDisplay; import javax.microedition.khronos.egl.EGLSurface; import javax.microedition.khronos.opengles.GL; +import static javax.microedition.khronos.egl.EGL10.*; + /** * Interface for rendering a ViewAncestor using hardware acceleration. * @@ -70,6 +72,15 @@ public abstract class HardwareRenderer { static final String DISABLE_VSYNC_PROPERTY = "hwui.disable_vsync"; /** + * System property used to debug EGL configuration choice. + * + * Possible values: + * "choice", print the chosen configuration only + * "all", print all possible configurations + */ + static final String PRINT_CONFIG_PROPERTY = "hwui.print_config"; + + /** * Turn on to draw dirty regions every other frame. */ private static final boolean DEBUG_DIRTY_REGION = false; @@ -389,33 +400,33 @@ public abstract class HardwareRenderer { */ static String getEGLErrorString(int error) { switch (error) { - case EGL10.EGL_SUCCESS: + case EGL_SUCCESS: return "EGL_SUCCESS"; - case EGL10.EGL_NOT_INITIALIZED: + case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; - case EGL10.EGL_BAD_ACCESS: + case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; - case EGL10.EGL_BAD_ALLOC: + case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; - case EGL10.EGL_BAD_ATTRIBUTE: + case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; - case EGL10.EGL_BAD_CONFIG: + case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; - case EGL10.EGL_BAD_CONTEXT: + case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; - case EGL10.EGL_BAD_CURRENT_SURFACE: + case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; - case EGL10.EGL_BAD_DISPLAY: + case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; - case EGL10.EGL_BAD_MATCH: + case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; - case EGL10.EGL_BAD_NATIVE_PIXMAP: + case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; - case EGL10.EGL_BAD_NATIVE_WINDOW: + case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; - case EGL10.EGL_BAD_PARAMETER: + case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; - case EGL10.EGL_BAD_SURFACE: + case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; case EGL11.EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; @@ -432,7 +443,7 @@ public abstract class HardwareRenderer { void checkEglErrors() { if (isEnabled()) { int error = sEgl.eglGetError(); - if (error != EGL10.EGL_SUCCESS) { + if (error != EGL_SUCCESS) { // something bad has happened revert to // normal rendering. fallback(error != EGL11.EGL_CONTEXT_LOST); @@ -460,7 +471,7 @@ public abstract class HardwareRenderer { if (mGl != null) { int err = sEgl.eglGetError(); - if (err != EGL10.EGL_SUCCESS) { + if (err != EGL_SUCCESS) { destroy(true); setRequested(false); } else { @@ -489,15 +500,17 @@ public abstract class HardwareRenderer { abstract GLES20Canvas createCanvas(); + abstract int[] getConfig(boolean dirtyRegions); + void initializeEgl() { synchronized (sEglLock) { if (sEgl == null && sEglConfig == null) { sEgl = (EGL10) EGLContext.getEGL(); // Get to the default display. - sEglDisplay = sEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + sEglDisplay = sEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (sEglDisplay == EGL10.EGL_NO_DISPLAY) { + if (sEglDisplay == EGL_NO_DISPLAY) { throw new RuntimeException("eglGetDisplay failed " + getEGLErrorString(sEgl.eglGetError())); } @@ -535,19 +548,63 @@ public abstract class HardwareRenderer { } private EGLConfig chooseEglConfig() { - int[] configsCount = new int[1]; EGLConfig[] configs = new EGLConfig[1]; + int[] configsCount = new int[1]; int[] configSpec = getConfig(sDirtyRegions); + + // Debug + final String debug = SystemProperties.get(PRINT_CONFIG_PROPERTY, ""); + if ("all".equalsIgnoreCase(debug)) { + sEgl.eglChooseConfig(sEglDisplay, configSpec, null, 0, configsCount); + + EGLConfig[] debugConfigs = new EGLConfig[configsCount[0]]; + sEgl.eglChooseConfig(sEglDisplay, configSpec, debugConfigs, + configsCount[0], configsCount); + + for (EGLConfig config : debugConfigs) { + printConfig(config); + } + } + if (!sEgl.eglChooseConfig(sEglDisplay, configSpec, configs, 1, configsCount)) { throw new IllegalArgumentException("eglChooseConfig failed " + getEGLErrorString(sEgl.eglGetError())); } else if (configsCount[0] > 0) { + if ("choice".equalsIgnoreCase(debug)) { + printConfig(configs[0]); + } return configs[0]; } + return null; } - abstract int[] getConfig(boolean dirtyRegions); + private void printConfig(EGLConfig config) { + int[] value = new int[1]; + + Log.d(LOG_TAG, "EGL configuration " + config + ":"); + + sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_RED_SIZE, value); + Log.d(LOG_TAG, " RED_SIZE = " + value[0]); + + sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_GREEN_SIZE, value); + Log.d(LOG_TAG, " GREEN_SIZE = " + value[0]); + + sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_BLUE_SIZE, value); + Log.d(LOG_TAG, " BLUE_SIZE = " + value[0]); + + sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_ALPHA_SIZE, value); + Log.d(LOG_TAG, " ALPHA_SIZE = " + value[0]); + + sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_DEPTH_SIZE, value); + Log.d(LOG_TAG, " DEPTH_SIZE = " + value[0]); + + sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_STENCIL_SIZE, value); + Log.d(LOG_TAG, " STENCIL_SIZE = " + value[0]); + + sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SURFACE_TYPE, value); + Log.d(LOG_TAG, " SURFACE_TYPE = 0x" + Integer.toHexString(value[0])); + } GL createEglSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException { // Check preconditions. @@ -569,22 +626,21 @@ public abstract class HardwareRenderer { * The window size has changed, so we need to create a new * surface. */ - if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { + if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) { /* * Unbind and destroy the old EGL surface, if * there is one. */ - sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); + sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); sEgl.eglDestroySurface(sEglDisplay, mEglSurface); } // Create an EGL surface we can render into. mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, holder, null); - if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { + if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) { int error = sEgl.eglGetError(); - if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { + if (error == EGL_BAD_NATIVE_WINDOW) { Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); return null; } @@ -621,9 +677,9 @@ public abstract class HardwareRenderer { } EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) { - int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, mGlVersion, EGL10.EGL_NONE }; + int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, mGlVersion, EGL_NONE }; - return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, + return egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, mGlVersion != 0 ? attrib_list : null); } @@ -646,8 +702,7 @@ public abstract class HardwareRenderer { mDestroyed = true; - sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); + sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); sEgl.eglDestroySurface(sEglDisplay, mEglSurface); mEglSurface = null; @@ -660,8 +715,8 @@ public abstract class HardwareRenderer { void invalidate() { // Cancels any existing buffer to ensure we'll get a buffer // of the right size before we call eglSwapBuffers - sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); + sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, + EGL_NO_SURFACE, EGL_NO_CONTEXT); } @Override @@ -772,7 +827,7 @@ public abstract class HardwareRenderer { } if (!mEglContext.equals(sEgl.eglGetCurrentContext()) || - !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) { + !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) { if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) { fallback(true); Log.e(LOG_TAG, "eglMakeCurrent failed " + @@ -804,16 +859,16 @@ public abstract class HardwareRenderer { @Override int[] getConfig(boolean dirtyRegions) { return new int[] { - EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL10.EGL_RED_SIZE, 8, - EGL10.EGL_GREEN_SIZE, 8, - EGL10.EGL_BLUE_SIZE, 8, - EGL10.EGL_ALPHA_SIZE, 8, - EGL10.EGL_DEPTH_SIZE, 0, - EGL10.EGL_STENCIL_SIZE, 0, - EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT | + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 0, + EGL_STENCIL_SIZE, 0, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT | (dirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0), - EGL10.EGL_NONE + EGL_NONE }; } diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index c913bb30cd90..836867b80fb1 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -161,6 +161,9 @@ public class Surface implements Parcelable { */ public static final int FLAGS_ORIENTATION_ANIMATION_DISABLE = 0x000000001; + // The mSurfaceControl will only be present for Surfaces used by the window + // server or system processes. When this class is parceled we defer to the + // mSurfaceControl to do the parceling. Otherwise we parcel the mNativeSurface. @SuppressWarnings("unused") private int mSurfaceControl; @SuppressWarnings("unused") @@ -202,6 +205,19 @@ public class Surface implements Parcelable { native private static void nativeClassInit(); static { nativeClassInit(); } + /** + * Create Surface from a SurfaceTexture. + * + * @param surfaceTexture The {@link SurfaceTexture} that is updated by this Surface. + * @hide + */ + public Surface(SurfaceTexture surfaceTexture) { + if (DEBUG_RELEASE) { + mCreationStack = new Exception(); + } + mCanvas = new CompatibleCanvas(); + initFromSurfaceTexture(surfaceTexture); + } /** * create a surface @@ -505,5 +521,7 @@ public class Surface implements Parcelable { private native void init(Parcel source); + private native void initFromSurfaceTexture(SurfaceTexture surfaceTexture); + private native int getIdentity(); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index c68b01cac538..22131881239b 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3903,6 +3903,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit int[] locationOnScreen = mAttachInfo.mInvalidateChildLocation; getLocationOnScreen(locationOnScreen); + bounds.offsetTo(0, 0); bounds.offset(locationOnScreen[0], locationOnScreen[1]); info.setBoundsInScreen(bounds); @@ -4280,6 +4281,36 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit } /** + * Set whether or not this view should account for system screen decorations + * such as the status bar and inset its content. This allows this view to be + * positioned in absolute screen coordinates and remain visible to the user. + * + * <p>This should only be used by top-level window decor views. + * + * @param fitSystemWindows true to inset content for system screen decorations, false for + * default behavior. + * + * @attr ref android.R.styleable#View_fitsSystemWindows + */ + public void setFitsSystemWindows(boolean fitSystemWindows) { + setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS); + } + + /** + * Check for the FITS_SYSTEM_WINDOWS flag. If this method returns true, this view + * will account for system screen decorations such as the status bar and inset its + * content. This allows the view to be positioned in absolute screen coordinates + * and remain visible to the user. + * + * @return true if this view will adjust its content bounds for system screen decorations. + * + * @attr ref android.R.styleable#View_fitsSystemWindows + */ + public boolean fitsSystemWindows() { + return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS; + } + + /** * Returns the visibility status for this view. * * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 6f909713e4c1..8cf03a67a6cd 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -2854,7 +2854,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // display lists to render, force an invalidate to allow the animation to // continue drawing another frame invalidate(true); - if (a.hasAlpha()) { + if (a.hasAlpha() && (child.mPrivateFlags & ALPHA_SET) == ALPHA_SET) { // alpha animations should cause the child to recreate its display list child.invalidate(true); } diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index 83c73cb85cc8..a80c2a7147c9 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -67,13 +67,17 @@ public final class AccessibilityManager { private static final String LOG_TAG = "AccessibilityManager"; + /** @hide */ + public static final int STATE_FLAG_ACCESSIBILITY_ENABLED = 0x00000001; + + /** @hide */ + public static final int STATE_FLAG_TOUCH_EXPLORATION_ENABLED = 0x00000002; + static final Object sInstanceSync = new Object(); private static AccessibilityManager sInstance; - private static final int DO_SET_ACCESSIBILITY_ENABLED = 10; - - private static final int DO_SET_TOUCH_EXPLORATION_ENABLED = 20; + private static final int DO_SET_STATE = 10; final IAccessibilityManager mService; @@ -100,13 +104,8 @@ public final class AccessibilityManager { } final IAccessibilityManagerClient.Stub mClient = new IAccessibilityManagerClient.Stub() { - public void setEnabled(boolean enabled) { - mHandler.obtainMessage(DO_SET_ACCESSIBILITY_ENABLED, enabled ? 1 : 0, 0).sendToTarget(); - } - - public void setTouchExplorationEnabled(boolean enabled) { - mHandler.obtainMessage(DO_SET_TOUCH_EXPLORATION_ENABLED, - enabled ? 1 : 0, 0).sendToTarget(); + public void setState(int state) { + mHandler.obtainMessage(DO_SET_STATE, state, 0).sendToTarget(); } }; @@ -119,14 +118,8 @@ public final class AccessibilityManager { @Override public void handleMessage(Message message) { switch (message.what) { - case DO_SET_ACCESSIBILITY_ENABLED : - final boolean isAccessibilityEnabled = (message.arg1 == 1); - setAccessibilityState(isAccessibilityEnabled); - return; - case DO_SET_TOUCH_EXPLORATION_ENABLED : - synchronized (mHandler) { - mIsTouchExplorationEnabled = (message.arg1 == 1); - } + case DO_SET_STATE : + setState(message.arg1); return; default : Log.w(LOG_TAG, "Unknown message type: " + message.what); @@ -163,8 +156,8 @@ public final class AccessibilityManager { mService = service; try { - final boolean isEnabled = mService.addClient(mClient); - setAccessibilityState(isEnabled); + final int stateFlags = mService.addClient(mClient); + setState(stateFlags); } catch (RemoteException re) { Log.e(LOG_TAG, "AccessibilityManagerService is dead", re); } @@ -341,6 +334,17 @@ public final class AccessibilityManager { } /** + * Sets the current state. + * + * @param stateFlags The state flags. + */ + private void setState(int stateFlags) { + final boolean accessibilityEnabled = (stateFlags & STATE_FLAG_ACCESSIBILITY_ENABLED) != 0; + setAccessibilityState(accessibilityEnabled); + mIsTouchExplorationEnabled = (stateFlags & STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0; + } + + /** * Sets the enabled state. * * @param isEnabled The accessibility state. diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 0e044712c0b2..6469b350a288 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -294,14 +294,14 @@ public class AccessibilityNodeInfo implements Parcelable { } /** - * Gets the unique id identifying this node's parent. + * Gets the parent. * <p> * <strong>Note:</strong> It is a client responsibility to recycle the * received info by calling {@link AccessibilityNodeInfo#recycle()} * to avoid creating of multiple instances. * </p> * - * @return The node's patent id. + * @return The parent. */ public AccessibilityNodeInfo getParent() { enforceSealed(); diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl index b14f02a75711..c621ff6d2d60 100644 --- a/core/java/android/view/accessibility/IAccessibilityManager.aidl +++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl @@ -34,7 +34,7 @@ import android.view.IWindow; */ interface IAccessibilityManager { - boolean addClient(IAccessibilityManagerClient client); + int addClient(IAccessibilityManagerClient client); boolean sendAccessibilityEvent(in AccessibilityEvent uiEvent); diff --git a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl index 4e69692494c5..5e7e8133e23c 100644 --- a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl +++ b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl @@ -24,7 +24,5 @@ package android.view.accessibility; */ oneway interface IAccessibilityManagerClient { - void setEnabled(boolean enabled); - - void setTouchExplorationEnabled(boolean enabled); + void setState(int stateFlags); } diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java index 229b4145bdcd..ae253cf1671b 100644 --- a/core/java/android/view/textservice/TextServicesManager.java +++ b/core/java/android/view/textservice/TextServicesManager.java @@ -22,9 +22,9 @@ import android.content.Context; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; -import android.view.textservice.SpellCheckerInfo; import android.service.textservice.SpellCheckerSession; import android.service.textservice.SpellCheckerSession.SpellCheckerSessionListener; +import android.util.Log; import java.util.Locale; @@ -38,6 +38,7 @@ import java.util.Locale; */ public final class TextServicesManager { private static final String TAG = TextServicesManager.class.getSimpleName(); + private static final boolean DBG = false; private static TextServicesManager sInstance; private static ITextServicesManager sService; @@ -75,12 +76,14 @@ public final class TextServicesManager { // TODO: Handle referToSpellCheckerLanguageSettings public SpellCheckerSession newSpellCheckerSession(Locale locale, SpellCheckerSessionListener listener, boolean referToSpellCheckerLanguageSettings) { - if (locale == null || listener == null) { + if (listener == null) { throw new NullPointerException(); } + // TODO: set a proper locale instead of the dummy locale + final String localeString = locale == null ? "en" : locale.toString(); final SpellCheckerInfo info; try { - info = sService.getCurrentSpellChecker(locale.toString()); + info = sService.getCurrentSpellChecker(localeString); } catch (RemoteException e) { return null; } @@ -89,8 +92,8 @@ public final class TextServicesManager { } final SpellCheckerSession session = new SpellCheckerSession(info, sService, listener); try { - sService.getSpellCheckerService( - info, locale.toString(), session.getTextServicesSessionListener(), + sService.getSpellCheckerService(info, localeString, + session.getTextServicesSessionListener(), session.getSpellCheckerSessionListener()); } catch (RemoteException e) { return null; @@ -103,8 +106,13 @@ public final class TextServicesManager { */ public SpellCheckerInfo[] getEnabledSpellCheckers() { try { - return sService.getEnabledSpellCheckers(); + final SpellCheckerInfo[] retval = sService.getEnabledSpellCheckers(); + if (DBG) { + Log.d(TAG, "getEnabledSpellCheckers: " + (retval != null ? retval.length : "null")); + } + return retval; } catch (RemoteException e) { + Log.e(TAG, "Error in getEnabledSpellCheckers: " + e); return null; } } diff --git a/core/java/android/webkit/JniUtil.java b/core/java/android/webkit/JniUtil.java index bb4d192516b9..620973e421d5 100644 --- a/core/java/android/webkit/JniUtil.java +++ b/core/java/android/webkit/JniUtil.java @@ -18,6 +18,7 @@ package android.webkit; import android.content.Context; import android.net.Uri; +import android.provider.Settings; import android.util.Log; import java.io.InputStream; @@ -38,7 +39,7 @@ class JniUtil { private static boolean initialized = false; - private static void checkIntialized() { + private static void checkInitialized() { if (!initialized) { throw new IllegalStateException("Call CookieSyncManager::createInstance() or create a webview before using this class"); } @@ -63,7 +64,7 @@ class JniUtil { * @return String The application's database directory */ private static synchronized String getDatabaseDirectory() { - checkIntialized(); + checkInitialized(); if (sDatabaseDirectory == null) sDatabaseDirectory = sContext.getDatabasePath("dummy").getParent(); @@ -76,7 +77,7 @@ class JniUtil { * @return String The application's cache directory */ private static synchronized String getCacheDirectory() { - checkIntialized(); + checkInitialized(); if (sCacheDirectory == null) sCacheDirectory = sContext.getCacheDir().getAbsolutePath(); @@ -166,5 +167,13 @@ class JniUtil { return sUseChromiumHttpStack; } + private static synchronized String getAutofillQueryUrl() { + checkInitialized(); + // If the device has not checked in it won't have pulled down the system setting for the + // Autofill Url. In that case we will not make autofill server requests. + return Settings.Secure.getString(sContext.getContentResolver(), + Settings.Secure.WEB_AUTOFILL_QUERY_URL); + } + private static native boolean nativeUseChromiumHttpStack(); } diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 6a3b2ffefae1..e24ab58503ad 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -4701,6 +4701,7 @@ public class WebView extends AbsoluteLayout private Message mUpdateMessage; private boolean mAutoFillable; private boolean mAutoComplete; + private WebSettings mWebSettings; public RequestFormData(String name, String url, Message msg, boolean autoFillable, boolean autoComplete) { @@ -4709,6 +4710,7 @@ public class WebView extends AbsoluteLayout mUpdateMessage = msg; mAutoFillable = autoFillable; mAutoComplete = autoComplete; + mWebSettings = getSettings(); } public void run() { @@ -4718,8 +4720,7 @@ public class WebView extends AbsoluteLayout // Note that code inside the adapter click handler in WebTextView depends // on the AutoFill item being at the top of the drop down list. If you change // the order, make sure to do it there too! - WebSettings settings = getSettings(); - if (settings != null && settings.getAutoFillProfile() != null) { + if (mWebSettings != null && mWebSettings.getAutoFillProfile() != null) { pastEntries.add(getResources().getText( com.android.internal.R.string.autofill_this_form).toString() + " " + diff --git a/core/java/android/widget/AdapterViewFlipper.java b/core/java/android/widget/AdapterViewFlipper.java index 273c2588e90c..4419886bed4c 100644 --- a/core/java/android/widget/AdapterViewFlipper.java +++ b/core/java/android/widget/AdapterViewFlipper.java @@ -62,15 +62,14 @@ public class AdapterViewFlipper extends AdapterViewAnimator { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, - com.android.internal.R.styleable.ViewFlipper); + com.android.internal.R.styleable.AdapterViewFlipper); mFlipInterval = a.getInt( - com.android.internal.R.styleable.ViewFlipper_flipInterval, DEFAULT_INTERVAL); + com.android.internal.R.styleable.AdapterViewFlipper_flipInterval, DEFAULT_INTERVAL); mAutoStart = a.getBoolean( - com.android.internal.R.styleable.ViewFlipper_autoStart, false); + com.android.internal.R.styleable.AdapterViewFlipper_autoStart, false); - // By default we want the flipper to loop - mLoopViews = a.getBoolean( - com.android.internal.R.styleable.AdapterViewAnimator_loopViews, true); + // A view flipper should cycle through the views + mLoopViews = true; a.recycle(); } diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java index 3bd7fabe9ec7..f999960219da 100644 --- a/core/java/android/widget/GridLayout.java +++ b/core/java/android/widget/GridLayout.java @@ -21,7 +21,6 @@ import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; import android.util.Pair; @@ -38,6 +37,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import static android.view.Gravity.*; import static java.lang.Math.max; import static java.lang.Math.min; @@ -167,7 +167,7 @@ public class GridLayout extends ViewGroup { // Misc constants private static final String TAG = GridLayout.class.getName(); - static boolean DEBUG = false; + private static boolean DEBUG = false; private static final int PRF = 1; // Defaults @@ -198,7 +198,8 @@ public class GridLayout extends ViewGroup { private int mOrientation = DEFAULT_ORIENTATION; private boolean mUseDefaultMargins = DEFAULT_USE_DEFAULT_MARGINS; private int mAlignmentMode = DEFAULT_ALIGNMENT_MODE; - private int mDefaultGravity = Gravity.NO_GRAVITY; + private Alignment mColumnAlignment = LEFT; + private Alignment mRowAlignment = BASELINE; private int mDefaultGap; // Constructors @@ -216,9 +217,9 @@ public class GridLayout extends ViewGroup { try { setRowCount(a.getInt(ROW_COUNT, DEFAULT_COUNT)); setColumnCount(a.getInt(COLUMN_COUNT, DEFAULT_COUNT)); - mOrientation = a.getInt(ORIENTATION, DEFAULT_ORIENTATION); - mUseDefaultMargins = a.getBoolean(USE_DEFAULT_MARGINS, DEFAULT_USE_DEFAULT_MARGINS); - mAlignmentMode = a.getInt(ALIGNMENT_MODE, DEFAULT_ALIGNMENT_MODE); + setOrientation(a.getInt(ORIENTATION, DEFAULT_ORIENTATION)); + setUseDefaultMargins(a.getBoolean(USE_DEFAULT_MARGINS, DEFAULT_USE_DEFAULT_MARGINS)); + setAlignmentMode(a.getInt(ALIGNMENT_MODE, DEFAULT_ALIGNMENT_MODE)); setRowOrderPreserved(a.getBoolean(ROW_ORDER_PRESERVED, DEFAULT_ORDER_PRESERVED)); setColumnOrderPreserved(a.getBoolean(COLUMN_ORDER_PRESERVED, DEFAULT_ORDER_PRESERVED)); } finally { @@ -514,6 +515,8 @@ public class GridLayout extends ViewGroup { requestLayout(); } + // Static utility methods + private static int max2(int[] a, int valueIfEmpty) { int result = valueIfEmpty; for (int i = 0, N = a.length; i < N; i++) { @@ -537,6 +540,24 @@ public class GridLayout extends ViewGroup { return result; } + private static Alignment getAlignment(int gravity, boolean horizontal) { + int mask = horizontal ? HORIZONTAL_GRAVITY_MASK : VERTICAL_GRAVITY_MASK; + int shift = horizontal ? AXIS_X_SHIFT : AXIS_Y_SHIFT; + int flags = (gravity & mask) >> shift; + switch (flags) { + case (AXIS_SPECIFIED | AXIS_PULL_BEFORE): + return LEADING; + case (AXIS_SPECIFIED | AXIS_PULL_AFTER): + return TRAILING; + case (AXIS_SPECIFIED | AXIS_PULL_BEFORE | AXIS_PULL_AFTER): + return FILL; + case AXIS_SPECIFIED: + return CENTER; + default: + return UNDEFINED_ALIGNMENT; + } + } + private int getDefaultMargin(View c, boolean horizontal, boolean leading) { return mDefaultGap / 2; } @@ -678,7 +699,7 @@ public class GridLayout extends ViewGroup { @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { - return new LayoutParams(getContext(), attrs, mDefaultGravity); + return new LayoutParams(getContext(), attrs); } @Override @@ -833,6 +854,9 @@ public class GridLayout extends ViewGroup { } private int getMeasurementIncludingMargin(View c, boolean horizontal) { + if (isGone(c)) { + return 0; + } int result = getMeasurement(c, horizontal); if (mAlignmentMode == ALIGN_MARGINS) { return result + getTotalMargin(c, horizontal); @@ -846,6 +870,11 @@ public class GridLayout extends ViewGroup { invalidateValues(); } + private Alignment getAlignment(Alignment alignment, boolean horizontal) { + return (alignment != UNDEFINED_ALIGNMENT) ? alignment : + (horizontal ? mColumnAlignment : mRowAlignment); + } + // Layout container /** @@ -895,8 +924,8 @@ public class GridLayout extends ViewGroup { int pWidth = getMeasurement(c, true); int pHeight = getMeasurement(c, false); - Alignment hAlign = columnSpec.alignment; - Alignment vAlign = rowSpec.alignment; + Alignment hAlign = getAlignment(columnSpec.alignment, true); + Alignment vAlign = getAlignment(rowSpec.alignment, false); int dx, dy; @@ -1035,14 +1064,10 @@ public class GridLayout extends ViewGroup { Assoc<Spec, Bounds> assoc = Assoc.of(Spec.class, Bounds.class); for (int i = 0, N = getChildCount(); i < N; i++) { View c = getChildAt(i); - if (isGone(c)) { - assoc.put(Spec.GONE, Bounds.GONE); - } else { - LayoutParams lp = getLayoutParams(c); - Spec spec = horizontal ? lp.columnSpec : lp.rowSpec; - Bounds bounds = spec.alignment.getBounds(); - assoc.put(spec, bounds); - } + LayoutParams lp = getLayoutParams(c); + Spec spec = horizontal ? lp.columnSpec : lp.rowSpec; + Bounds bounds = getAlignment(spec.alignment, horizontal).getBounds(); + assoc.put(spec, bounds); } return assoc.pack(); } @@ -1054,7 +1079,6 @@ public class GridLayout extends ViewGroup { } for (int i = 0, N = getChildCount(); i < N; i++) { View c = getChildAt(i); - if (isGone(c)) continue; LayoutParams lp = getLayoutParams(c); Spec spec = horizontal ? lp.columnSpec : lp.rowSpec; groupBounds.getValue(i).include(c, spec, GridLayout.this, this); @@ -1094,11 +1118,8 @@ public class GridLayout extends ViewGroup { for (int i = 0; i < bounds.length; i++) { int size = bounds[i].size(min); MutableInt valueHolder = links.getValue(i); - if (min) { - valueHolder.value = max(valueHolder.value, size); - } else { - valueHolder.value = -max(-valueHolder.value, size); - } + // this effectively takes the max() of the minima and the min() of the maxima + valueHolder.value = max(valueHolder.value, min ? size : -size); } } @@ -1397,7 +1418,7 @@ public class GridLayout extends ViewGroup { } if (!changed) { if (DEBUG) { - Log.d(TAG, axis + " iteration completed in " + (1 + i) + " steps of " + N); + Log.v(TAG, axis + " iteration completed in " + (1 + i) + " steps of " + N); } return; } @@ -1654,14 +1675,6 @@ public class GridLayout extends ViewGroup { private static final int DEFAULT_COLUMN = UNDEFINED; private static final Interval DEFAULT_SPAN = new Interval(UNDEFINED, UNDEFINED + 1); private static final int DEFAULT_SPAN_SIZE = DEFAULT_SPAN.size(); - private static final Alignment DEFAULT_COLUMN_ALIGNMENT = LEFT; - private static final Alignment DEFAULT_ROW_ALIGNMENT = BASELINE; - - // Misc - - private static final Rect CONTAINER_BOUNDS = new Rect(0, 0, 2, 2); - private static final Alignment[] COLUMN_ALIGNMENTS = { LEFT, CENTER, RIGHT }; - private static final Alignment[] ROW_ALIGNMENTS = { TOP, CENTER, BOTTOM }; // TypedArray indices @@ -1728,8 +1741,7 @@ public class GridLayout extends ViewGroup { * Constructs a new LayoutParams with default values as defined in {@link LayoutParams}. */ public LayoutParams() { - this(new Spec(DEFAULT_SPAN, DEFAULT_ROW_ALIGNMENT, Spec.DEFAULT_FLEXIBILITY), - new Spec(DEFAULT_SPAN, DEFAULT_COLUMN_ALIGNMENT, Spec.DEFAULT_FLEXIBILITY)); + this(spec(UNDEFINED), spec(UNDEFINED)); } // Copying constructors @@ -1753,18 +1765,12 @@ public class GridLayout extends ViewGroup { */ public LayoutParams(LayoutParams that) { super(that); - this.columnSpec = new Spec(that.columnSpec); this.rowSpec = new Spec(that.rowSpec); + this.columnSpec = new Spec(that.columnSpec); } // AttributeSet constructors - private LayoutParams(Context context, AttributeSet attrs, int defaultGravity) { - super(context, attrs); - reInitSuper(context, attrs); - init(context, attrs, defaultGravity); - } - /** * {@inheritDoc} * @@ -1772,27 +1778,13 @@ public class GridLayout extends ViewGroup { * defined in {@link LayoutParams}. */ public LayoutParams(Context context, AttributeSet attrs) { - this(context, attrs, Gravity.NO_GRAVITY); + super(context, attrs); + reInitSuper(context, attrs); + init(context, attrs); } // Implementation - private static boolean definesVertical(int gravity) { - return gravity > 0 && (gravity & Gravity.VERTICAL_GRAVITY_MASK) != 0; - } - - private static boolean definesHorizontal(int gravity) { - return gravity > 0 && (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) != 0; - } - - private static <T> T getAlignment(T[] alignments, T fill, int min, int max, - boolean isUndefined, T defaultValue) { - if (isUndefined) { - return defaultValue; - } - return min != max ? fill : alignments[min]; - } - // Reinitialise the margins using a different default policy than MarginLayoutParams. // Here we use the value UNDEFINED (as distinct from zero) to represent the undefined state // so that a layout manager default can be accessed post set up. We need this as, at the @@ -1817,44 +1809,20 @@ public class GridLayout extends ViewGroup { } } - // Gravity. For conversion from the static the integers defined in the Gravity class, - // use Gravity.apply() to apply gravity to a view of zero size and see where it ends up. - private static Alignment getColAlignment(int gravity, int width) { - Rect r = new Rect(0, 0, 0, 0); - Gravity.apply(gravity, 0, 0, CONTAINER_BOUNDS, r); - - boolean fill = (width == MATCH_PARENT); - Alignment defaultAlignment = fill ? FILL : DEFAULT_COLUMN_ALIGNMENT; - return getAlignment(COLUMN_ALIGNMENTS, FILL, r.left, r.right, - !definesHorizontal(gravity), defaultAlignment); - } - - private static Alignment getRowAlignment(int gravity, int height) { - Rect r = new Rect(0, 0, 0, 0); - Gravity.apply(gravity, 0, 0, CONTAINER_BOUNDS, r); - - boolean fill = (height == MATCH_PARENT); - Alignment defaultAlignment = fill ? FILL : DEFAULT_ROW_ALIGNMENT; - return getAlignment(ROW_ALIGNMENTS, FILL, r.top, r.bottom, - !definesVertical(gravity), defaultAlignment); - } - - private void init(Context context, AttributeSet attrs, int defaultGravity) { + private void init(Context context, AttributeSet attrs) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GridLayout_Layout); try { - int gravity = a.getInt(GRAVITY, defaultGravity); + int gravity = a.getInt(GRAVITY, Gravity.NO_GRAVITY); int column = a.getInt(COLUMN, DEFAULT_COLUMN); - int columnSpan = a.getInt(COLUMN_SPAN, DEFAULT_SPAN_SIZE); - Interval hSpan = new Interval(column, column + columnSpan); - int hFlexibility = a.getInt(COLUMN_FLEXIBILITY, Spec.DEFAULT_FLEXIBILITY); - this.columnSpec = new Spec(hSpan, getColAlignment(gravity, width), hFlexibility); + int colSpan = a.getInt(COLUMN_SPAN, DEFAULT_SPAN_SIZE); + int hFlexibility = a.getInt(COLUMN_FLEXIBILITY, Spec.UNDEFINED_FLEXIBILITY); + this.columnSpec = spec(column, colSpan, getAlignment(gravity, true), hFlexibility); int row = a.getInt(ROW, DEFAULT_ROW); int rowSpan = a.getInt(ROW_SPAN, DEFAULT_SPAN_SIZE); - Interval vSpan = new Interval(row, row + rowSpan); - int vFlexibility = a.getInt(ROW_FLEXIBILITY, Spec.DEFAULT_FLEXIBILITY); - this.rowSpec = new Spec(vSpan, getRowAlignment(gravity, height), vFlexibility); + int vFlexibility = a.getInt(ROW_FLEXIBILITY, Spec.UNDEFINED_FLEXIBILITY); + this.rowSpec = spec(row, rowSpan, getAlignment(gravity, false), vFlexibility); } finally { a.recycle(); } @@ -1869,8 +1837,8 @@ public class GridLayout extends ViewGroup { * @attr ref android.R.styleable#GridLayout_Layout_layout_gravity */ public void setGravity(int gravity) { - columnSpec = columnSpec.copyWriteAlignment(getColAlignment(gravity, width)); - rowSpec = rowSpec.copyWriteAlignment(getRowAlignment(gravity, height)); + rowSpec = rowSpec.copyWriteAlignment(getAlignment(gravity, false)); + columnSpec = columnSpec.copyWriteAlignment(getAlignment(gravity, true)); } @Override @@ -2045,7 +2013,7 @@ public class GridLayout extends ViewGroup { public int before; public int after; - public int flexibility; + public int flexibility; // we're flexible iff all included specs are flexible private Bounds() { reset(); @@ -2054,7 +2022,7 @@ public class GridLayout extends ViewGroup { protected void reset() { before = Integer.MIN_VALUE; after = Integer.MIN_VALUE; - flexibility = UNDEFINED_FLEXIBILITY; + flexibility = CAN_STRETCH; // from the above, we're flexible when empty } protected void include(int before, int after) { @@ -2064,10 +2032,7 @@ public class GridLayout extends ViewGroup { protected int size(boolean min) { if (!min) { - // Note in the usual case, components don't define anything - // leaving their flexibility is undefined and their stretchability - // defined as if the CAN_STRETCH flag was false. - if (canStretch(flexibility) && !isUndefined(flexibility)) { + if (canStretch(flexibility)) { return MAX_SIZE; } } @@ -2078,11 +2043,12 @@ public class GridLayout extends ViewGroup { return before - alignment.getAlignmentValue(c, size); } - protected void include(View c, Spec spec, GridLayout gridLayout, Axis axis) { - this.flexibility &= spec.flexibility; + protected final void include(View c, Spec spec, GridLayout gridLayout, Axis axis) { + this.flexibility &= spec.getFlexibility(); int size = gridLayout.getMeasurementIncludingMargin(c, axis.horizontal); // todo test this works correctly when the returned value is UNDEFINED - int before = spec.alignment.getAlignmentValue(c, size); + Alignment alignment = gridLayout.getAlignment(spec.alignment, axis.horizontal); + int before = alignment.getAlignmentValue(c, size); include(before, size - before); } @@ -2107,8 +2073,6 @@ public class GridLayout extends ViewGroup { * {@code x} such that {@code min <= x < max}. */ static class Interval { - private static final Interval GONE = new Interval(UNDEFINED, UNDEFINED); - /** * The minimum value. */ @@ -2186,40 +2150,38 @@ public class GridLayout extends ViewGroup { } } - /** - * A spec defines either the horizontal or vertical characteristics of a group of - * cells. - */ + /** + * A Spec defines the horizontal or vertical characteristics of a group of + * cells. Each spec. defines the <em>grid indices</em>, <em>alignment</em> and + * <em>flexibility</em> along the appropriate axis. + * <p> + * The <em>grid indices</em> are the leading and trailing edges of this cell group. + * See {@link GridLayout} for a description of the conventions used by GridLayout + * for grid indices. + * <p> + * The <em>alignment</em> property specifies how cells should be aligned in this group. + * For row groups, this specifies the vertical alignment. + * For column groups, this specifies the horizontal alignment. + */ public static class Spec { - private static final int DEFAULT_FLEXIBILITY = UNDEFINED_FLEXIBILITY; - - private static final Spec GONE = new Spec(Interval.GONE, Alignment.GONE); + private static final int UNDEFINED_FLEXIBILITY = UNDEFINED; - /** - * The grid indices of the leading and trailing edges of this cell group for the - * appropriate axis. - * <p> - * See {@link GridLayout} for a description of the conventions used by GridLayout - * for grid indices. - */ final Interval span; - /** - * Specifies how cells should be aligned in this group. - * For row groups, this specifies the vertical alignment. - * For column groups, this specifies the horizontal alignment. - */ + final Alignment alignment; - /** - * The flexibility field tells GridLayout how to derive minimum and maximum size - * values for a component. Specifications are made with respect to a child's - * 'measured size'. A child's measured size is, in turn, controlled by its - * height and width layout parameters which either specify a size or, in - * the case of {@link LayoutParams#WRAP_CONTENT WRAP_CONTENT}, defer to - * the computed size of the component. - * - * @see GridLayout#CAN_STRETCH - */ + /** + * The <em>flexibility</em> property tells GridLayout how to derive minimum and maximum size + * values for a component. Specifications are made with respect to a child's + * 'measured size'. A child's measured size is, in turn, controlled by its + * height and width layout parameters which either specify a size or, in + * the case of {@link LayoutParams#WRAP_CONTENT WRAP_CONTENT}, defer to + * the computed size of the component. + * <p> + * A cell group is flexible only if <em>all</em> of its components are flexible. + * <p> + * By default, flexibility is {@link #INFLEXIBLE} only when alignment/gravity is undefined. + */ final int flexibility; private Spec(Interval span, Alignment alignment, int flexibility) { @@ -2229,7 +2191,7 @@ public class GridLayout extends ViewGroup { } private Spec(Interval span, Alignment alignment) { - this(span, alignment, DEFAULT_FLEXIBILITY); + this(span, alignment, UNDEFINED_FLEXIBILITY); } /* Copying constructor */ @@ -2249,8 +2211,14 @@ public class GridLayout extends ViewGroup { return new Spec(span, alignment, flexibility); } - private Spec copyWriteFlexibility(int flexibility) { - return new Spec(span, alignment, flexibility); + private static int defaultFlexibility(Alignment alignment) { + return (alignment == UNDEFINED_ALIGNMENT) ? INFLEXIBLE : CAN_STRETCH; + } + + int getFlexibility() { + return (flexibility != UNDEFINED_FLEXIBILITY) ? + flexibility : + defaultFlexibility(alignment); } /** @@ -2293,34 +2261,23 @@ public class GridLayout extends ViewGroup { } /** - * Return a Spec, {@code spec}, where: - * <ul> - * <li> {@code spec.span = [start, start + size]} </li> - * <li> {@code spec.alignment = alignment} </li> - * <li> {@code spec.flexibility = flexibility} </li> - * </ul> + * @deprecated Please use {@link #spec(int, int, Alignment)} instead, + * all spec's that define alignments (gravity) are assumed to be able to stretch. * - * @param start the start - * @param size the size - * @param alignment the alignment - * @param flexibility the flexibility + * @hide */ + @Deprecated public static Spec spec(int start, int size, Alignment alignment, int flexibility) { return new Spec(start, size, alignment, flexibility); } /** - * Return a Spec, {@code spec}, where: - * <ul> - * <li> {@code spec.span = [start, start + 1]} </li> - * <li> {@code spec.alignment = alignment} </li> - * <li> {@code spec.flexibility = flexibility} </li> - * </ul> + * @deprecated Please use {@link #spec(int, Alignment)} instead, + * all spec's that define alignments (gravity) are assumed to be able to stretch. * - * @param start the start - * @param alignment the alignment - * @param flexibility the flexibility + * @hide */ + @Deprecated public static Spec spec(int start, Alignment alignment, int flexibility) { return spec(start, 1, alignment, flexibility); } @@ -2337,7 +2294,7 @@ public class GridLayout extends ViewGroup { * @param alignment the alignment */ public static Spec spec(int start, int size, Alignment alignment) { - return spec(start, size, alignment, Spec.DEFAULT_FLEXIBILITY); + return spec(start, size, alignment, Spec.UNDEFINED_FLEXIBILITY); } /** @@ -2355,6 +2312,31 @@ public class GridLayout extends ViewGroup { } /** + * Return a Spec, {@code spec}, where: + * <ul> + * <li> {@code spec.span = [start, start + size]} </li> + * </ul> + * + * @param start the start + * @param size the size + */ + public static Spec spec(int start, int size) { + return spec(start, size, UNDEFINED_ALIGNMENT); + } + + /** + * Return a Spec, {@code spec}, where: + * <ul> + * <li> {@code spec.span = [start, start + 1]} </li> + * </ul> + * + * @param start the start index + */ + public static Spec spec(int start) { + return spec(start, 1); + } + + /** * Alignments specify where a view should be placed within a cell group and * what size it should be. * <p> @@ -2376,13 +2358,6 @@ public class GridLayout extends ViewGroup { * <p> */ public static abstract class Alignment { - private static final Alignment GONE = new Alignment() { - public int getAlignmentValue(View view, int viewSize) { - assert false; - return 0; - } - }; - Alignment() { } @@ -2422,11 +2397,16 @@ public class GridLayout extends ViewGroup { } } + private static final Alignment UNDEFINED_ALIGNMENT = new Alignment() { + public int getAlignmentValue(View view, int viewSize) { + return UNDEFINED; + } + }; + private static final Alignment LEADING = new Alignment() { public int getAlignmentValue(View view, int viewSize) { return 0; } - }; private static final Alignment TRAILING = new Alignment() { @@ -2542,38 +2522,17 @@ public class GridLayout extends ViewGroup { return (flexibility & CAN_STRETCH) != 0; } - private static boolean isUndefined(int flexibility) { - return (flexibility & UNDEFINED) != 0; - } - - /** - * Indicates that a view requests precisely the size specified by its layout parameters. - * - * @see Spec#flexibility - */ - private static final int NONE = 0; - - /** - * Indicates that a view's size should lie between its minimum and the size specified by - * its layout parameters. - * - * @see Spec#flexibility - */ - private static final int CAN_SHRINK = 1; + private static final int INFLEXIBLE = 0; /** * Indicates that a view's size should be greater than or equal to the size specified by * its layout parameters. * - * @see Spec#flexibility - */ - public static final int CAN_STRETCH = 2; - - /** - * A default value for flexibility. + * @deprecated Please use {@link #spec(int, int, Alignment)} instead, + * all spec's that define alignment (gravity) are assumed to able to stretch. * - * @see Spec#flexibility + * @hide */ - private static final int UNDEFINED_FLEXIBILITY = UNDEFINED | CAN_SHRINK | CAN_STRETCH; - + @Deprecated + public static final int CAN_STRETCH = 2; } diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 563fc26aa6e5..36927ca434ef 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -91,6 +91,7 @@ public class PopupWindow { private boolean mLayoutInScreen; private boolean mClipToScreen; private boolean mAllowScrollingAnchorParent = true; + private boolean mLayoutInsetDecor = false; private OnTouchListener mTouchInterceptor; @@ -658,6 +659,22 @@ public class PopupWindow { } /** + * Allows the popup window to force the flag + * {@link WindowManager.LayoutParams#FLAG_LAYOUT_INSET_DECOR}, overriding default behavior. + * This will cause the popup to inset its content to account for system windows overlaying + * the screen, such as the status bar. + * + * <p>This will often be combined with {@link #setLayoutInScreenEnabled(boolean)}. + * + * @param enabled true if the popup's views should inset content to account for system windows, + * the way that decor views behave for full-screen windows. + * @hide + */ + public void setLayoutInsetDecor(boolean enabled) { + mLayoutInsetDecor = enabled; + } + + /** * Set the layout type for this window. Should be one of the TYPE constants defined in * {@link WindowManager.LayoutParams}. * @@ -942,6 +959,7 @@ public class PopupWindow { if (mContext != null) { p.packageName = mContext.getPackageName(); } + mPopupView.setFitsSystemWindows(mLayoutInsetDecor); mWindowManager.addView(mPopupView, p); } @@ -1012,6 +1030,9 @@ public class PopupWindow { if (mLayoutInScreen) { curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; } + if (mLayoutInsetDecor) { + curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; + } return curFlags; } diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java index b2d1a1e53573..55b73dffb4a6 100644 --- a/core/java/android/widget/SearchView.java +++ b/core/java/android/widget/SearchView.java @@ -45,6 +45,7 @@ import android.text.style.ImageSpan; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; +import android.view.CollapsibleActionView; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; @@ -58,18 +59,30 @@ import com.android.internal.R; import java.util.WeakHashMap; /** - * A widget that provides a user interface for the user to enter a search query and submit a - * request to a search provider. Shows a list of query suggestions or results, if - * available, and allows the user to pick a suggestion or result to launch into. + * A widget that provides a user interface for the user to enter a search query and submit a request + * to a search provider. Shows a list of query suggestions or results, if available, and allows the + * user to pick a suggestion or result to launch into. * - * <p>For more information, see the <a href="{@docRoot}guide/topics/search/index.html">Search</a> - * documentation.<p> + * <p> + * When the SearchView is used in an ActionBar as an action view for a collapsible menu item, it + * needs to be set to iconified by default using {@link #setIconifiedByDefault(boolean) + * setIconifiedByDefault(true)}. This is the default, so nothing needs to be done. + * </p> + * <p> + * If you want the search field to always be visible, then call setIconifiedByDefault(false). + * </p> * + * <p> + * For more information, see the <a href="{@docRoot}guide/topics/search/index.html">Search</a> + * documentation. + * <p> + * + * @see android.view.MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW * @attr ref android.R.styleable#SearchView_iconifiedByDefault * @attr ref android.R.styleable#SearchView_maxWidth * @attr ref android.R.styleable#SearchView_queryHint */ -public class SearchView extends LinearLayout { +public class SearchView extends LinearLayout implements CollapsibleActionView { private static final boolean DBG = false; private static final String LOG_TAG = "SearchView"; @@ -100,6 +113,7 @@ public class SearchView extends LinearLayout { private int mMaxWidth; private boolean mVoiceButtonEnabled; private CharSequence mUserQuery; + private boolean mExpandedInActionView; private SearchableInfo mSearchable; private Bundle mAppSearchData; @@ -623,7 +637,7 @@ public class SearchView extends LinearLayout { final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText()); // Should we show the close button? It is not shown if there's no focus, // field is not iconified by default and there is no text in it. - final boolean showClose = hasText || mIconifiedByDefault; + final boolean showClose = hasText || (mIconifiedByDefault && !mExpandedInActionView); mCloseButton.setVisibility(showClose ? VISIBLE : INVISIBLE); mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET); } @@ -1022,6 +1036,25 @@ public class SearchView extends LinearLayout { super.onAttachedToWindow(); } + /** + * {@inheritDoc} + */ + @Override + public void onActionViewCollapsed() { + mQueryTextView.setText(""); + setIconified(true); + mExpandedInActionView = false; + } + + /** + * {@inheritDoc} + */ + @Override + public void onActionViewExpanded() { + mExpandedInActionView = true; + setIconified(false); + } + private void adjustDropDownSizeAndPosition() { if (mDropDownAnchor.getWidth() > 1) { Resources res = getContext().getResources(); diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java index b7565f3129d5..0c80a1170b13 100644 --- a/core/java/android/widget/Switch.java +++ b/core/java/android/widget/Switch.java @@ -34,6 +34,7 @@ import android.view.Gravity; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.ViewConfiguration; +import android.view.accessibility.AccessibilityEvent; import com.android.internal.R; @@ -360,6 +361,13 @@ public class Switch extends CompoundButton { } } + @Override + public void onPopulateAccessibilityEvent(AccessibilityEvent event) { + super.onPopulateAccessibilityEvent(event); + Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout; + event.getText().add(switchText.getText()); + } + private Layout makeLayout(CharSequence text) { return new StaticLayout(text, mTextPaint, (int) Math.ceil(Layout.getDesiredWidth(text, mTextPaint)), diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index bd70dad7de21..29290560124d 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -167,11 +167,11 @@ static void audioCallback(int event, void* user, void *info) { // ---------------------------------------------------------------------------- static int android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, - jint streamType, jint sampleRateInHertz, jint channels, + jint streamType, jint sampleRateInHertz, jint javaChannelMask, jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession) { - LOGV("sampleRate=%d, audioFormat(from Java)=%d, channels=%x, buffSize=%d", - sampleRateInHertz, audioFormat, channels, buffSizeInBytes); + LOGV("sampleRate=%d, audioFormat(from Java)=%d, channel mask=%x, buffSize=%d", + sampleRateInHertz, audioFormat, javaChannelMask, buffSizeInBytes); int afSampleRate; int afFrameCount; @@ -184,11 +184,16 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th return AUDIOTRACK_ERROR_SETUP_AUDIOSYSTEM; } - if (!audio_is_output_channel(channels)) { + // Java channel masks don't map directly to the native definition, but it's a simple shift + // to skip the two deprecated channel configurations "default" and "mono". + uint32_t nativeChannelMask = ((uint32_t)javaChannelMask) >> 2; + + if (!audio_is_output_channel(nativeChannelMask)) { LOGE("Error creating AudioTrack: invalid channel mask."); return AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK; } - int nbChannels = popcount(channels); + + int nbChannels = popcount(nativeChannelMask); // check the stream type audio_stream_type_t atStreamType; @@ -285,7 +290,7 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th atStreamType,// stream type sampleRateInHertz, format,// word length, PCM - channels, + nativeChannelMask, frameCount, 0,// flags audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user) @@ -306,7 +311,7 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th atStreamType,// stream type sampleRateInHertz, format,// word length, PCM - channels, + nativeChannelMask, frameCount, 0,// flags audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)); diff --git a/core/jni/android_text_format_Time.cpp b/core/jni/android_text_format_Time.cpp index c152aa8351af..69c6021e22e8 100644 --- a/core/jni/android_text_format_Time.cpp +++ b/core/jni/android_text_format_Time.cpp @@ -641,7 +641,7 @@ static JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ { "normalize", "(Z)J", (void*)android_text_format_Time_normalize }, { "switchTimezone", "(Ljava/lang/String;)V", (void*)android_text_format_Time_switchTimezone }, - { "compare", "(Landroid/text/format/Time;Landroid/text/format/Time;)I", (void*)android_text_format_Time_compare }, + { "nativeCompare", "(Landroid/text/format/Time;Landroid/text/format/Time;)I", (void*)android_text_format_Time_compare }, { "format1", "(Ljava/lang/String;)Ljava/lang/String;", (void*)android_text_format_Time_format }, { "format2445", "()Ljava/lang/String;", (void*)android_text_format_Time_format2445 }, { "toString", "()Ljava/lang/String;", (void*)android_text_format_Time_toString }, diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 0dc92934fdd9..4c1ca313feff 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -22,6 +22,7 @@ #include "android/graphics/GraphicsJNI.h" #include <binder/IMemory.h> +#include <gui/SurfaceTexture.h> #include <surfaceflinger/SurfaceComposerClient.h> #include <surfaceflinger/Surface.h> #include <ui/Region.h> @@ -38,6 +39,7 @@ #include "JNIHelp.h" #include <android_runtime/AndroidRuntime.h> #include <android_runtime/android_view_Surface.h> +#include <android_runtime/android_graphics_SurfaceTexture.h> #include <utils/misc.h> @@ -244,6 +246,19 @@ static void Surface_init( setSurfaceControl(env, clazz, surface); } +static void Surface_initFromSurfaceTexture( + JNIEnv* env, jobject clazz, jobject jst) +{ + sp<ISurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, jst)); + sp<Surface> surface(new Surface(st)); + if (surface == NULL) { + jniThrowException(env, OutOfResourcesException, NULL); + return; + } + setSurfaceControl(env, clazz, NULL); + setSurface(env, clazz, surface); +} + static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel) { Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel); @@ -761,10 +776,26 @@ static void Surface_writeToParcel( return; } + // The Java instance may have a SurfaceControl (in the case of the + // WindowManager or a system app). In that case, we defer to the + // SurfaceControl to send its ISurface. Otherwise, if the Surface is + // available we let it parcel itself. Finally, if the Surface is also + // NULL we fall back to using the SurfaceControl path which sends an + // empty surface; this matches legacy behavior. const sp<SurfaceControl>& control(getSurfaceControl(env, clazz)); - SurfaceControl::writeSurfaceToParcel(control, parcel); + if (control != NULL) { + SurfaceControl::writeSurfaceToParcel(control, parcel); + } else { + sp<Surface> surface(Surface_getSurface(env, clazz)); + if (surface != NULL) { + Surface::writeToParcel(surface, parcel); + } else { + SurfaceControl::writeSurfaceToParcel(NULL, parcel); + } + } if (flags & PARCELABLE_WRITE_RETURN_VALUE) { - setSurfaceControl(env, clazz, 0); + setSurfaceControl(env, clazz, NULL); + setSurface(env, clazz, NULL); } } @@ -784,6 +815,7 @@ static JNINativeMethod gSurfaceMethods[] = { {"nativeClassInit", "()V", (void*)nativeClassInit }, {"init", "(Landroid/view/SurfaceSession;ILjava/lang/String;IIIII)V", (void*)Surface_init }, {"init", "(Landroid/os/Parcel;)V", (void*)Surface_initParcel }, + {"initFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V", (void*)Surface_initFromSurfaceTexture }, {"getIdentity", "()I", (void*)Surface_getIdentity }, {"destroy", "()V", (void*)Surface_destroy }, {"release", "()V", (void*)Surface_release }, diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 7d7aea920012..88ab983e40cd 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2278,6 +2278,8 @@ <flag name="feedbackVisual" value="0x00000008" /> <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_GENERIC} feedback. --> <flag name="feedbackGeneric" value="0x00000010" /> + <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_ALL_MASK} feedback. --> + <flag name="feedbackAllMask" value="0xffffffff" /> </attr> <!-- The minimal period in milliseconds between two accessibility events of the same type are sent to this serivce. This setting can be changed at runtime by calling @@ -3359,18 +3361,16 @@ The default is LEFT | BASELINE. See {@link android.widget.GridLayout.LayoutParams#setGravity(int)}. --> <attr name="layout_gravity" /> - <!-- A value specifying how much deficit or excess width this component can accomodate. - The default is FIXED. --> + <!-- {@deprecated To make a column group lexible, ensure that every component in the + group defines a horizontal gravity.} --> <attr name="layout_columnFlexibility" > - <!-- If possible, width should be greater than or equal to the specified width. - See {@link android.widget.GridLayout#CAN_STRETCH}. --> + <enum name="inflexible" value="0" /> <enum name="canStretch" value="2" /> </attr> - <!-- A value specifying how much deficit or excess height this component can accomodate. - The default is FIXED. --> + <!-- {@deprecated To make a row group flexible, ensure that every component in the + group defines a vertical gravity.} --> <attr name="layout_rowFlexibility" > - <!-- If possible, height should be greater than or equal to the specified height. - See {@link android.widget.GridLayout#CAN_STRETCH}. --> + <enum name="inflexible" value="0" /> <enum name="canStretch" value="2" /> </attr> </declare-styleable> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 2b2f356fc724..65dce4977eeb 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -469,6 +469,10 @@ speech --> <bool name="config_bluetooth_wide_band_speech">true</bool> + <!-- Boolean indicating if current platform supports quick switch-on/off of + Bluetooth Module --> + <bool name="config_bluetooth_adapter_quick_switch">true</bool> + <!-- The default data-use polling period. --> <integer name="config_datause_polling_period_sec">600</integer> diff --git a/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java b/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java index bbf1696eb25b..4814c61abe7c 100644 --- a/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java +++ b/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java @@ -65,13 +65,13 @@ public class RecycleAccessibilityEventTest extends TestCase { assertEquals(0, first.getText().size()); assertFalse(first.isChecked()); assertNull(first.getContentDescription()); - assertEquals(0, first.getItemCount()); + assertEquals(-1, first.getItemCount()); assertEquals(AccessibilityEvent.INVALID_POSITION, first.getCurrentItemIndex()); assertFalse(first.isEnabled()); assertFalse(first.isPassword()); - assertEquals(0, first.getFromIndex()); - assertEquals(0, first.getAddedCount()); - assertEquals(0, first.getRemovedCount()); + assertEquals(-1, first.getFromIndex()); + assertEquals(-1, first.getAddedCount()); + assertEquals(-1, first.getRemovedCount()); // get another event from the pool (this must be the recycled first) AccessibilityEvent second = AccessibilityEvent.obtain(); diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp index 2d8e877b97d1..986f32c4037e 100644 --- a/drm/common/IDrmManagerService.cpp +++ b/drm/common/IDrmManagerService.cpp @@ -110,11 +110,11 @@ static void clearDecryptHandle(DecryptHandle* handle) { handle->extendedData.clear(); } -int BpDrmManagerService::addUniqueId(int uniqueId) { +int BpDrmManagerService::addUniqueId(bool isNative) { LOGV("add uniqueid"); Parcel data, reply; data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor()); - data.writeInt32(uniqueId); + data.writeInt32(isNative); remote()->transact(ADD_UNIQUEID, data, &reply); return reply.readInt32(); } diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp index 1809619d0262..3e4fe8c07d23 100644 --- a/drm/drmserver/DrmManager.cpp +++ b/drm/drmserver/DrmManager.cpp @@ -49,32 +49,42 @@ DrmManager::~DrmManager() { } -int DrmManager::addUniqueId(int uniqueId) { +int DrmManager::addUniqueId(bool isNative) { Mutex::Autolock _l(mLock); - if (0 == uniqueId) { - int temp = 0; - bool foundUniqueId = false; - srand(time(NULL)); - - while (!foundUniqueId) { - const int size = mUniqueIdVector.size(); - temp = rand() % 100; - - int index = 0; - for (; index < size; ++index) { - if (mUniqueIdVector.itemAt(index) == temp) { - foundUniqueId = false; - break; - } - } - if (index == size) { - foundUniqueId = true; + + int temp = 0; + bool foundUniqueId = false; + const int size = mUniqueIdVector.size(); + const int uniqueIdRange = 0xfff; + int maxLoopTimes = (uniqueIdRange - 1) / 2; + srand(time(NULL)); + + while (!foundUniqueId) { + temp = rand() & uniqueIdRange; + + if (isNative) { + // set a flag to differentiate DrmManagerClient + // created from native side and java side + temp |= 0x1000; + } + + int index = 0; + for (; index < size; ++index) { + if (mUniqueIdVector.itemAt(index) == temp) { + foundUniqueId = false; + break; } } - uniqueId = temp; + if (index == size) { + foundUniqueId = true; + } + + maxLoopTimes --; + LOG_FATAL_IF(maxLoopTimes <= 0, "cannot find an unique ID for this session"); } - mUniqueIdVector.push(uniqueId); - return uniqueId; + + mUniqueIdVector.push(temp); + return temp; } void DrmManager::removeUniqueId(int uniqueId) { diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp index 583669e980a0..7ebcac39380b 100644 --- a/drm/drmserver/DrmManagerService.cpp +++ b/drm/drmserver/DrmManagerService.cpp @@ -78,8 +78,8 @@ DrmManagerService::~DrmManagerService() { delete mDrmManager; mDrmManager = NULL; } -int DrmManagerService::addUniqueId(int uniqueId) { - return mDrmManager->addUniqueId(uniqueId); +int DrmManagerService::addUniqueId(bool isNative) { + return mDrmManager->addUniqueId(isNative); } void DrmManagerService::removeUniqueId(int uniqueId) { diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java index f3a034307ad9..9a7194c4d637 100755 --- a/drm/java/android/drm/DrmManagerClient.java +++ b/drm/java/android/drm/DrmManagerClient.java @@ -248,9 +248,7 @@ public class DrmManagerClient { mEventHandler = new EventHandler(eventThread.getLooper()); // save the unique id - mUniqueId = hashCode(); - - _initialize(mUniqueId, new WeakReference<DrmManagerClient>(this)); + mUniqueId = _initialize(new WeakReference<DrmManagerClient>(this)); } protected void finalize() { @@ -794,7 +792,7 @@ public class DrmManagerClient { } // private native interfaces - private native void _initialize(int uniqueId, Object weak_this); + private native int _initialize(Object weak_this); private native void _finalize(int uniqueId); diff --git a/drm/jni/android_drm_DrmManagerClient.cpp b/drm/jni/android_drm_DrmManagerClient.cpp index e13183990410..80a8447331a5 100644 --- a/drm/jni/android_drm_DrmManagerClient.cpp +++ b/drm/jni/android_drm_DrmManagerClient.cpp @@ -224,11 +224,12 @@ static sp<DrmManagerClientImpl> getDrmManagerClientImpl(JNIEnv* env, jobject thi return sp<DrmManagerClientImpl>(client); } -static void android_drm_DrmManagerClient_initialize( - JNIEnv* env, jobject thiz, jint uniqueId, jobject weak_thiz) { +static jint android_drm_DrmManagerClient_initialize( + JNIEnv* env, jobject thiz, jobject weak_thiz) { LOGV("initialize - Enter"); - sp<DrmManagerClientImpl> drmManager = DrmManagerClientImpl::create(&uniqueId); + int uniqueId = 0; + sp<DrmManagerClientImpl> drmManager = DrmManagerClientImpl::create(&uniqueId, false); drmManager->addClient(uniqueId); // Set the listener to DrmManager @@ -237,6 +238,8 @@ static void android_drm_DrmManagerClient_initialize( setDrmManagerClientImpl(env, thiz, drmManager); LOGV("initialize - Exit"); + + return uniqueId; } static void android_drm_DrmManagerClient_finalize(JNIEnv* env, jobject thiz, jint uniqueId) { @@ -711,7 +714,7 @@ static jobject android_drm_DrmManagerClient_closeConvertSession( static JNINativeMethod nativeMethods[] = { - {"_initialize", "(ILjava/lang/Object;)V", + {"_initialize", "(Ljava/lang/Object;)I", (void*)android_drm_DrmManagerClient_initialize}, {"_finalize", "(I)V", diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp index b50199f649f0..c9c0d57961b9 100644 --- a/drm/libdrmframework/DrmManagerClient.cpp +++ b/drm/libdrmframework/DrmManagerClient.cpp @@ -24,7 +24,7 @@ using namespace android; DrmManagerClient::DrmManagerClient(): mUniqueId(0), mDrmManagerClientImpl(NULL) { - mDrmManagerClientImpl = DrmManagerClientImpl::create(&mUniqueId); + mDrmManagerClientImpl = DrmManagerClientImpl::create(&mUniqueId, true); mDrmManagerClientImpl->addClient(mUniqueId); } diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp index a36bd4ae4023..67f58ca8fe20 100644 --- a/drm/libdrmframework/DrmManagerClientImpl.cpp +++ b/drm/libdrmframework/DrmManagerClientImpl.cpp @@ -33,13 +33,10 @@ sp<IDrmManagerService> DrmManagerClientImpl::sDrmManagerService; sp<DrmManagerClientImpl::DeathNotifier> DrmManagerClientImpl::sDeathNotifier; const String8 DrmManagerClientImpl::EMPTY_STRING(""); -DrmManagerClientImpl* DrmManagerClientImpl::create(int* pUniqueId) { - if (0 == *pUniqueId) { - int uniqueId = getDrmManagerService()->addUniqueId(*pUniqueId); - *pUniqueId = uniqueId; - } else { - getDrmManagerService()->addUniqueId(*pUniqueId); - } +DrmManagerClientImpl* DrmManagerClientImpl::create( + int* pUniqueId, bool isNative) { + *pUniqueId = getDrmManagerService()->addUniqueId(isNative); + return new DrmManagerClientImpl(); } diff --git a/drm/libdrmframework/include/DrmManager.h b/drm/libdrmframework/include/DrmManager.h index af2c2a8506d3..ac2b94606576 100644 --- a/drm/libdrmframework/include/DrmManager.h +++ b/drm/libdrmframework/include/DrmManager.h @@ -53,7 +53,7 @@ public: virtual ~DrmManager(); public: - int addUniqueId(int uniqueId); + int addUniqueId(bool isNative); void removeUniqueId(int uniqueId); diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h index 564896bdf366..e3338d9e8679 100644 --- a/drm/libdrmframework/include/DrmManagerClientImpl.h +++ b/drm/libdrmframework/include/DrmManagerClientImpl.h @@ -38,7 +38,7 @@ private: DrmManagerClientImpl() { } public: - static DrmManagerClientImpl* create(int* pUniqueId); + static DrmManagerClientImpl* create(int* pUniqueId, bool isNative); static void remove(int uniqueId); diff --git a/drm/libdrmframework/include/DrmManagerService.h b/drm/libdrmframework/include/DrmManagerService.h index 227496a8bac0..9cb5804e6915 100644 --- a/drm/libdrmframework/include/DrmManagerService.h +++ b/drm/libdrmframework/include/DrmManagerService.h @@ -46,7 +46,7 @@ private: virtual ~DrmManagerService(); public: - int addUniqueId(int uniqueId); + int addUniqueId(bool isNative); void removeUniqueId(int uniqueId); diff --git a/drm/libdrmframework/include/IDrmManagerService.h b/drm/libdrmframework/include/IDrmManagerService.h index 7727e551a5ef..b9618bbc27aa 100644 --- a/drm/libdrmframework/include/IDrmManagerService.h +++ b/drm/libdrmframework/include/IDrmManagerService.h @@ -81,7 +81,7 @@ public: DECLARE_META_INTERFACE(DrmManagerService); public: - virtual int addUniqueId(int uniqueId) = 0; + virtual int addUniqueId(bool isNative) = 0; virtual void removeUniqueId(int uniqueId) = 0; @@ -167,7 +167,7 @@ public: BpDrmManagerService(const sp<IBinder>& impl) : BpInterface<IDrmManagerService>(impl) {} - virtual int addUniqueId(int uniqueId); + virtual int addUniqueId(bool isNative); virtual void removeUniqueId(int uniqueId); diff --git a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h index b61e3d353a27..4a5afcf42c6b 100644 --- a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h +++ b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h @@ -143,7 +143,13 @@ protected: * Register a callback to be invoked when the caller required to * receive necessary information * - * @param[in] uniqueId Unique identifier for a session + * @param[in] uniqueId Unique identifier for a session. uniqueId is a random + * number generated in the DRM service. If the DrmManagerClient + * is created in native code, uniqueId will be a number ranged + * from 0x1000 to 0x1fff. If it comes from Java code, the uniqueId + * will be a number ranged from 0x00 to 0xfff. So bit 0x1000 in + * uniqueId could be used in DRM plugins to differentiate native + * OnInfoListener and Java OnInfoListener. * @param[in] infoListener Listener * @return status_t * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h index 134c208f4d26..2a8e7255602b 100644 --- a/include/gui/SurfaceTexture.h +++ b/include/gui/SurfaceTexture.h @@ -211,7 +211,6 @@ protected: // all slots. void freeAllBuffers(); static bool isExternalFormat(uint32_t format); - static GLenum getTextureTarget(uint32_t format); private: @@ -348,10 +347,6 @@ private: // reset mCurrentTexture to INVALID_BUFFER_SLOT. int mCurrentTexture; - // mCurrentTextureTarget is the GLES texture target to be used with the - // current texture. - GLenum mCurrentTextureTarget; - // mCurrentTextureBuf is the graphic buffer of the current texture. It's // possible that this buffer is not associated with any buffer slot, so we // must track it separately in order to support the getCurrentBuffer method. diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h index 496b23e5f04f..1417416538dc 100644 --- a/include/media/AudioEffect.h +++ b/include/media/AudioEffect.h @@ -21,6 +21,7 @@ #include <sys/types.h> #include <media/IAudioFlinger.h> +#include <media/IAudioPolicyService.h> #include <media/IEffect.h> #include <media/IEffectClient.h> #include <hardware/audio_effect.h> @@ -111,6 +112,36 @@ public: /* + * Returns a list of descriptors corresponding to the pre processings enabled by default + * on an AudioRecord with the supplied audio session ID. + * + * Parameters: + * audioSession: audio session ID. + * descriptors: address where the effect descriptors should be returned. + * count: as input, the maximum number of descriptor than should be returned + * as output, the number of descriptor returned if status is NO_ERROR or the actual + * number of enabled pre processings if status is NO_MEMORY + * + * Returned status (from utils/Errors.h) can be: + * NO_ERROR successful operation. + * NO_MEMORY the number of descriptor to return is more than the maximum number + * indicated by count. + * PERMISSION_DENIED could not get AudioFlinger interface + * NO_INIT effect library failed to initialize + * BAD_VALUE invalid audio session or descriptor pointers + * + * Returned value + * *descriptor updated with descriptors of pre processings enabled by default + * *count number of descriptors returned if returned status is N_ERROR. + * total number of pre processing enabled by default if returned status is + * NO_MEMORY. This happens if the count passed as input is less than the number + * of descriptors to return + */ + static status_t queryDefaultPreProcessing(int audioSession, + effect_descriptor_t *descriptors, + uint32_t *count); + + /* * Events used by callback function (effect_callback_t). */ enum event_type { diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h index 86b9f85f8635..ed265e16d704 100644 --- a/include/media/IAudioPolicyService.h +++ b/include/media/IAudioPolicyService.h @@ -85,6 +85,9 @@ public: int id) = 0; virtual status_t unregisterEffect(int id) = 0; virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const = 0; + virtual status_t queryDefaultPreProcessing(int audioSession, + effect_descriptor_t *descriptors, + uint32_t *count) = 0; }; diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h index 007aea6c0362..ec84e2574aed 100644 --- a/include/media/IMediaRecorder.h +++ b/include/media/IMediaRecorder.h @@ -43,7 +43,6 @@ public: virtual status_t setAudioEncoder(int ae) = 0; virtual status_t setOutputFile(const char* path) = 0; virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0; - virtual status_t setOutputFileAuxiliary(int fd) = 0; virtual status_t setVideoSize(int width, int height) = 0; virtual status_t setVideoFrameRate(int frames_per_second) = 0; virtual status_t setParameters(const String8& params) = 0; diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h index 72d3736296d1..30db64246a34 100644 --- a/include/media/mediarecorder.h +++ b/include/media/mediarecorder.h @@ -215,7 +215,6 @@ public: status_t setAudioEncoder(int ae); status_t setOutputFile(const char* path); status_t setOutputFile(int fd, int64_t offset, int64_t length); - status_t setOutputFileAuxiliary(int fd); status_t setVideoSize(int width, int height); status_t setVideoFrameRate(int frames_per_second); status_t setParameters(const String8& params); @@ -249,7 +248,6 @@ private: bool mIsAudioEncoderSet; bool mIsVideoEncoderSet; bool mIsOutputFileSet; - bool mIsAuxiliaryOutputFileSet; Mutex mLock; Mutex mNotifyLock; }; diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h index f07ebbab2803..0e264c7be02a 100644 --- a/include/media/stagefright/CameraSourceTimeLapse.h +++ b/include/media/stagefright/CameraSourceTimeLapse.h @@ -53,27 +53,10 @@ public: void startQuickReadReturns(); private: - // If true, will use still camera takePicture() for time lapse frames - // If false, will use the videocamera frames instead. - bool mUseStillCameraForTimeLapse; - - // Size of picture taken from still camera. This may be larger than the size - // of the video, as still camera may not support the exact video resolution - // demanded. See setPictureSizeToClosestSupported(). - int32_t mPictureWidth; - int32_t mPictureHeight; - // size of the encoded video. int32_t mVideoWidth; int32_t mVideoHeight; - // True if we need to crop the still camera image to get the video frame. - bool mNeedCropping; - - // Start location of the cropping rectangle. - int32_t mCropRectStartX; - int32_t mCropRectStartY; - // Time between capture of two frames during time lapse recording // Negative value indicates that timelapse is disabled. int64_t mTimeBetweenTimeLapseFrameCaptureUs; @@ -84,9 +67,6 @@ private: // Real timestamp of the last encoded time lapse frame int64_t mLastTimeLapseFrameRealTimestampUs; - // Thread id of thread which takes still picture and sleeps in a loop. - pthread_t mThreadTimeLapse; - // Variable set in dataCallbackTimestamp() to help skipCurrentFrame() // to know if current frame needs to be skipped. bool mSkipCurrentFrame; @@ -111,9 +91,6 @@ private: // Lock for accessing quick stop variables. Mutex mQuickStopLock; - // Condition variable to wake up still picture thread. - Condition mTakePictureCondition; - // mQuickStop is set to true if we use quick read() returns, otherwise it is set // to false. Once in this mode read() return a copy of the last read frame // with the same time stamp. See startQuickReadReturns(). @@ -148,32 +125,13 @@ private: // Wrapper over CameraSource::read() to implement quick stop. virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL); - // For still camera case starts a thread which calls camera's takePicture() - // in a loop. For video camera case, just starts the camera's video recording. - virtual void startCameraRecording(); - - // For still camera case joins the thread created in startCameraRecording(). // For video camera case, just stops the camera's video recording. virtual void stopCameraRecording(); - // For still camera case don't need to do anything as memory is locally - // allocated with refcounting. - // For video camera case just tell the camera to release the frame. - virtual void releaseRecordingFrame(const sp<IMemory>& frame); - // mSkipCurrentFrame is set to true in dataCallbackTimestamp() if the current // frame needs to be skipped and this function just returns the value of mSkipCurrentFrame. virtual bool skipCurrentFrame(int64_t timestampUs); - // Handles the callback to handle raw frame data from the still camera. - // Creates a copy of the frame data as the camera can reuse the frame memory - // once this callback returns. The function also sets a new timstamp corresponding - // to one frame time ahead of the last encoded frame's time stamp. It then - // calls dataCallbackTimestamp() of the base class with the copied data and the - // modified timestamp, which will think that it recieved the frame from a video - // camera and proceed as usual. - virtual void dataCallback(int32_t msgType, const sp<IMemory> &data); - // In the video camera case calls skipFrameAndModifyTimeStamp() to modify // timestamp and set mSkipCurrentFrame. // Then it calls the base CameraSource::dataCallbackTimestamp() @@ -189,24 +147,6 @@ private: // Otherwise returns false. bool trySettingVideoSize(int32_t width, int32_t height); - // The still camera may not support the demanded video width and height. - // We look for the supported picture sizes from the still camera and - // choose the smallest one with either dimensions higher than the corresponding - // video dimensions. The still picture will be cropped to get the video frame. - // The function returns true if the camera supports picture sizes greater than - // or equal to the passed in width and height, and false otherwise. - bool setPictureSizeToClosestSupported(int32_t width, int32_t height); - - // Computes the offset of the rectangle from where to start cropping the - // still image into the video frame. We choose the center of the image to be - // cropped. The offset is stored in (mCropRectStartX, mCropRectStartY). - bool computeCropRectangleOffset(); - - // Crops the source data into a smaller image starting at - // (mCropRectStartX, mCropRectStartY) and of the size of the video frame. - // The data is returned into a newly allocated IMemory. - sp<IMemory> cropYUVImage(const sp<IMemory> &source_data); - // When video camera is used for time lapse capture, returns true // until enough time has passed for the next time lapse frame. When // the frame needs to be encoded, it returns false and also modifies @@ -217,22 +157,6 @@ private: // Wrapper to enter threadTimeLapseEntry() static void *ThreadTimeLapseWrapper(void *me); - // Runs a loop which sleeps until a still picture is required - // and then calls mCamera->takePicture() to take the still picture. - // Used only in the case mUseStillCameraForTimeLapse = true. - void threadTimeLapseEntry(); - - // Wrapper to enter threadStartPreview() - static void *ThreadStartPreviewWrapper(void *me); - - // Starts the camera's preview. - void threadStartPreview(); - - // Starts thread ThreadStartPreviewWrapper() for restarting preview. - // Needs to be done in a thread so that dataCallback() which calls this function - // can return, and the camera can know that takePicture() is done. - void restartPreview(); - // Creates a copy of source_data into a new memory of final type MemoryBase. sp<IMemory> createIMemoryCopy(const sp<IMemory> &source_data); diff --git a/include/media/stagefright/MetadataBufferType.h b/include/media/stagefright/MetadataBufferType.h index 52a3257d7b91..4eaf8ac2990e 100644 --- a/include/media/stagefright/MetadataBufferType.h +++ b/include/media/stagefright/MetadataBufferType.h @@ -69,6 +69,16 @@ typedef enum { * kMetadataBufferTypeGrallocSource is used to indicate that * the payload of the metadata buffers can be interpreted as * a buffer_handle_t. + * So in this case,the metadata that the encoder receives + * will have a byte stream that consists of two parts: + * 1. First, there is an integer indicating that it is a GRAlloc + * source (kMetadataBufferTypeGrallocSource) + * 2. This is followed by the buffer_handle_t that is a handle to the + * GRalloc buffer. The encoder needs to interpret this GRalloc handle + * and encode the frames. + * -------------------------------------------------------------- + * | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) | + * -------------------------------------------------------------- */ kMetadataBufferTypeGrallocSource = 1, diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h index 56bd9c315005..fab258c2272d 100644 --- a/include/media/stagefright/SurfaceMediaSource.h +++ b/include/media/stagefright/SurfaceMediaSource.h @@ -63,6 +63,10 @@ public: MediaBuffer **buffer, const ReadOptions *options = NULL); virtual sp<MetaData> getFormat(); + // Pass the metadata over to the buffer, call when you have the lock + void passMetadataBufferLocked(MediaBuffer **buffer); + bool checkBufferMatchesSlot(int slot, MediaBuffer *buffer); + // Get / Set the frame rate used for encoding. Default fps = 30 status_t setFrameRate(int32_t fps) ; int32_t getFrameRate( ) const; @@ -152,7 +156,7 @@ public: status_t setBufferCountServer(int bufferCount); // getTimestamp retrieves the timestamp associated with the image - // set by the most recent call to updateFrameInfoLocked(). + // set by the most recent call to read() // // The timestamp is in nanoseconds, and is monotonically increasing. Its // other semantics (zero point, etc) are source-dependent and should be diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h index 9c352ad9ab53..0460bbd35a8b 100644 --- a/include/surfaceflinger/Surface.h +++ b/include/surfaceflinger/Surface.h @@ -122,7 +122,10 @@ public: uint32_t reserved[2]; }; + explicit Surface(const sp<ISurfaceTexture>& st); + static status_t writeToParcel(const sp<Surface>& control, Parcel* parcel); + static sp<Surface> readFromParcel(const Parcel& data); static bool isValid(const sp<Surface>& surface) { return (surface != 0) && surface->isValid(); @@ -147,14 +150,14 @@ private: Surface& operator = (Surface& rhs); Surface(const Surface& rhs); - Surface(const sp<SurfaceControl>& control); + explicit Surface(const sp<SurfaceControl>& control); Surface(const Parcel& data, const sp<IBinder>& ref); ~Surface(); /* * private stuff... */ - void init(); + void init(const sp<ISurfaceTexture>& surfaceTexture); static void cleanCachedSurfacesLocked(); diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index c4f9e53d5dcc..ccf98e500c9a 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -184,6 +184,7 @@ status_t SurfaceControl::writeSurfaceToParcel( identity = control->mIdentity; } parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); + parcel->writeStrongBinder(NULL); // NULL ISurfaceTexture in this case. parcel->writeInt32(identity); return NO_ERROR; } @@ -192,7 +193,8 @@ sp<Surface> SurfaceControl::getSurface() const { Mutex::Autolock _l(mLock); if (mSurfaceData == 0) { - mSurfaceData = new Surface(const_cast<SurfaceControl*>(this)); + sp<SurfaceControl> surface_control(const_cast<SurfaceControl*>(this)); + mSurfaceData = new Surface(surface_control); } return mSurfaceData; } @@ -208,31 +210,58 @@ Surface::Surface(const sp<SurfaceControl>& surface) mSurface(surface->mSurface), mIdentity(surface->mIdentity) { - init(); + sp<ISurfaceTexture> st; + if (mSurface != NULL) { + st = mSurface->getSurfaceTexture(); + } + init(st); } Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref) : SurfaceTextureClient() { - mSurface = interface_cast<ISurface>(ref); + mSurface = interface_cast<ISurface>(ref); + sp<IBinder> st_binder(parcel.readStrongBinder()); + sp<ISurfaceTexture> st; + if (st_binder != NULL) { + st = interface_cast<ISurfaceTexture>(st_binder); + } else if (mSurface != NULL) { + st = mSurface->getSurfaceTexture(); + } + mIdentity = parcel.readInt32(); - init(); + init(st); +} + +Surface::Surface(const sp<ISurfaceTexture>& st) + : SurfaceTextureClient(), + mSurface(NULL), + mIdentity(0) +{ + init(st); } status_t Surface::writeToParcel( const sp<Surface>& surface, Parcel* parcel) { sp<ISurface> sur; + sp<ISurfaceTexture> st; uint32_t identity = 0; if (Surface::isValid(surface)) { sur = surface->mSurface; + st = surface->getISurfaceTexture(); identity = surface->mIdentity; - } else if (surface != 0 && surface->mSurface != 0) { - LOGW("Parceling invalid surface with non-NULL ISurface as NULL: " - "mSurface = %p, mIdentity = %d", - surface->mSurface.get(), surface->mIdentity); + } else if (surface != 0 && + (surface->mSurface != NULL || + surface->getISurfaceTexture() != NULL)) { + LOGE("Parceling invalid surface with non-NULL ISurface/ISurfaceTexture as NULL: " + "mSurface = %p, surfaceTexture = %p, mIdentity = %d, ", + surface->mSurface.get(), surface->getISurfaceTexture().get(), + surface->mIdentity); } - parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); + + parcel->writeStrongBinder(sur != NULL ? sur->asBinder() : NULL); + parcel->writeStrongBinder(st != NULL ? st->asBinder() : NULL); parcel->writeInt32(identity); return NO_ERROR; @@ -249,8 +278,8 @@ sp<Surface> Surface::readFromParcel(const Parcel& data) { surface = new Surface(data, binder); sCachedSurfaces.add(binder, surface); } - if (surface->mSurface == 0) { - surface = 0; + if (surface->mSurface == NULL && surface->getISurfaceTexture() == NULL) { + surface = 0; } cleanCachedSurfacesLocked(); return surface; @@ -267,10 +296,9 @@ void Surface::cleanCachedSurfacesLocked() { } } -void Surface::init() +void Surface::init(const sp<ISurfaceTexture>& surfaceTexture) { - if (mSurface != NULL) { - sp<ISurfaceTexture> surfaceTexture(mSurface->getSurfaceTexture()); + if (mSurface != NULL || surfaceTexture != NULL) { LOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface"); if (surfaceTexture != NULL) { setISurfaceTexture(surfaceTexture); diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index c190195b53d0..8d199574f433 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -86,7 +86,6 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) : mClientBufferCount(0), mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS), mCurrentTexture(INVALID_BUFFER_SLOT), - mCurrentTextureTarget(GL_TEXTURE_EXTERNAL_OES), mCurrentTransform(0), mCurrentTimestamp(0), mNextTransform(0), @@ -651,12 +650,8 @@ status_t SurfaceTexture::updateTexImage() { LOGW("updateTexImage: clearing GL error: %#04x", error); } - GLenum target = getTextureTarget(mSlots[buf].mGraphicBuffer->format); - if (target != mCurrentTextureTarget) { - glDeleteTextures(1, &mTexName); - } - glBindTexture(target, mTexName); - glEGLImageTargetTexture2DOES(target, (GLeglImageOES)image); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName); + glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image); bool failed = false; while ((error = glGetError()) != GL_NO_ERROR) { @@ -678,7 +673,6 @@ status_t SurfaceTexture::updateTexImage() { // Update the SurfaceTexture state. mCurrentTexture = buf; - mCurrentTextureTarget = target; mCurrentTextureBuf = mSlots[buf].mGraphicBuffer; mCurrentCrop = mSlots[buf].mCrop; mCurrentTransform = mSlots[buf].mTransform; @@ -692,7 +686,7 @@ status_t SurfaceTexture::updateTexImage() { mDequeueCondition.signal(); } else { // We always bind the texture even if we don't update its contents. - glBindTexture(mCurrentTextureTarget, mTexName); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName); } return OK; @@ -717,20 +711,8 @@ bool SurfaceTexture::isExternalFormat(uint32_t format) return false; } -GLenum SurfaceTexture::getTextureTarget(uint32_t format) -{ - GLenum target = GL_TEXTURE_2D; -#if defined(GL_OES_EGL_image_external) - if (isExternalFormat(format)) { - target = GL_TEXTURE_EXTERNAL_OES; - } -#endif - return target; -} - GLenum SurfaceTexture::getCurrentTextureTarget() const { - Mutex::Autolock lock(mMutex); - return mCurrentTextureTarget; + return GL_TEXTURE_EXTERNAL_OES; } void SurfaceTexture::getTransformMatrix(float mtx[16]) { @@ -959,12 +941,12 @@ void SurfaceTexture::dump(String8& result, const char* prefix, } snprintf(buffer, SIZE, - "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d, target=0x%04x}\n" + "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n" "%snext : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n" , prefix, mCurrentCrop.left, mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom, - mCurrentTransform, mCurrentTexture, mCurrentTextureTarget, + mCurrentTransform, mCurrentTexture, prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, mNextCrop.bottom, mCurrentTransform, fifoSize, fifo.string() ); diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp index 0fac6cda05a4..44babcf873b6 100644 --- a/libs/gui/tests/SurfaceTexture_test.cpp +++ b/libs/gui/tests/SurfaceTexture_test.cpp @@ -832,9 +832,7 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) { pt->requestExitAndWait(); } -// XXX: This test is disabled because there are currently no drivers that can -// handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target. -TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferNpot) { +TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferNpot) { const int texWidth = 64; const int texHeight = 66; @@ -871,26 +869,24 @@ TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferNpot) { EXPECT_TRUE(checkPixel( 0, 65, 35, 35, 35, 35)); EXPECT_TRUE(checkPixel(15, 10, 35, 231, 231, 231)); - EXPECT_TRUE(checkPixel(24, 63, 38, 228, 231, 35)); + EXPECT_TRUE(checkPixel(23, 65, 231, 35, 231, 35)); EXPECT_TRUE(checkPixel(19, 40, 35, 231, 35, 35)); EXPECT_TRUE(checkPixel(38, 30, 231, 35, 35, 35)); EXPECT_TRUE(checkPixel(42, 54, 35, 35, 35, 231)); - EXPECT_TRUE(checkPixel(37, 33, 228, 38, 38, 38)); + EXPECT_TRUE(checkPixel(37, 34, 35, 231, 231, 231)); EXPECT_TRUE(checkPixel(31, 8, 231, 35, 35, 231)); - EXPECT_TRUE(checkPixel(36, 47, 228, 35, 231, 231)); - EXPECT_TRUE(checkPixel(24, 63, 38, 228, 231, 35)); - EXPECT_TRUE(checkPixel(48, 3, 228, 228, 38, 35)); + EXPECT_TRUE(checkPixel(37, 47, 231, 35, 231, 231)); + EXPECT_TRUE(checkPixel(25, 38, 35, 35, 35, 35)); + EXPECT_TRUE(checkPixel(49, 6, 35, 231, 35, 35)); EXPECT_TRUE(checkPixel(54, 50, 35, 231, 231, 231)); - EXPECT_TRUE(checkPixel(24, 25, 41, 41, 231, 231)); - EXPECT_TRUE(checkPixel(10, 9, 38, 38, 231, 231)); + EXPECT_TRUE(checkPixel(27, 26, 231, 231, 231, 231)); + EXPECT_TRUE(checkPixel(10, 6, 35, 35, 231, 231)); EXPECT_TRUE(checkPixel(29, 4, 35, 35, 35, 231)); - EXPECT_TRUE(checkPixel(56, 31, 38, 228, 231, 35)); + EXPECT_TRUE(checkPixel(55, 28, 35, 35, 231, 35)); EXPECT_TRUE(checkPixel(58, 55, 35, 35, 231, 231)); } -// XXX: This test is disabled because there are currently no drivers that can -// handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target. -TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferPow2) { +TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferPow2) { const int texWidth = 64; const int texHeight = 64; @@ -944,9 +940,7 @@ TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferPow2) { EXPECT_TRUE(checkPixel( 3, 52, 35, 231, 35, 35)); } -// XXX: This test is disabled because there are currently no drivers that can -// handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target. -TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromGLFilledRGBABufferPow2) { +TEST_F(SurfaceTextureGLTest, TexturingFromGLFilledRGBABufferPow2) { const int texWidth = 64; const int texHeight = 64; @@ -956,7 +950,7 @@ TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromGLFilledRGBABufferPow2) { EGLSurface stcEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig, mANW.get(), NULL); ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_NE(EGL_NO_SURFACE, mEglSurface); + ASSERT_NE(EGL_NO_SURFACE, stcEglSurface); EXPECT_TRUE(eglMakeCurrent(mEglDisplay, stcEglSurface, stcEglSurface, mEglContext)); @@ -980,6 +974,8 @@ TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromGLFilledRGBABufferPow2) { eglSwapBuffers(mEglDisplay, stcEglSurface); + eglDestroySurface(mEglDisplay, stcEglSurface); + // Do the consumer side of things EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)); diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp index 4a40a63485ac..996acd5bceac 100644 --- a/libs/hwui/GradientCache.cpp +++ b/libs/hwui/GradientCache.cpp @@ -181,11 +181,8 @@ void GradientCache::generateTexture(SkBitmap* bitmap, Texture* texture) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture->setFilter(GL_LINEAR, GL_LINEAR); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); } }; // namespace uirenderer diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index 3c2d80de3a79..0c536b077021 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -51,8 +51,6 @@ struct Layer { texture.width = layerWidth; texture.height = layerHeight; colorFilter = NULL; - firstFilter = true; - firstWrap = true; } ~Layer() { @@ -150,27 +148,11 @@ struct Layer { } void setWrap(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false) { - if (firstWrap || force || wrapS != texture.wrapS || wrapT != texture.wrapT) { - firstWrap = true; - texture.setWrap(wrapS, wrapT); - if (bindTexture) { - glBindTexture(renderTarget, texture.id); - } - glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS); - glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT); - } + texture.setWrap(wrapS, wrapT, bindTexture, force, renderTarget); } void setFilter(GLenum min, GLenum mag, bool bindTexture = false, bool force = false) { - if (firstFilter || force || min != texture.minFilter || mag != texture.magFilter) { - firstFilter = false; - texture.setFilter(min, mag); - if (bindTexture) { - glBindTexture(renderTarget, texture.id); - } - glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min); - glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag); - } + texture.setFilter(min, mag,bindTexture, force, renderTarget); } inline bool isCacheable() { @@ -296,8 +278,6 @@ private: */ mat4 texTransform; - bool firstFilter; - bool firstWrap; }; // struct Layer }; // namespace uirenderer diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp index 1a15e8788955..36083afd53bc 100644 --- a/libs/hwui/LayerCache.cpp +++ b/libs/hwui/LayerCache.cpp @@ -107,7 +107,7 @@ Layer* LayerCache::get(const uint32_t width, const uint32_t height) { layer->generateTexture(); layer->bindTexture(); layer->setFilter(GL_NEAREST, GL_NEAREST); - layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, false); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); #if DEBUG_LAYERS diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 85a976222d88..e67abbd7e17d 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1293,16 +1293,16 @@ void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, Sk SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); - setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); - float x = left; float y = top; + GLenum filter = GL_LINEAR; bool ignoreTransform = false; if (mSnapshot->transform->isPureTranslate()) { x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f); y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f); ignoreTransform = true; + filter = GL_NEAREST; } setupDraw(); @@ -1315,7 +1315,11 @@ void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, Sk setupDrawBlending(true, mode); setupDrawProgram(); setupDrawModelView(x, y, x + texture->width, y + texture->height, ignoreTransform); + setupDrawTexture(texture->id); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + texture->setFilter(filter, filter); + setupDrawPureColorUniforms(); setupDrawColorFilterUniforms(); setupDrawShaderUniforms(); @@ -1379,7 +1383,9 @@ void OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHei Texture* texture = mCaches.textureCache.get(bitmap); if (!texture) return; const AutoTexture autoCleanup(texture); - setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true); + texture->setFilter(GL_LINEAR, GL_LINEAR, true); int alpha; SkXfermode::Mode mode; @@ -1462,7 +1468,7 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, Texture* texture = mCaches.textureCache.get(bitmap); if (!texture) return; const AutoTexture autoCleanup(texture); - setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true); const float width = texture->width; const float height = texture->height; @@ -1483,11 +1489,13 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, const float x = (int) floorf(dstLeft + mSnapshot->transform->getTranslateX() + 0.5f); const float y = (int) floorf(dstTop + mSnapshot->transform->getTranslateY() + 0.5f); + texture->setFilter(GL_NEAREST, GL_NEAREST, true); drawTextureMesh(x, y, x + (dstRight - dstLeft), y + (dstBottom - dstTop), texture->id, alpha / 255.0f, mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, false, true); } else { + texture->setFilter(GL_LINEAR, GL_LINEAR, true); drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom, texture->id, alpha / 255.0f, mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount); @@ -1507,7 +1515,8 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int Texture* texture = mCaches.textureCache.get(bitmap); if (!texture) return; const AutoTexture autoCleanup(texture); - setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true); + texture->setFilter(GL_LINEAR, GL_LINEAR, true); int alpha; SkXfermode::Mode mode; @@ -2411,16 +2420,18 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); - setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true); if (mSnapshot->transform->isPureTranslate()) { const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f); const float y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f); + texture->setFilter(GL_NEAREST, GL_NEAREST, true); drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id, alpha / 255.0f, mode, texture->blend, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount, false, true); } else { + texture->setFilter(GL_LINEAR, GL_LINEAR, true); drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode, texture->blend, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount); @@ -2550,22 +2561,5 @@ SkXfermode::Mode OpenGLRenderer::getXfermode(SkXfermode* mode) { return resultMode; } -void OpenGLRenderer::setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT) { - bool bound = false; - if (wrapS != texture->wrapS) { - glBindTexture(GL_TEXTURE_2D, texture->id); - bound = true; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); - texture->wrapS = wrapS; - } - if (wrapT != texture->wrapT) { - if (!bound) { - glBindTexture(GL_TEXTURE_2D, texture->id); - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); - texture->wrapT = wrapT; - } -} - }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 0a3d509058fc..fa893f02a69d 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -464,12 +464,6 @@ private: } /** - * Sets the wrap modes for the specified texture. The wrap modes are modified - * only when needed. - */ - inline void setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT); - - /** * Enable or disable blending as necessary. This function sets the appropriate * blend function based on the specified xfermode. */ diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h index f4d968639df2..33953be5d20d 100644 --- a/libs/hwui/ShapeCache.h +++ b/libs/hwui/ShapeCache.h @@ -624,11 +624,8 @@ void ShapeCache<Entry>::generateTexture(SkBitmap& bitmap, Texture* texture) { glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.getPixels()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture->setFilter(GL_LINEAR, GL_LINEAR); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); } }; // namespace uirenderer diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index 8878c709809e..1a60dca04248 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -77,14 +77,7 @@ void SkiaShader::setupProgram(Program* program, const mat4& modelView, const Sna void SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT) { glBindTexture(GL_TEXTURE_2D, texture->id); - if (wrapS != texture->wrapS) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); - texture->wrapS = wrapS; - } - if (wrapT != texture->wrapT) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); - texture->wrapT = wrapT; - } + texture->setWrap(wrapS, wrapT); } void SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) { @@ -151,6 +144,9 @@ void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView, // Uniforms bindTexture(texture, mWrapS, mWrapT); + GLenum filter = textureTransform.isPureTranslate() ? GL_NEAREST : GL_LINEAR; + texture->setFilter(filter, filter); + glUniform1i(program->getUniform("bitmapSampler"), textureSlot); glUniformMatrix4fv(program->getUniform("textureTransform"), 1, GL_FALSE, &textureTransform.data[0]); diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp index 8f6f860ff14e..a3ee63b08555 100644 --- a/libs/hwui/TextDropShadowCache.cpp +++ b/libs/hwui/TextDropShadowCache.cpp @@ -137,11 +137,8 @@ ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, shadow.image); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture->setFilter(GL_LINEAR, GL_LINEAR); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); if (size < mMaxSize) { if (mDebugEnabled) { diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h index c6ae326d0303..48229b6e4adb 100644 --- a/libs/hwui/Texture.h +++ b/libs/hwui/Texture.h @@ -35,16 +35,45 @@ struct Texture { minFilter = GL_NEAREST; magFilter = GL_NEAREST; + + firstFilter = true; + firstWrap = true; } - void setWrap(GLenum wrapS, GLenum wrapT) { - this->wrapS = wrapS; - this->wrapT = wrapT; + void setWrap(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false, + GLenum renderTarget = GL_TEXTURE_2D) { + + if (firstWrap || force || wrapS != this->wrapS || wrapT != this->wrapT) { + firstWrap = true; + + this->wrapS = wrapS; + this->wrapT = wrapT; + + if (bindTexture) { + glBindTexture(renderTarget, id); + } + + glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS); + glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT); + } } - void setFilter(GLenum min, GLenum mag) { - minFilter = min; - magFilter = mag; + void setFilter(GLenum min, GLenum mag, bool bindTexture = false, bool force = false, + GLenum renderTarget = GL_TEXTURE_2D) { + + if (firstFilter || force || min != minFilter || mag != magFilter) { + firstFilter = false; + + minFilter = min; + magFilter = mag; + + if (bindTexture) { + glBindTexture(renderTarget, id); + } + + glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min); + glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag); + } } /** @@ -87,6 +116,10 @@ struct Texture { */ GLenum minFilter; GLenum magFilter; + +private: + bool firstFilter; + bool firstWrap; }; // struct Texture class AutoTexture { diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index 3752874053a6..f926fddcd7b3 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -219,11 +219,8 @@ void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool rege break; } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture->setFilter(GL_LINEAR, GL_LINEAR); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); } void TextureCache::uploadLoFiTexture(bool resize, SkBitmap* bitmap, diff --git a/libs/rs/driver/rsdRuntimeStubs.cpp b/libs/rs/driver/rsdRuntimeStubs.cpp index 2f9f410f9b9c..d8050ac7bdea 100644 --- a/libs/rs/driver/rsdRuntimeStubs.cpp +++ b/libs/rs/driver/rsdRuntimeStubs.cpp @@ -365,24 +365,49 @@ static const Allocation * SC_GetAllocation(const void *ptr) { return rsrGetAllocation(rsc, sc, ptr); } -static void SC_ForEach(Script *target, - Allocation *in, - Allocation *out, - const void *usr, - const RsScriptCall *call) { +static void SC_ForEach_SAA(Script *target, + Allocation *in, + Allocation *out) { + GET_TLS(); + rsrForEach(rsc, sc, target, in, out, NULL, 0, NULL); +} + +static void SC_ForEach_SAAU(Script *target, + Allocation *in, + Allocation *out, + const void *usr) { GET_TLS(); rsrForEach(rsc, sc, target, in, out, usr, 0, NULL); } -static void SC_ForEach2(Script *target, - Allocation *in, - Allocation *out, - const void *usr, - const RsScriptCall *call) { +static void SC_ForEach_SAAUS(Script *target, + Allocation *in, + Allocation *out, + const void *usr, + const RsScriptCall *call) { GET_TLS(); rsrForEach(rsc, sc, target, in, out, usr, 0, call); } +static void SC_ForEach_SAAUL(Script *target, + Allocation *in, + Allocation *out, + const void *usr, + uint32_t usrLen) { + GET_TLS(); + rsrForEach(rsc, sc, target, in, out, usr, usrLen, NULL); +} + +static void SC_ForEach_SAAULS(Script *target, + Allocation *in, + Allocation *out, + const void *usr, + uint32_t usrLen, + const RsScriptCall *call) { + GET_TLS(); + rsrForEach(rsc, sc, target, in, out, usr, usrLen, call); +} + ////////////////////////////////////////////////////////////////////////////// @@ -648,8 +673,11 @@ static RsdSymbolTable gSyms[] = { { "_Z19rsgClearDepthTargetv", (void *)&SC_ClearFrameBufferObjectDepthTarget, false }, { "_Z24rsgClearAllRenderTargetsv", (void *)&SC_ClearFrameBufferObjectTargets, false }, - { "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach, false }, - { "_Z9rsForEach9rs_script13rs_allocationS0_PKvj", (void *)&SC_ForEach2, false }, + { "_Z9rsForEach9rs_script13rs_allocationS0_", (void *)&SC_ForEach_SAA, false }, + { "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach_SAAU, false }, + { "_Z9rsForEach9rs_script13rs_allocationS0_PKvPK16rs_script_call_t", (void *)&SC_ForEach_SAAUS, false }, + { "_Z9rsForEach9rs_script13rs_allocationS0_PKvj", (void *)&SC_ForEach_SAAUL, false }, + { "_Z9rsForEach9rs_script13rs_allocationS0_PKvjPK16rs_script_call_t", (void *)&SC_ForEach_SAAULS, false }, // time { "_Z6rsTimePi", (void *)&SC_Time, true }, diff --git a/libs/rs/scriptc/rs_math.rsh b/libs/rs/scriptc/rs_math.rsh index f38f72c4ee08..fb5c4f6ddb65 100644 --- a/libs/rs/scriptc/rs_math.rsh +++ b/libs/rs/scriptc/rs_math.rsh @@ -249,15 +249,28 @@ typedef struct rs_script_call { uint32_t arrayEnd; } rs_script_call_t; +#if 1//(RS_VERSION >= 14) extern void __attribute__((overloadable)) - rsForEach(rs_script script, rs_allocation input, - rs_allocation output, const void * usrData); + rsForEach(rs_script script, rs_allocation input, rs_allocation output); extern void __attribute__((overloadable)) + rsForEach(rs_script script, rs_allocation input, rs_allocation output, + const void * usrData, size_t usrDataLen); + +extern void __attribute__((overloadable)) + rsForEach(rs_script script, rs_allocation input, rs_allocation output, + const void * usrData, size_t usrDataLen, const rs_script_call_t *); +#else +extern void __attribute__((overloadable)) rsForEach(rs_script script, rs_allocation input, rs_allocation output, const void * usrData, const rs_script_call_t *); +#endif +// Move me once dependant changes are in. +extern void __attribute__((overloadable)) + rsForEach(rs_script script, rs_allocation input, + rs_allocation output, const void * usrData); /** diff --git a/libs/rs/scriptc/rs_types.rsh b/libs/rs/scriptc/rs_types.rsh index 536d1f04da48..121e013cf0ee 100644 --- a/libs/rs/scriptc/rs_types.rsh +++ b/libs/rs/scriptc/rs_types.rsh @@ -19,6 +19,9 @@ typedef uint16_t ushort; typedef uint32_t uint; typedef uint64_t ulong; +typedef uint32_t size_t; +typedef int32_t ssize_t; + typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_element; typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_type; typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_allocation; @@ -88,6 +91,8 @@ typedef float4 rs_quaternion; #define RS_PACKED __attribute__((packed, aligned(4))) +#define NULL ((const void *)0) + typedef enum { RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X = 0, RS_ALLOCATION_CUBEMAP_FACE_NEGATIVE_X = 1, diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp index cb6c24627eca..6cf01c8d6887 100644 --- a/libs/utils/ResourceTypes.cpp +++ b/libs/utils/ResourceTypes.cpp @@ -4346,7 +4346,8 @@ status_t ResTable::createIdmap(const ResTable& overlay, uint32_t originalCrc, ui | (0x0000ffff & (entryIndex)); resource_name resName; if (!this->getResourceName(resID, &resName)) { - return UNKNOWN_ERROR; + LOGW("idmap: resource 0x%08x has spec but lacks values, skipping\n", resID); + continue; } const String16 overlayType(resName.type, resName.typeLen); diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index 31e463124ae2..8990fe59cb63 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -54,7 +54,8 @@ public class AudioFormat { /** Default audio channel mask */ public static final int CHANNEL_OUT_DEFAULT = 1; - // Channel mask definitions must be kept in sync with native values in include/media/AudioSystem.h + // Channel mask definitions below are translated to the native values defined in + // in /system/core/include/system/audio.h in the JNI code of AudioTrack public static final int CHANNEL_OUT_FRONT_LEFT = 0x4; public static final int CHANNEL_OUT_FRONT_RIGHT = 0x8; public static final int CHANNEL_OUT_FRONT_CENTER = 0x10; @@ -64,6 +65,25 @@ public class AudioFormat { public static final int CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x100; public static final int CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x200; public static final int CHANNEL_OUT_BACK_CENTER = 0x400; + /** @hide */ + public static final int CHANNEL_OUT_SIDE_LEFT = 0x800; + /** @hide */ + public static final int CHANNEL_OUT_SIDE_RIGHT = 0x1000; + /** @hide */ + public static final int CHANNEL_OUT_TOP_CENTER = 0x2000; + /** @hide */ + public static final int CHANNEL_OUT_TOP_FRONT_LEFT = 0x4000; + /** @hide */ + public static final int CHANNEL_OUT_TOP_FRONT_CENTER = 0x8000; + /** @hide */ + public static final int CHANNEL_OUT_TOP_FRONT_RIGHT = 0x10000; + /** @hide */ + public static final int CHANNEL_OUT_TOP_BACK_LEFT = 0x20000; + /** @hide */ + public static final int CHANNEL_OUT_TOP_BACK_CENTER = 0x40000; + /** @hide */ + public static final int CHANNEL_OUT_TOP_BACK_RIGHT = 0x80000; + public static final int CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT; public static final int CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT); public static final int CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | @@ -75,6 +95,12 @@ public class AudioFormat { public static final int CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT | CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER); + /** @hide */ + public static final int CHANNEL_OUT_7POINT1_SURROUND = ( + CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_FRONT_RIGHT | + CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT | + CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT | + CHANNEL_OUT_LOW_FREQUENCY); public static final int CHANNEL_IN_DEFAULT = 1; public static final int CHANNEL_IN_LEFT = 0x4; diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 482b437dd3dc..95671bc47c15 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -611,7 +611,7 @@ public class MediaPlayer * needed. Not calling this method when playing back a video will * result in only the audio track being played. * - * Either a surface or surface texture must be set if a display or video sink + * Either a surface holder or surface must be set if a display or video sink * is needed. Not calling this method or {@link #setTexture(SurfaceTexture)} * when playing back a video will result in only the audio track being played. * @@ -630,6 +630,27 @@ public class MediaPlayer } /** + * Sets the {@link Surface} to be used as the sink for the video portion of + * the media. This is similar to {@link #setDisplay(SurfaceHolder)}, but does not + * support {@link #setScreenOnWhilePlaying(boolean)} or {@link #updateSurfaceScreenOn()}. + * Setting a Surface will un-set any Surface or SurfaceHolder that was previously set. + * + * @param surface The {@link Surface} to be used for the video portion of the media. + * + * @hide Pending review by API council. + */ + public void setSurface(Surface surface) { + if (mScreenOnWhilePlaying && surface != null && mSurface != null) { + Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for Surface"); + } + mSurfaceHolder = null; + mSurface = surface; + mParcelSurfaceTexture = null; // TODO(tedbo): Remove. + _setVideoSurfaceOrSurfaceTexture(); + updateSurfaceScreenOn(); + } + + /** * Sets the {@link SurfaceTexture} to be used as the sink for the * video portion of the media. Either a surface or surface texture * must be set if a video sink is needed. The same surface texture @@ -665,7 +686,7 @@ public class MediaPlayer * @param pst The {@link ParcelSurfaceTexture} to be used as the sink for * the video portion of the media. * - * @hide Pending review by API council. + * @hide Pending removal when there are no more callers. */ public void setParcelSurfaceTexture(ParcelSurfaceTexture pst) { if (mScreenOnWhilePlaying && pst != null && mParcelSurfaceTexture == null) { @@ -1000,8 +1021,8 @@ public class MediaPlayer */ public void setScreenOnWhilePlaying(boolean screenOn) { if (mScreenOnWhilePlaying != screenOn) { - if (screenOn && mParcelSurfaceTexture != null) { - Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for SurfaceTexture"); + if (screenOn && mSurfaceHolder == null) { + Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective without a SurfaceHolder"); } mScreenOnWhilePlaying = screenOn; updateSurfaceScreenOn(); diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index a8ac510259d4..58f9432c4baf 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -872,10 +872,14 @@ public class MediaScanner values.put(Files.FileColumns.FORMAT, format); } // new file, insert it - if (inserter != null) { - result = inserter.insert(values); - } else { + // We insert directories immediately to ensure they are in the database + // before the files they contain. + // Otherwise we can get duplicate directory entries in the database + // if one of the media FileInserters is flushed before the files table FileInserter + if (inserter == null || entry.mFormat == MtpConstants.FORMAT_ASSOCIATION) { result = mMediaProvider.insert(tableUri, values); + } else { + result = inserter.insert(values); } if (result != null) { diff --git a/media/java/android/media/audiofx/AcousticEchoCanceler.java b/media/java/android/media/audiofx/AcousticEchoCanceler.java new file mode 100644 index 000000000000..7197dd2fc768 --- /dev/null +++ b/media/java/android/media/audiofx/AcousticEchoCanceler.java @@ -0,0 +1,67 @@ +/* + * 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 android.media.audiofx; + +/** + * Acoustic Echo Canceler (AEC). + * <p>Acoustic Echo Canceler (AEC) is an audio pre-processing which removes the contribution of the + * signal received from the remote party from the captured audio signal. + * <p>AEC is used by voice communication applications (voice chat, video conferencing, SIP calls) + * where the presence of echo with significant delay in the signal received from the remote party + * is highly disturbing. AEC is often used in conjunction with noise suppression (NS). + * <p>An application creates an AcousticEchoCanceler object to instantiate and control an AEC + * engine in the audio capture path. + * <p>To attach the AcousticEchoCanceler to a particular {@link android.media.AudioRecord}, + * specify the audio session ID of this AudioRecord when constructing the AcousticEchoCanceler. + * The audio session is retrieved by calling + * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance. + * <p>On some devices, an AEC can be inserted by default in the capture path by the platform + * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can + * query which pre-processings are currently applied to an AudioRecord instance by calling + * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the + * AudioRecord. + * <p>See {@link android.media.audiofx.AudioEffect} class for more details on + * controlling audio effects. + * @hide + */ + +public class AcousticEchoCanceler extends AudioEffect { + + private final static String TAG = "AcousticEchoCanceler"; + + /** + * Class constructor. + * <p> The application must catch exceptions when creating an AcousticEchoCanceler as the + * constructor is not guarantied to succeed: + * <ul> + * <li>IllegalArgumentException is thrown if the device does not implement an AEC</li> + * <li>UnsupportedOperationException is thrown is the resources allocated to audio + * pre-procesing are currently exceeded.</li> + * </ul> + * + * @param audioSession system wide unique audio session identifier. The AcousticEchoCanceler + * will be applied to the AudioRecord with the same audio session. + * + * @throws java.lang.IllegalArgumentException + * @throws java.lang.UnsupportedOperationException + * @throws java.lang.RuntimeException + */ + public AcousticEchoCanceler(int audioSession) + throws IllegalArgumentException, UnsupportedOperationException, RuntimeException { + super(EFFECT_TYPE_AEC, EFFECT_TYPE_NULL, 0, audioSession); + } +} diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java index 39c6d3ef4e3f..3ac010493053 100644 --- a/media/java/android/media/audiofx/AudioEffect.java +++ b/media/java/android/media/audiofx/AudioEffect.java @@ -66,6 +66,8 @@ public class AudioEffect { private final static String TAG = "AudioEffect-JAVA"; + // effect type UUIDs are taken from hardware/libhardware/include/hardware/audio_effect.h + /** * The following UUIDs define effect types corresponding to standard audio * effects whose implementation and interface conform to the OpenSL ES @@ -105,6 +107,27 @@ public class AudioEffect { .fromString("37cc2c00-dddd-11db-8577-0002a5d5c51b"); /** + * UUID for Automatic Gain Control (AGC) audio pre-processing + * @hide + */ + public static final UUID EFFECT_TYPE_AGC = UUID + .fromString("0a8abfe0-654c-11e0-ba26-0002a5d5c51b"); + + /** + * UUID for Acoustic Echo Canceler (AEC) audio pre-processing + * @hide + */ + public static final UUID EFFECT_TYPE_AEC = UUID + .fromString("7b491460-8d4d-11e0-bd61-0002a5d5c51b"); + + /** + * UUID for Noise Suppressor (NS) audio pre-processing + * @hide + */ + public static final UUID EFFECT_TYPE_NS = UUID + .fromString("58b4b260-8e06-11e0-aa8e-0002a5d5c51b"); + + /** * Null effect UUID. Used when the UUID for effect type of * @hide */ @@ -180,7 +203,8 @@ public class AudioEffect { * <ul> * <li>type: UUID corresponding to the OpenSL ES interface implemented by this effect</li> * <li>uuid: UUID for this particular implementation</li> - * <li>connectMode: {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY}</li> + * <li>connectMode: {@link #EFFECT_INSERT}, {@link #EFFECT_AUXILIARY} or + * {at_link #EFFECT_PRE_PROCESSING}</li> * <li>name: human readable effect name</li> * <li>implementor: human readable effect implementor name</li> * </ul> @@ -212,11 +236,13 @@ public class AudioEffect { */ public UUID uuid; /** - * Indicates if the effect is of insert category {@link #EFFECT_INSERT} or auxiliary - * category {@link #EFFECT_AUXILIARY}. Insert effects (Typically an Equalizer) are applied + * Indicates if the effect is of insert category {@link #EFFECT_INSERT}, auxiliary + * category {@link #EFFECT_AUXILIARY} or pre processing category + * {at_link #EFFECT_PRE_PROCESSING}. Insert effects (Typically an Equalizer) are applied * to the entire audio source and usually not shared by several sources. Auxiliary effects * (typically a reverberator) are applied to part of the signal (wet) and the effect output * is added to the original signal (dry). + * Audio pre processing are applied to audio captured on a particular AudioRecord. */ public String connectMode; /** @@ -243,6 +269,12 @@ public class AudioEffect { * attaching it to the MediaPlayer or AudioTrack. */ public static final String EFFECT_AUXILIARY = "Auxiliary"; + /** + * Effect connection mode is pre processing. + * The audio pre processing effects are attached to an audio input (AudioRecord). + * @hide + */ + public static final String EFFECT_PRE_PROCESSING = "Pre Processing"; // -------------------------------------------------------------------------- // Member variables @@ -410,6 +442,19 @@ public class AudioEffect { return (Descriptor[]) native_query_effects(); } + /** + * Query all audio pre processing effects applied to the AudioRecord with the supplied + * audio session ID. Returns an array of {@link android.media.audiofx.AudioEffect.Descriptor} + * objects. + * @param audioSession system wide unique audio session identifier. + * @throws IllegalStateException + * @hide + */ + + static public Descriptor[] queryPreProcessings(int audioSession) { + return (Descriptor[]) native_query_pre_processing(audioSession); + } + // -------------------------------------------------------------------------- // Control methods // -------------------- @@ -1155,6 +1200,8 @@ public class AudioEffect { private static native Object[] native_query_effects(); + private static native Object[] native_query_pre_processing(int audioSession); + // --------------------------------------------------------- // Utility methods // ------------------ diff --git a/media/java/android/media/audiofx/AutomaticGainControl.java b/media/java/android/media/audiofx/AutomaticGainControl.java new file mode 100644 index 000000000000..44574f06f857 --- /dev/null +++ b/media/java/android/media/audiofx/AutomaticGainControl.java @@ -0,0 +1,67 @@ +/* + * 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 android.media.audiofx; + +/** + * Automatic Gain Control (AGC). + * <p>Automatic Gain Control (AGC) is an audio pre-processing which automatically normalizes the + * output of the captured signal by boosting or lowering input from the microphone to match a preset + * level so that that the output signal level is virtually constant. + * AGC can be used by applications where the input signal dynamic range is not important but where + * a constant strong capture level is desired. + * <p>An application creates a AutomaticGainControl object to instantiate and control an AGC + * engine in the audio framework. + * <p>To attach the AutomaticGainControl to a particular {@link android.media.AudioRecord}, + * specify the audio session ID of this AudioRecord when constructing the AutomaticGainControl. + * The audio session is retrieved by calling + * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance. + * <p>On some devices, an AGC can be inserted by default in the capture path by the platform + * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can + * query which pre-processings are currently applied to an AudioRecord instance by calling + * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the + * AudioRecord. + * <p>See {@link android.media.audiofx.AudioEffect} class for more details on + * controlling audio effects. + * @hide + */ + +public class AutomaticGainControl extends AudioEffect { + + private final static String TAG = "AutomaticGainControl"; + + /** + * Class constructor. + * <p> The application must catch exceptions when creating an AutomaticGainControl as the + * constructor is not guarantied to succeed: + * <ul> + * <li>IllegalArgumentException is thrown if the device does not implement an AGC</li> + * <li>UnsupportedOperationException is thrown is the resources allocated to audio + * pre-procesing are currently exceeded.</li> + * </ul> + * + * @param audioSession system wide unique audio session identifier. The AutomaticGainControl + * will be applied to the AudioRecord with the same audio session. + * + * @throws java.lang.IllegalArgumentException + * @throws java.lang.UnsupportedOperationException + * @throws java.lang.RuntimeException + */ + public AutomaticGainControl(int audioSession) + throws IllegalArgumentException, UnsupportedOperationException, RuntimeException { + super(EFFECT_TYPE_AGC, EFFECT_TYPE_NULL, 0, audioSession); + } +} diff --git a/media/java/android/media/audiofx/NoiseSuppressor.java b/media/java/android/media/audiofx/NoiseSuppressor.java new file mode 100644 index 000000000000..4e7a8b6ef07f --- /dev/null +++ b/media/java/android/media/audiofx/NoiseSuppressor.java @@ -0,0 +1,68 @@ +/* + * 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 android.media.audiofx; + +/** + * Noise Suppressor (NS). + * <p>Noise suppression (NS) is an audio pre-processing which removes background noise from the + * captured signal. The component of the signal considered as noise can be either stationary + * (car/airplane engine, AC system) or non-stationary (other peoples conversations, car horn) for + * more advanced implementations. + * <p>NS is mostly used by voice communication applications (voice chat, video conferencing, + * SIP calls). + * <p>An application creates a NoiseSuppressor object to instantiate and control an NS + * engine in the audio framework. + * <p>To attach the NoiseSuppressor to a particular {@link android.media.AudioRecord}, + * specify the audio session ID of this AudioRecord when constructing the NoiseSuppressor. + * The audio session is retrieved by calling + * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance. + * <p>On some devices, NS can be inserted by default in the capture path by the platform + * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can + * query which pre-processings are currently applied to an AudioRecord instance by calling + * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the + * AudioRecord. + * <p>See {@link android.media.audiofx.AudioEffect} class for more details on + * controlling audio effects. + * @hide + */ + +public class NoiseSuppressor extends AudioEffect { + + private final static String TAG = "NoiseSuppressor"; + + /** + * Class constructor. + * <p> The application must catch exceptions when creating an NoiseSuppressor as the + * constructor is not guarantied to succeed: + * <ul> + * <li>IllegalArgumentException is thrown if the device does not implement an NS</li> + * <li>UnsupportedOperationException is thrown is the resources allocated to audio + * pre-procesing are currently exceeded.</li> + * </ul> + * + * @param audioSession system wide unique audio session identifier. The NoiseSuppressor + * will be applied to the AudioRecord with the same audio session. + * + * @throws java.lang.IllegalArgumentException + * @throws java.lang.UnsupportedOperationException + * @throws java.lang.RuntimeException + */ + public NoiseSuppressor(int audioSession) + throws IllegalArgumentException, UnsupportedOperationException, RuntimeException { + super(EFFECT_TYPE_NS, EFFECT_TYPE_NULL, 0, audioSession); + } +} diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp index e71e7272bc14..57cabe2775cb 100644 --- a/media/jni/audioeffect/android_media_AudioEffect.cpp +++ b/media/jni/audioeffect/android_media_AudioEffect.cpp @@ -725,18 +725,22 @@ android_media_AudioEffect_native_queryEffects(JNIEnv *env, jclass clazz) goto queryEffects_failure; } + if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) { + jdescConnect = env->NewStringUTF("Auxiliary"); + } else if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT) { + jdescConnect = env->NewStringUTF("Insert"); + } else if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC) { + jdescConnect = env->NewStringUTF("Pre Processing"); + } else { + continue; + } + AudioEffect::guidToString(&desc.type, str, EFFECT_STRING_LEN_MAX); jdescType = env->NewStringUTF(str); AudioEffect::guidToString(&desc.uuid, str, EFFECT_STRING_LEN_MAX); jdescUuid = env->NewStringUTF(str); - if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) { - jdescConnect = env->NewStringUTF("Auxiliary"); - } else { - jdescConnect = env->NewStringUTF("Insert"); - } - jdescName = env->NewStringUTF(desc.name); jdescImplementor = env->NewStringUTF(desc.implementor); @@ -771,6 +775,87 @@ queryEffects_failure: } + + +static jobjectArray +android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz, jint audioSession) +{ + // kDefaultNumEffects is a "reasonable" value ensuring that only one query will be enough on + // most devices to get all active audio pre processing on a given session. + static const uint32_t kDefaultNumEffects = 5; + + effect_descriptor_t *descriptors = new effect_descriptor_t[kDefaultNumEffects]; + uint32_t numEffects = kDefaultNumEffects; + + status_t status = AudioEffect::queryDefaultPreProcessing(audioSession, + descriptors, + &numEffects); + if ((status != NO_ERROR && status != NO_MEMORY) || + numEffects == 0) { + delete[] descriptors; + return NULL; + } + if (status == NO_MEMORY) { + delete [] descriptors; + descriptors = new effect_descriptor_t[numEffects]; + status = AudioEffect::queryDefaultPreProcessing(audioSession, + descriptors, + &numEffects); + } + if (status != NO_ERROR || numEffects == 0) { + delete[] descriptors; + return NULL; + } + LOGV("queryDefaultPreProcessing() got %d effects", numEffects); + + jobjectArray ret = env->NewObjectArray(numEffects, fields.clazzDesc, NULL); + if (ret == NULL) { + delete[] descriptors; + return ret; + } + + char str[EFFECT_STRING_LEN_MAX]; + jstring jdescType; + jstring jdescUuid; + jstring jdescConnect; + jstring jdescName; + jstring jdescImplementor; + jobject jdesc; + + for (uint32_t i = 0; i < numEffects; i++) { + + AudioEffect::guidToString(&descriptors[i].type, str, EFFECT_STRING_LEN_MAX); + jdescType = env->NewStringUTF(str); + AudioEffect::guidToString(&descriptors[i].uuid, str, EFFECT_STRING_LEN_MAX); + jdescUuid = env->NewStringUTF(str); + jdescConnect = env->NewStringUTF("Pre Processing"); + jdescName = env->NewStringUTF(descriptors[i].name); + jdescImplementor = env->NewStringUTF(descriptors[i].implementor); + + jdesc = env->NewObject(fields.clazzDesc, + fields.midDescCstor, + jdescType, + jdescUuid, + jdescConnect, + jdescName, + jdescImplementor); + env->DeleteLocalRef(jdescType); + env->DeleteLocalRef(jdescUuid); + env->DeleteLocalRef(jdescConnect); + env->DeleteLocalRef(jdescName); + env->DeleteLocalRef(jdescImplementor); + if (jdesc == NULL) { + LOGE("env->NewObject(fields.clazzDesc, fields.midDescCstor)"); + env->DeleteLocalRef(ret); + return NULL;; + } + + env->SetObjectArrayElement(ret, i, jdesc); + } + + return ret; +} + // ---------------------------------------------------------------------------- // Dalvik VM type signatures @@ -787,6 +872,8 @@ static JNINativeMethod gMethods[] = { {"native_getParameter", "(I[BI[B)I", (void *)android_media_AudioEffect_native_getParameter}, {"native_command", "(II[BI[B)I", (void *)android_media_AudioEffect_native_command}, {"native_query_effects", "()[Ljava/lang/Object;", (void *)android_media_AudioEffect_native_queryEffects}, + {"native_query_pre_processing", "(I)[Ljava/lang/Object;", + (void *)android_media_AudioEffect_native_queryPreProcessings}, }; diff --git a/media/jni/mediaeditor/VideoEditorJava.cpp b/media/jni/mediaeditor/VideoEditorJava.cpp index 13f63505484b..ec8050f63c38 100755 --- a/media/jni/mediaeditor/VideoEditorJava.cpp +++ b/media/jni/mediaeditor/VideoEditorJava.cpp @@ -25,11 +25,13 @@ extern "C" { void -videoEditJava_checkAndThrowIllegalArgumentException( +videoEditJava_checkAndThrowIllegalArgumentExceptionFunc( bool* pResult, JNIEnv* pEnv, bool condition, - const char* pMessage) + const char* pMessage, + const char* pFile, + int lineNo) { // Check if the previous action succeeded. if (*pResult) @@ -39,7 +41,8 @@ videoEditJava_checkAndThrowIllegalArgumentException( { // Log the exception. VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",\ - "videoEditJava_checkAndThrowIllegalArgumentException, %s", pMessage); + "videoEditJava_checkAndThrowIllegalArgumentException, %s (%s:%d)", + pMessage, pFile, lineNo); // Reset the result flag. (*pResult) = false; @@ -51,11 +54,14 @@ videoEditJava_checkAndThrowIllegalArgumentException( } void -videoEditJava_checkAndThrowRuntimeException( +videoEditJava_checkAndThrowRuntimeExceptionFunc( bool* pResult, JNIEnv* pEnv, bool condition, - M4OSA_ERR result) + M4OSA_ERR result, + const char* pFile, + int lineNo + ) { const char* pMessage = NULL; @@ -70,7 +76,8 @@ videoEditJava_checkAndThrowRuntimeException( // Log the exception. VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA", - "videoEditJava_checkAndThrowRuntimeException, %s", pMessage); + "videoEditJava_checkAndThrowRuntimeException, %s (%s:%d)", + pMessage, pFile, lineNo); // Reset the result flag. (*pResult) = false; @@ -82,11 +89,14 @@ videoEditJava_checkAndThrowRuntimeException( } void -videoEditJava_checkAndThrowIllegalStateException( +videoEditJava_checkAndThrowIllegalStateExceptionFunc( bool* pResult, JNIEnv* pEnv, bool condition, - const char* pMessage) + const char* pMessage, + const char* pFile, + int lineNo + ) { // Check if the previous action succeeded. if (*pResult) @@ -96,7 +106,8 @@ videoEditJava_checkAndThrowIllegalStateException( { // Log the exception. VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA", - "videoEditJava_checkAndThrowIllegalStateException, %s", pMessage); + "videoEditJava_checkAndThrowIllegalStateException, %s (%s:%d)", + pMessage, pFile, lineNo); // Reset the result flag. (*pResult) = false; diff --git a/media/jni/mediaeditor/VideoEditorJava.h b/media/jni/mediaeditor/VideoEditorJava.h index 9d7f096bae77..0a2db08adb2c 100755 --- a/media/jni/mediaeditor/VideoEditorJava.h +++ b/media/jni/mediaeditor/VideoEditorJava.h @@ -351,26 +351,47 @@ typedef struct jmethodID methodIds[]; } VideoEditJava_MethodIds; +#define videoEditJava_checkAndThrowIllegalArgumentException(\ + a, b, c, d) videoEditJava_checkAndThrowIllegalArgumentExceptionFunc(\ + a, b, c, d, __FILE__, __LINE__) + +#define videoEditJava_checkAndThrowRuntimeException(\ + a, b, c, d) videoEditJava_checkAndThrowRuntimeExceptionFunc(\ + a, b, c, d, __FILE__, __LINE__) + +#define videoEditJava_checkAndThrowIllegalStateException(\ + a, b, c, d) videoEditJava_checkAndThrowIllegalStateExceptionFunc(\ + a, b, c, d, __FILE__, __LINE__) + void -videoEditJava_checkAndThrowIllegalArgumentException( +videoEditJava_checkAndThrowIllegalArgumentExceptionFunc( bool* pResult, JNIEnv* pEnv, bool condition, - const char* pMessage); + const char* pMessage, + const char* pFile, + int lineNo + ); void -videoEditJava_checkAndThrowRuntimeException( +videoEditJava_checkAndThrowRuntimeExceptionFunc( bool* pResult, JNIEnv* pEnv, bool condition, - M4OSA_ERR result); + M4OSA_ERR result, + const char* pFile, + int lineNo + ); void -videoEditJava_checkAndThrowIllegalStateException( +videoEditJava_checkAndThrowIllegalStateExceptionFunc( bool* pResult, JNIEnv* pEnv, bool condition, - const char* pMessage); + const char* pMessage, + const char* pFile, + int lineNo + ); void videoEditJava_getClass( diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp index 39195516fff6..063374416e58 100644 --- a/media/libmedia/AudioEffect.cpp +++ b/media/libmedia/AudioEffect.cpp @@ -419,6 +419,15 @@ status_t AudioEffect::getEffectDescriptor(effect_uuid_t *uuid, effect_descriptor return af->getEffectDescriptor(uuid, descriptor); } + +status_t AudioEffect::queryDefaultPreProcessing(int audioSession, + effect_descriptor_t *descriptors, + uint32_t *count) +{ + const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->queryDefaultPreProcessing(audioSession, descriptors, count); +} // ------------------------------------------------------------------------- status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid) diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 49d410f4ce86..15f4be04cc1a 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -53,6 +53,7 @@ enum { UNREGISTER_EFFECT, IS_STREAM_ACTIVE, GET_DEVICES_FOR_STREAM, + QUERY_DEFAULT_PRE_PROCESSING }; class BpAudioPolicyService : public BpInterface<IAudioPolicyService> @@ -321,6 +322,31 @@ public: remote()->transact(IS_STREAM_ACTIVE, data, &reply); return reply.readInt32(); } + + virtual status_t queryDefaultPreProcessing(int audioSession, + effect_descriptor_t *descriptors, + uint32_t *count) + { + if (descriptors == NULL || count == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.writeInt32(audioSession); + data.writeInt32(*count); + status_t status = remote()->transact(QUERY_DEFAULT_PRE_PROCESSING, data, &reply); + if (status != NO_ERROR) { + return status; + } + status = static_cast <status_t> (reply.readInt32()); + uint32_t retCount = reply.readInt32(); + if (retCount != 0) { + uint32_t numDesc = (retCount < *count) ? retCount : *count; + reply.read(descriptors, sizeof(effect_descriptor_t) * numDesc); + } + *count = retCount; + return status; + } }; IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService"); @@ -559,6 +585,29 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } break; + case QUERY_DEFAULT_PRE_PROCESSING: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + int audioSession = data.readInt32(); + uint32_t count = data.readInt32(); + uint32_t retCount = count; + effect_descriptor_t *descriptors = + (effect_descriptor_t *)new char[count * sizeof(effect_descriptor_t)]; + status_t status = queryDefaultPreProcessing(audioSession, descriptors, &retCount); + reply->writeInt32(status); + if (status != NO_ERROR && status != NO_MEMORY) { + retCount = 0; + } + reply->writeInt32(retCount); + if (retCount) { + if (retCount < count) { + count = retCount; + } + reply->write(descriptors, sizeof(effect_descriptor_t) * count); + } + delete[] descriptors; + return status; + } + default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp index 7e44c2991c5c..38e111e54c9d 100644 --- a/media/libmedia/IMediaRecorder.cpp +++ b/media/libmedia/IMediaRecorder.cpp @@ -46,7 +46,6 @@ enum { SET_AUDIO_ENCODER, SET_OUTPUT_FILE_PATH, SET_OUTPUT_FILE_FD, - SET_OUTPUT_FILE_AUXILIARY_FD, SET_VIDEO_SIZE, SET_VIDEO_FRAMERATE, SET_PARAMETERS, @@ -177,15 +176,6 @@ public: return reply.readInt32(); } - status_t setOutputFileAuxiliary(int fd) { - LOGV("setOutputFileAuxiliary(%d)", fd); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - data.writeFileDescriptor(fd); - remote()->transact(SET_OUTPUT_FILE_AUXILIARY_FD, data, &reply); - return reply.readInt32(); - } - status_t setVideoSize(int width, int height) { LOGV("setVideoSize(%dx%d)", width, height); @@ -404,13 +394,6 @@ status_t BnMediaRecorder::onTransact( ::close(fd); return NO_ERROR; } break; - case SET_OUTPUT_FILE_AUXILIARY_FD: { - LOGV("SET_OUTPUT_FILE_AUXILIARY_FD"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - int fd = dup(data.readFileDescriptor()); - reply->writeInt32(setOutputFileAuxiliary(fd)); - return NO_ERROR; - } break; case SET_VIDEO_SIZE: { LOGV("SET_VIDEO_SIZE"); CHECK_INTERFACE(IMediaRecorder, data, reply); diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index fab674ca515c..11d281fd8ee6 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -322,32 +322,6 @@ status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length) return ret; } -status_t MediaRecorder::setOutputFileAuxiliary(int fd) -{ - LOGV("setOutputFileAuxiliary(%d)", fd); - if(mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (mIsAuxiliaryOutputFileSet) { - LOGE("output file has already been set"); - return INVALID_OPERATION; - } - if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { - LOGE("setOutputFile called in an invalid state(%d)", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->setOutputFileAuxiliary(fd); - if (OK != ret) { - LOGV("setOutputFileAuxiliary failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return ret; - } - mIsAuxiliaryOutputFileSet = true; - return ret; -} - status_t MediaRecorder::setVideoSize(int width, int height) { LOGV("setVideoSize(%d, %d)", width, height); @@ -629,7 +603,6 @@ void MediaRecorder::doCleanUp() mIsAudioEncoderSet = false; mIsVideoEncoderSet = false; mIsOutputFileSet = false; - mIsAuxiliaryOutputFileSet = false; } // Release should be OK in any state diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp index 905b88568eb7..6f80b35275a3 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.cpp +++ b/media/libmediaplayerservice/MediaRecorderClient.cpp @@ -178,17 +178,6 @@ status_t MediaRecorderClient::setOutputFile(int fd, int64_t offset, int64_t leng return mRecorder->setOutputFile(fd, offset, length); } -status_t MediaRecorderClient::setOutputFileAuxiliary(int fd) -{ - LOGV("setOutputFileAuxiliary(%d)", fd); - Mutex::Autolock lock(mLock); - if (mRecorder == NULL) { - LOGE("recorder is not initialized"); - return NO_INIT; - } - return mRecorder->setOutputFileAuxiliary(fd); -} - status_t MediaRecorderClient::setVideoSize(int width, int height) { LOGV("setVideoSize(%dx%d)", width, height); diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h index c87a3c0a23e8..c9ccf22ed944 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.h +++ b/media/libmediaplayerservice/MediaRecorderClient.h @@ -41,7 +41,6 @@ public: virtual status_t setOutputFile(const char* path); virtual status_t setOutputFile(int fd, int64_t offset, int64_t length); - virtual status_t setOutputFileAuxiliary(int fd); virtual status_t setVideoSize(int width, int height); virtual status_t setVideoFrameRate(int frames_per_second); virtual status_t setParameters(const String8& params); diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 6427bb701646..6fdb72623fb7 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -28,9 +28,7 @@ #include <media/stagefright/AMRWriter.h> #include <media/stagefright/AACWriter.h> #include <media/stagefright/CameraSource.h> -#include <media/stagefright/VideoSourceDownSampler.h> #include <media/stagefright/CameraSourceTimeLapse.h> -#include <media/stagefright/MediaSourceSplitter.h> #include <media/stagefright/MPEG2TSWriter.h> #include <media/stagefright/MPEG4Writer.h> #include <media/stagefright/MediaDebug.h> @@ -67,8 +65,8 @@ static void addBatteryData(uint32_t params) { StagefrightRecorder::StagefrightRecorder() - : mWriter(NULL), mWriterAux(NULL), - mOutputFd(-1), mOutputFdAux(-1), + : mWriter(NULL), + mOutputFd(-1), mAudioSource(AUDIO_SOURCE_CNT), mVideoSource(VIDEO_SOURCE_LIST_END), mStarted(false), mSurfaceMediaSource(NULL) { @@ -259,24 +257,6 @@ status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t leng return OK; } -status_t StagefrightRecorder::setOutputFileAuxiliary(int fd) { - LOGV("setOutputFileAuxiliary: %d", fd); - - if (fd < 0) { - LOGE("Invalid file descriptor: %d", fd); - return -EBADF; - } - - mCaptureAuxVideo = true; - - if (mOutputFdAux >= 0) { - ::close(mOutputFdAux); - } - mOutputFdAux = dup(fd); - - return OK; -} - // Attempt to parse an int64 literal optionally surrounded by whitespace, // returns true on success, false otherwise. static bool safe_strtoi64(const char *s, int64_t *val) { @@ -573,42 +553,6 @@ status_t StagefrightRecorder::setParamTimeBetweenTimeLapseFrameCapture(int64_t t return OK; } -status_t StagefrightRecorder::setParamAuxVideoWidth(int32_t width) { - LOGV("setParamAuxVideoWidth : %d", width); - - if (width <= 0) { - LOGE("Width (%d) is not positive", width); - return BAD_VALUE; - } - - mAuxVideoWidth = width; - return OK; -} - -status_t StagefrightRecorder::setParamAuxVideoHeight(int32_t height) { - LOGV("setParamAuxVideoHeight : %d", height); - - if (height <= 0) { - LOGE("Height (%d) is not positive", height); - return BAD_VALUE; - } - - mAuxVideoHeight = height; - return OK; -} - -status_t StagefrightRecorder::setParamAuxVideoEncodingBitRate(int32_t bitRate) { - LOGV("StagefrightRecorder::setParamAuxVideoEncodingBitRate: %d", bitRate); - - if (bitRate <= 0) { - LOGE("Invalid video encoding bit rate: %d", bitRate); - return BAD_VALUE; - } - - mAuxVideoBitRate = bitRate; - return OK; -} - status_t StagefrightRecorder::setParamGeoDataLongitude( int32_t longitudex10000) { @@ -738,21 +682,6 @@ status_t StagefrightRecorder::setParameter( return setParamTimeBetweenTimeLapseFrameCapture( 1000LL * timeBetweenTimeLapseFrameCaptureMs); } - } else if (key == "video-aux-param-width") { - int32_t auxWidth; - if (safe_strtoi32(value.string(), &auxWidth)) { - return setParamAuxVideoWidth(auxWidth); - } - } else if (key == "video-aux-param-height") { - int32_t auxHeight; - if (safe_strtoi32(value.string(), &auxHeight)) { - return setParamAuxVideoHeight(auxHeight); - } - } else if (key == "video-aux-param-encoding-bitrate") { - int32_t auxVideoBitRate; - if (safe_strtoi32(value.string(), &auxVideoBitRate)) { - return setParamAuxVideoEncodingBitRate(auxVideoBitRate); - } } else { LOGE("setParameter: failed to find key %s", key.string()); } @@ -1517,7 +1446,6 @@ status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) { } status_t StagefrightRecorder::setupMPEG4Recording( - bool useSplitCameraSource, int outputFd, int32_t videoWidth, int32_t videoHeight, int32_t videoBitRate, @@ -1531,28 +1459,7 @@ status_t StagefrightRecorder::setupMPEG4Recording( if (mVideoSource < VIDEO_SOURCE_LIST_END) { sp<MediaSource> mediaSource; - if (useSplitCameraSource) { - // TODO: Check if there is a better way to handle this - if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) { - LOGE("Cannot use split camera when encoding frames"); - return INVALID_OPERATION; - } - LOGV("Using Split camera source"); - mediaSource = mCameraSourceSplitter->createClient(); - } else { - err = setupMediaSource(&mediaSource); - } - - if ((videoWidth != mVideoWidth) || (videoHeight != mVideoHeight)) { - // TODO: Might be able to handle downsampling even if using GRAlloc - if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) { - LOGE("Cannot change size or Downsample when encoding frames"); - return INVALID_OPERATION; - } - // Use downsampling from the original source. - mediaSource = - new VideoSourceDownSampler(mediaSource, videoWidth, videoHeight); - } + err = setupMediaSource(&mediaSource); if (err != OK) { return err; } @@ -1620,24 +1527,8 @@ void StagefrightRecorder::setupMPEG4MetaData(int64_t startTimeUs, int32_t totalB } status_t StagefrightRecorder::startMPEG4Recording() { - if (mCaptureAuxVideo) { - if (!mCaptureTimeLapse) { - LOGE("Auxiliary video can be captured only in time lapse mode"); - return UNKNOWN_ERROR; - } - LOGV("Creating MediaSourceSplitter"); - sp<CameraSource> cameraSource; - status_t err = setupCameraSource(&cameraSource); - if (err != OK) { - return err; - } - mCameraSourceSplitter = new MediaSourceSplitter(cameraSource); - } else { - mCameraSourceSplitter = NULL; - } - int32_t totalBitRate; - status_t err = setupMPEG4Recording(mCaptureAuxVideo, + status_t err = setupMPEG4Recording( mOutputFd, mVideoWidth, mVideoHeight, mVideoBitRate, &totalBitRate, &mWriter); if (err != OK) { @@ -1653,33 +1544,6 @@ status_t StagefrightRecorder::startMPEG4Recording() { return err; } - if (mCaptureAuxVideo) { - CHECK(mOutputFdAux >= 0); - if (mWriterAux != NULL) { - LOGE("Auxiliary File writer is not avaialble"); - return UNKNOWN_ERROR; - } - if ((mAuxVideoWidth > mVideoWidth) || (mAuxVideoHeight > mVideoHeight) || - ((mAuxVideoWidth == mVideoWidth) && mAuxVideoHeight == mVideoHeight)) { - LOGE("Auxiliary video size (%d x %d) same or larger than the main video size (%d x %d)", - mAuxVideoWidth, mAuxVideoHeight, mVideoWidth, mVideoHeight); - return UNKNOWN_ERROR; - } - - int32_t totalBitrateAux; - err = setupMPEG4Recording(mCaptureAuxVideo, - mOutputFdAux, mAuxVideoWidth, mAuxVideoHeight, - mAuxVideoBitRate, &totalBitrateAux, &mWriterAux); - if (err != OK) { - return err; - } - - sp<MetaData> metaAux = new MetaData; - setupMPEG4MetaData(startTimeUs, totalBitrateAux, &metaAux); - - return mWriterAux->start(metaAux.get()); - } - return OK; } @@ -1690,13 +1554,6 @@ status_t StagefrightRecorder::pause() { } mWriter->pause(); - if (mCaptureAuxVideo) { - if (mWriterAux == NULL) { - return UNKNOWN_ERROR; - } - mWriterAux->pause(); - } - if (mStarted) { mStarted = false; @@ -1724,13 +1581,6 @@ status_t StagefrightRecorder::stop() { mCameraSourceTimeLapse = NULL; } - if (mCaptureAuxVideo) { - if (mWriterAux != NULL) { - mWriterAux->stop(); - mWriterAux.clear(); - } - } - if (mWriter != NULL) { err = mWriter->stop(); mWriter.clear(); @@ -1741,13 +1591,6 @@ status_t StagefrightRecorder::stop() { mOutputFd = -1; } - if (mCaptureAuxVideo) { - if (mOutputFdAux >= 0) { - ::close(mOutputFdAux); - mOutputFdAux = -1; - } - } - if (mStarted) { mStarted = false; @@ -1787,11 +1630,8 @@ status_t StagefrightRecorder::reset() { mVideoEncoder = VIDEO_ENCODER_H263; mVideoWidth = 176; mVideoHeight = 144; - mAuxVideoWidth = 176; - mAuxVideoHeight = 144; mFrameRate = -1; mVideoBitRate = 192000; - mAuxVideoBitRate = 192000; mSampleRate = 8000; mAudioChannels = 1; mAudioBitRate = 12200; @@ -1811,8 +1651,6 @@ status_t StagefrightRecorder::reset() { mTrackEveryTimeDurationUs = 0; mCaptureTimeLapse = false; mTimeBetweenTimeLapseFrameCaptureUs = -1; - mCaptureAuxVideo = false; - mCameraSourceSplitter = NULL; mCameraSourceTimeLapse = NULL; mIsMetaDataStoredInVideoBuffers = false; mEncoderProfiles = MediaProfiles::getInstance(); @@ -1821,7 +1659,6 @@ status_t StagefrightRecorder::reset() { mLongitudex10000 = -3600000; mOutputFd = -1; - mOutputFdAux = -1; return OK; } @@ -1858,8 +1695,6 @@ status_t StagefrightRecorder::dump( snprintf(buffer, SIZE, " Recorder: %p\n", this); snprintf(buffer, SIZE, " Output file (fd %d):\n", mOutputFd); result.append(buffer); - snprintf(buffer, SIZE, " Output file Auxiliary (fd %d):\n", mOutputFdAux); - result.append(buffer); snprintf(buffer, SIZE, " File format: %d\n", mOutputFormat); result.append(buffer); snprintf(buffer, SIZE, " Max file size (bytes): %lld\n", mMaxFileSizeBytes); @@ -1904,14 +1739,10 @@ status_t StagefrightRecorder::dump( result.append(buffer); snprintf(buffer, SIZE, " Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight); result.append(buffer); - snprintf(buffer, SIZE, " Aux Frame size (pixels): %dx%d\n", mAuxVideoWidth, mAuxVideoHeight); - result.append(buffer); snprintf(buffer, SIZE, " Frame rate (fps): %d\n", mFrameRate); result.append(buffer); snprintf(buffer, SIZE, " Bit rate (bps): %d\n", mVideoBitRate); result.append(buffer); - snprintf(buffer, SIZE, " Aux Bit rate (bps): %d\n", mAuxVideoBitRate); - result.append(buffer); ::write(fd, result.string(), result.size()); return OK; } diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index 1618b92a78ae..5c5f05c465b5 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -30,7 +30,6 @@ class Camera; class ICameraRecordingProxy; class CameraSource; class CameraSourceTimeLapse; -class MediaSourceSplitter; struct MediaSource; struct MediaWriter; class MetaData; @@ -55,7 +54,6 @@ struct StagefrightRecorder : public MediaRecorderBase { virtual status_t setPreviewSurface(const sp<Surface>& surface); virtual status_t setOutputFile(const char *path); virtual status_t setOutputFile(int fd, int64_t offset, int64_t length); - virtual status_t setOutputFileAuxiliary(int fd); virtual status_t setParameters(const String8& params); virtual status_t setListener(const sp<IMediaRecorderClient>& listener); virtual status_t prepare(); @@ -74,8 +72,8 @@ private: sp<ICameraRecordingProxy> mCameraProxy; sp<Surface> mPreviewSurface; sp<IMediaRecorderClient> mListener; - sp<MediaWriter> mWriter, mWriterAux; - int mOutputFd, mOutputFdAux; + sp<MediaWriter> mWriter; + int mOutputFd; sp<AudioSource> mAudioSourceNode; audio_source_t mAudioSource; @@ -85,9 +83,8 @@ private: video_encoder mVideoEncoder; bool mUse64BitFileOffset; int32_t mVideoWidth, mVideoHeight; - int32_t mAuxVideoWidth, mAuxVideoHeight; int32_t mFrameRate; - int32_t mVideoBitRate, mAuxVideoBitRate; + int32_t mVideoBitRate; int32_t mAudioBitRate; int32_t mAudioChannels; int32_t mSampleRate; @@ -109,8 +106,6 @@ private: bool mCaptureTimeLapse; int64_t mTimeBetweenTimeLapseFrameCaptureUs; - bool mCaptureAuxVideo; - sp<MediaSourceSplitter> mCameraSourceSplitter; sp<CameraSourceTimeLapse> mCameraSourceTimeLapse; @@ -127,7 +122,6 @@ private: sp<SurfaceMediaSource> mSurfaceMediaSource; status_t setupMPEG4Recording( - bool useSplitCameraSource, int outputFd, int32_t videoWidth, int32_t videoHeight, int32_t videoBitRate, @@ -166,9 +160,6 @@ private: status_t setParamAudioTimeScale(int32_t timeScale); status_t setParamTimeLapseEnable(int32_t timeLapseEnable); status_t setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs); - status_t setParamAuxVideoHeight(int32_t height); - status_t setParamAuxVideoWidth(int32_t width); - status_t setParamAuxVideoEncodingBitRate(int32_t bitRate); status_t setParamVideoEncodingBitRate(int32_t bitRate); status_t setParamVideoIFramesInterval(int32_t seconds); status_t setParamVideoEncoderProfile(int32_t profile); diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp index fe78c462d1f5..1ba79e57edb3 100644 --- a/media/libstagefright/CameraSourceTimeLapse.cpp +++ b/media/libstagefright/CameraSourceTimeLapse.cpp @@ -24,15 +24,10 @@ #include <media/stagefright/CameraSourceTimeLapse.h> #include <media/stagefright/MediaDebug.h> #include <media/stagefright/MetaData.h> -#include <media/stagefright/YUVImage.h> -#include <media/stagefright/YUVCanvas.h> #include <camera/Camera.h> #include <camera/CameraParameters.h> -#include <ui/Rect.h> #include <utils/String8.h> #include <utils/Vector.h> -#include "OMX_Video.h" -#include <limits.h> namespace android { @@ -74,20 +69,14 @@ CameraSourceTimeLapse::CameraSourceTimeLapse( mLastTimeLapseFrameRealTimestampUs(0), mSkipCurrentFrame(false) { - LOGD("starting time lapse mode: %lld us", mTimeBetweenTimeLapseFrameCaptureUs); + LOGD("starting time lapse mode: %lld us", + mTimeBetweenTimeLapseFrameCaptureUs); + mVideoWidth = videoSize.width; mVideoHeight = videoSize.height; - if (trySettingVideoSize(videoSize.width, videoSize.height)) { - mUseStillCameraForTimeLapse = false; - } else { - // TODO: Add a check to see that mTimeBetweenTimeLapseFrameCaptureUs is greater - // than the fastest rate at which the still camera can take pictures. - mUseStillCameraForTimeLapse = true; - CHECK(setPictureSizeToClosestSupported(videoSize.width, videoSize.height)); - mNeedCropping = computeCropRectangleOffset(); - mMeta->setInt32(kKeyWidth, videoSize.width); - mMeta->setInt32(kKeyHeight, videoSize.height); + if (!trySettingVideoSize(videoSize.width, videoSize.height)) { + mInitCheck = NO_INIT; } // Initialize quick stop variables. @@ -101,24 +90,22 @@ CameraSourceTimeLapse::~CameraSourceTimeLapse() { } void CameraSourceTimeLapse::startQuickReadReturns() { + LOGV("startQuickReadReturns"); Mutex::Autolock autoLock(mQuickStopLock); - LOGV("Enabling quick read returns"); // Enable quick stop mode. mQuickStop = true; - if (mUseStillCameraForTimeLapse) { - // wake up the thread right away. - mTakePictureCondition.signal(); - } else { - // Force dataCallbackTimestamp() coming from the video camera to not skip the - // next frame as we want read() to get a get a frame right away. - mForceRead = true; - } + // Force dataCallbackTimestamp() coming from the video camera to + // not skip the next frame as we want read() to get a get a frame + // right away. + mForceRead = true; } -bool CameraSourceTimeLapse::trySettingVideoSize(int32_t width, int32_t height) { - LOGV("trySettingVideoSize: %dx%d", width, height); +bool CameraSourceTimeLapse::trySettingVideoSize( + int32_t width, int32_t height) { + + LOGV("trySettingVideoSize"); int64_t token = IPCThreadState::self()->clearCallingIdentity(); String8 s = mCamera->getParameters(); @@ -162,53 +149,8 @@ bool CameraSourceTimeLapse::trySettingVideoSize(int32_t width, int32_t height) { return isSuccessful; } -bool CameraSourceTimeLapse::setPictureSizeToClosestSupported(int32_t width, int32_t height) { - LOGV("setPictureSizeToClosestSupported: %dx%d", width, height); - int64_t token = IPCThreadState::self()->clearCallingIdentity(); - String8 s = mCamera->getParameters(); - IPCThreadState::self()->restoreCallingIdentity(token); - - CameraParameters params(s); - Vector<Size> supportedSizes; - params.getSupportedPictureSizes(supportedSizes); - - int32_t minPictureSize = INT_MAX; - for (uint32_t i = 0; i < supportedSizes.size(); ++i) { - int32_t pictureWidth = supportedSizes[i].width; - int32_t pictureHeight = supportedSizes[i].height; - - if ((pictureWidth >= width) && (pictureHeight >= height)) { - int32_t pictureSize = pictureWidth*pictureHeight; - if (pictureSize < minPictureSize) { - minPictureSize = pictureSize; - mPictureWidth = pictureWidth; - mPictureHeight = pictureHeight; - } - } - } - LOGV("Picture size = (%d, %d)", mPictureWidth, mPictureHeight); - return (minPictureSize != INT_MAX); -} - -bool CameraSourceTimeLapse::computeCropRectangleOffset() { - if ((mPictureWidth == mVideoWidth) && (mPictureHeight == mVideoHeight)) { - return false; - } - - CHECK((mPictureWidth > mVideoWidth) && (mPictureHeight > mVideoHeight)); - - int32_t widthDifference = mPictureWidth - mVideoWidth; - int32_t heightDifference = mPictureHeight - mVideoHeight; - - mCropRectStartX = widthDifference/2; - mCropRectStartY = heightDifference/2; - - LOGV("setting crop rectangle offset to (%d, %d)", mCropRectStartX, mCropRectStartY); - - return true; -} - void CameraSourceTimeLapse::signalBufferReturned(MediaBuffer* buffer) { + LOGV("signalBufferReturned"); Mutex::Autolock autoLock(mQuickStopLock); if (mQuickStop && (buffer == mLastReadBufferCopy)) { buffer->setObserver(NULL); @@ -218,7 +160,12 @@ void CameraSourceTimeLapse::signalBufferReturned(MediaBuffer* buffer) { } } -void createMediaBufferCopy(const MediaBuffer& sourceBuffer, int64_t frameTime, MediaBuffer **newBuffer) { +void createMediaBufferCopy( + const MediaBuffer& sourceBuffer, + int64_t frameTime, + MediaBuffer **newBuffer) { + + LOGV("createMediaBufferCopy"); size_t sourceSize = sourceBuffer.size(); void* sourcePointer = sourceBuffer.data(); @@ -229,6 +176,7 @@ void createMediaBufferCopy(const MediaBuffer& sourceBuffer, int64_t frameTime, M } void CameraSourceTimeLapse::fillLastReadBufferCopy(MediaBuffer& sourceBuffer) { + LOGV("fillLastReadBufferCopy"); int64_t frameTime; CHECK(sourceBuffer.meta_data()->findInt64(kKeyTime, &frameTime)); createMediaBufferCopy(sourceBuffer, frameTime, &mLastReadBufferCopy); @@ -238,11 +186,12 @@ void CameraSourceTimeLapse::fillLastReadBufferCopy(MediaBuffer& sourceBuffer) { status_t CameraSourceTimeLapse::read( MediaBuffer **buffer, const ReadOptions *options) { + LOGV("read"); if (mLastReadBufferCopy == NULL) { mLastReadStatus = CameraSource::read(buffer, options); - // mQuickStop may have turned to true while read was blocked. Make a copy of - // the buffer in that case. + // mQuickStop may have turned to true while read was blocked. + // Make a copy of the buffer in that case. Mutex::Autolock autoLock(mQuickStopLock); if (mQuickStop && *buffer) { fillLastReadBufferCopy(**buffer); @@ -255,105 +204,19 @@ status_t CameraSourceTimeLapse::read( } } -// static -void *CameraSourceTimeLapse::ThreadTimeLapseWrapper(void *me) { - CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me); - source->threadTimeLapseEntry(); - return NULL; -} - -void CameraSourceTimeLapse::threadTimeLapseEntry() { - while (mStarted) { - { - Mutex::Autolock autoLock(mCameraIdleLock); - if (!mCameraIdle) { - mCameraIdleCondition.wait(mCameraIdleLock); - } - CHECK(mCameraIdle); - mCameraIdle = false; - } - - // Even if mQuickStop == true we need to take one more picture - // as a read() may be blocked, waiting for a frame to get available. - // After this takePicture, if mQuickStop == true, we can safely exit - // this thread as read() will make a copy of this last frame and keep - // returning it in the quick stop mode. - Mutex::Autolock autoLock(mQuickStopLock); - CHECK_EQ(OK, mCamera->takePicture(CAMERA_MSG_RAW_IMAGE)); - if (mQuickStop) { - LOGV("threadTimeLapseEntry: Exiting due to mQuickStop = true"); - return; - } - mTakePictureCondition.waitRelative(mQuickStopLock, - mTimeBetweenTimeLapseFrameCaptureUs * 1000); - } - LOGV("threadTimeLapseEntry: Exiting due to mStarted = false"); -} - -void CameraSourceTimeLapse::startCameraRecording() { - if (mUseStillCameraForTimeLapse) { - LOGV("start time lapse recording using still camera"); - - int64_t token = IPCThreadState::self()->clearCallingIdentity(); - String8 s = mCamera->getParameters(); - - CameraParameters params(s); - params.setPictureSize(mPictureWidth, mPictureHeight); - mCamera->setParameters(params.flatten()); - mCameraIdle = true; - mStopWaitingForIdleCamera = false; - - // disable shutter sound and play the recording sound. - mCamera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, 0, 0); - mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0); - IPCThreadState::self()->restoreCallingIdentity(token); - - // create a thread which takes pictures in a loop - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - - pthread_create(&mThreadTimeLapse, &attr, ThreadTimeLapseWrapper, this); - pthread_attr_destroy(&attr); - } else { - LOGV("start time lapse recording using video camera"); - CameraSource::startCameraRecording(); - } -} - void CameraSourceTimeLapse::stopCameraRecording() { - if (mUseStillCameraForTimeLapse) { - void *dummy; - pthread_join(mThreadTimeLapse, &dummy); - - // Last takePicture may still be underway. Wait for the camera to get - // idle. - Mutex::Autolock autoLock(mCameraIdleLock); - mStopWaitingForIdleCamera = true; - if (!mCameraIdle) { - mCameraIdleCondition.wait(mCameraIdleLock); - } - CHECK(mCameraIdle); - mCamera->setListener(NULL); - - // play the recording sound. - mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0); - } else { - CameraSource::stopCameraRecording(); - } + LOGV("stopCameraRecording"); + CameraSource::stopCameraRecording(); if (mLastReadBufferCopy) { mLastReadBufferCopy->release(); mLastReadBufferCopy = NULL; } } -void CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) { - if (!mUseStillCameraForTimeLapse) { - CameraSource::releaseRecordingFrame(frame); - } -} +sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy( + const sp<IMemory> &source_data) { -sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(const sp<IMemory> &source_data) { + LOGV("createIMemoryCopy"); size_t source_size = source_data->size(); void* source_pointer = source_data->pointer(); @@ -363,102 +226,8 @@ sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(const sp<IMemory> &source_d return newMemory; } -// Allocates IMemory of final type MemoryBase with the given size. -sp<IMemory> allocateIMemory(size_t size) { - sp<MemoryHeapBase> newMemoryHeap = new MemoryHeapBase(size); - sp<MemoryBase> newMemory = new MemoryBase(newMemoryHeap, 0, size); - return newMemory; -} - -// static -void *CameraSourceTimeLapse::ThreadStartPreviewWrapper(void *me) { - CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me); - source->threadStartPreview(); - return NULL; -} - -void CameraSourceTimeLapse::threadStartPreview() { - CHECK_EQ(OK, mCamera->startPreview()); - Mutex::Autolock autoLock(mCameraIdleLock); - mCameraIdle = true; - mCameraIdleCondition.signal(); -} - -void CameraSourceTimeLapse::restartPreview() { - // Start this in a different thread, so that the dataCallback can return - LOGV("restartPreview"); - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - pthread_t threadPreview; - pthread_create(&threadPreview, &attr, ThreadStartPreviewWrapper, this); - pthread_attr_destroy(&attr); -} - -sp<IMemory> CameraSourceTimeLapse::cropYUVImage(const sp<IMemory> &source_data) { - // find the YUV format - int32_t srcFormat; - CHECK(mMeta->findInt32(kKeyColorFormat, &srcFormat)); - YUVImage::YUVFormat yuvFormat; - if (srcFormat == OMX_COLOR_FormatYUV420SemiPlanar) { - yuvFormat = YUVImage::YUV420SemiPlanar; - } else { - CHECK_EQ(srcFormat, OMX_COLOR_FormatYUV420Planar); - yuvFormat = YUVImage::YUV420Planar; - } - - // allocate memory for cropped image and setup a canvas using it. - sp<IMemory> croppedImageMemory = allocateIMemory( - YUVImage::bufferSize(yuvFormat, mVideoWidth, mVideoHeight)); - YUVImage yuvImageCropped(yuvFormat, - mVideoWidth, mVideoHeight, - (uint8_t *)croppedImageMemory->pointer()); - YUVCanvas yuvCanvasCrop(yuvImageCropped); - - YUVImage yuvImageSource(yuvFormat, - mPictureWidth, mPictureHeight, - (uint8_t *)source_data->pointer()); - yuvCanvasCrop.CopyImageRect( - Rect(mCropRectStartX, mCropRectStartY, - mCropRectStartX + mVideoWidth, - mCropRectStartY + mVideoHeight), - 0, 0, - yuvImageSource); - - return croppedImageMemory; -} - -void CameraSourceTimeLapse::dataCallback(int32_t msgType, const sp<IMemory> &data) { - if (msgType == CAMERA_MSG_COMPRESSED_IMAGE) { - // takePicture will complete after this callback, so restart preview. - restartPreview(); - return; - } - if (msgType != CAMERA_MSG_RAW_IMAGE) { - return; - } - - LOGV("dataCallback for timelapse still frame"); - CHECK_EQ(true, mUseStillCameraForTimeLapse); - - int64_t timestampUs; - if (mNumFramesReceived == 0) { - timestampUs = mStartTimeUs; - } else { - timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs; - } - - if (mNeedCropping) { - sp<IMemory> croppedImageData = cropYUVImage(data); - dataCallbackTimestamp(timestampUs, msgType, croppedImageData); - } else { - sp<IMemory> dataCopy = createIMemoryCopy(data); - dataCallbackTimestamp(timestampUs, msgType, dataCopy); - } -} - bool CameraSourceTimeLapse::skipCurrentFrame(int64_t timestampUs) { + LOGV("skipCurrentFrame"); if (mSkipCurrentFrame) { mSkipCurrentFrame = false; return true; @@ -468,72 +237,58 @@ bool CameraSourceTimeLapse::skipCurrentFrame(int64_t timestampUs) { } bool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) { - if (!mUseStillCameraForTimeLapse) { - if (mLastTimeLapseFrameRealTimestampUs == 0) { - // First time lapse frame. Initialize mLastTimeLapseFrameRealTimestampUs - // to current time (timestampUs) and save frame data. - LOGV("dataCallbackTimestamp timelapse: initial frame"); + LOGV("skipFrameAndModifyTimeStamp"); + if (mLastTimeLapseFrameRealTimestampUs == 0) { + // First time lapse frame. Initialize mLastTimeLapseFrameRealTimestampUs + // to current time (timestampUs) and save frame data. + LOGV("dataCallbackTimestamp timelapse: initial frame"); - mLastTimeLapseFrameRealTimestampUs = *timestampUs; - return false; - } + mLastTimeLapseFrameRealTimestampUs = *timestampUs; + return false; + } - { - Mutex::Autolock autoLock(mQuickStopLock); - - // mForceRead may be set to true by startQuickReadReturns(). In that - // case don't skip this frame. - if (mForceRead) { - LOGV("dataCallbackTimestamp timelapse: forced read"); - mForceRead = false; - *timestampUs = - mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs; - return false; - } - } + { + Mutex::Autolock autoLock(mQuickStopLock); - // Workaround to bypass the first 2 input frames for skipping. - // The first 2 output frames from the encoder are: decoder specific info and - // the compressed video frame data for the first input video frame. - if (mNumFramesEncoded >= 1 && *timestampUs < - (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenTimeLapseFrameCaptureUs)) { - // Skip all frames from last encoded frame until - // sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed. - // Tell the camera to release its recording frame and return. - LOGV("dataCallbackTimestamp timelapse: skipping intermediate frame"); - return true; - } else { - // Desired frame has arrived after mTimeBetweenTimeLapseFrameCaptureUs time: - // - Reset mLastTimeLapseFrameRealTimestampUs to current time. - // - Artificially modify timestampUs to be one frame time (1/framerate) ahead - // of the last encoded frame's time stamp. - LOGV("dataCallbackTimestamp timelapse: got timelapse frame"); - - mLastTimeLapseFrameRealTimestampUs = *timestampUs; - *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs; + // mForceRead may be set to true by startQuickReadReturns(). In that + // case don't skip this frame. + if (mForceRead) { + LOGV("dataCallbackTimestamp timelapse: forced read"); + mForceRead = false; + *timestampUs = + mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs; return false; } } + + // Workaround to bypass the first 2 input frames for skipping. + // The first 2 output frames from the encoder are: decoder specific info and + // the compressed video frame data for the first input video frame. + if (mNumFramesEncoded >= 1 && *timestampUs < + (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenTimeLapseFrameCaptureUs)) { + // Skip all frames from last encoded frame until + // sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed. + // Tell the camera to release its recording frame and return. + LOGV("dataCallbackTimestamp timelapse: skipping intermediate frame"); + return true; + } else { + // Desired frame has arrived after mTimeBetweenTimeLapseFrameCaptureUs time: + // - Reset mLastTimeLapseFrameRealTimestampUs to current time. + // - Artificially modify timestampUs to be one frame time (1/framerate) ahead + // of the last encoded frame's time stamp. + LOGV("dataCallbackTimestamp timelapse: got timelapse frame"); + + mLastTimeLapseFrameRealTimestampUs = *timestampUs; + *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs; + return false; + } return false; } void CameraSourceTimeLapse::dataCallbackTimestamp(int64_t timestampUs, int32_t msgType, const sp<IMemory> &data) { - if (!mUseStillCameraForTimeLapse) { - mSkipCurrentFrame = skipFrameAndModifyTimeStamp(×tampUs); - } else { - Mutex::Autolock autoLock(mCameraIdleLock); - // If we are using the still camera and stop() has been called, it may - // be waiting for the camera to get idle. In that case return - // immediately. Calling CameraSource::dataCallbackTimestamp() will lead - // to a deadlock since it tries to access CameraSource::mLock which in - // this case is held by CameraSource::stop() currently waiting for the - // camera to get idle. And camera will not get idle until this call - // returns. - if (mStopWaitingForIdleCamera) { - return; - } - } + LOGV("dataCallbackTimestamp"); + mSkipCurrentFrame = skipFrameAndModifyTimeStamp(×tampUs); CameraSource::dataCallbackTimestamp(timestampUs, msgType, data); } diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp index ff4b08fb6c3f..3d8c56a159f2 100644 --- a/media/libstagefright/SurfaceMediaSource.cpp +++ b/media/libstagefright/SurfaceMediaSource.cpp @@ -23,6 +23,7 @@ #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaDebug.h> #include <media/stagefright/openmax/OMX_IVCommon.h> +#include <media/stagefright/MetadataBufferType.h> #include <surfaceflinger/ISurfaceComposer.h> #include <surfaceflinger/SurfaceComposerClient.h> @@ -710,9 +711,9 @@ status_t SurfaceMediaSource::read( MediaBuffer **buffer, mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer; mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp; - // Pass the data to the MediaBuffer - // TODO: Change later to pass in only the metadata - *buffer = new MediaBuffer(mCurrentBuf); + // Pass the data to the MediaBuffer. Pass in only the metadata + passMetadataBufferLocked(buffer); + (*buffer)->setObserver(this); (*buffer)->add_ref(); (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp); @@ -720,6 +721,34 @@ status_t SurfaceMediaSource::read( MediaBuffer **buffer, return OK; } +// Pass the data to the MediaBuffer. Pass in only the metadata +// The metadata passed consists of two parts: +// 1. First, there is an integer indicating that it is a GRAlloc +// source (kMetadataBufferTypeGrallocSource) +// 2. This is followed by the buffer_handle_t that is a handle to the +// GRalloc buffer. The encoder needs to interpret this GRalloc handle +// and encode the frames. +// -------------------------------------------------------------- +// | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) | +// -------------------------------------------------------------- +// Note: Call only when you have the lock +void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) { + LOGV("passMetadataBuffer"); + // MediaBuffer allocates and owns this data + MediaBuffer *tempBuffer = + new MediaBuffer(4 + sizeof(buffer_handle_t)); + char *data = (char *)tempBuffer->data(); + if (data == NULL) { + LOGE("Cannot allocate memory for passing buffer metadata!"); + return; + } + OMX_U32 type = kMetadataBufferTypeGrallocSource; + memcpy(data, &type, 4); + memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t)); + *buffer = tempBuffer; +} + + void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) { LOGV("signalBufferReturned"); @@ -727,14 +756,13 @@ void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) { Mutex::Autolock autoLock(mMutex); if (!mStarted) { - LOGV("started = false. Nothing to do"); + LOGW("signalBufferReturned: mStarted = false! Nothing to do!"); return; } for (Fifo::iterator it = mQueue.begin(); it != mQueue.end(); ++it) { - if (mSlots[*it].mGraphicBuffer == buffer->graphicBuffer()) { - LOGV("Buffer %d returned. Setting it 'FREE'. New Queue size = %d", - *it, mQueue.size()-1); + CHECK(mSlots[*it].mGraphicBuffer != NULL); + if (checkBufferMatchesSlot(*it, buffer)) { mSlots[*it].mBufferState = BufferSlot::FREE; mQueue.erase(it); buffer->setObserver(0); @@ -751,6 +779,14 @@ void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) { } } +bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) { + LOGV("Check if Buffer matches slot"); + // need to convert to char* for pointer arithmetic and then + // copy the byte stream into our handle + buffer_handle_t bufferHandle ; + memcpy( &bufferHandle, (char *)(buffer->data()) + 4, sizeof(buffer_handle_t)); + return mSlots[slot].mGraphicBuffer->handle == bufferHandle; +} } // end of namespace android diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp index ce108122b8f7..dc6f2c9dabc1 100644 --- a/media/libstagefright/tests/SurfaceMediaSource_test.cpp +++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp @@ -71,8 +71,8 @@ protected: mANW.clear(); } - const int mYuvTexWidth;// = 64; - const int mYuvTexHeight;// = 66; + const int mYuvTexWidth; + const int mYuvTexHeight; sp<SurfaceMediaSource> mSMS; sp<SurfaceTextureClient> mSTC; @@ -124,7 +124,6 @@ sp<MPEG4Writer> SurfaceMediaSourceTest::setUpWriter(OMXClient &client ) { // TODO: overwriting the colorformat since the format set by GRAlloc // could be wrong or not be read by OMX enc_meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar); - // colorFormat); sp<MediaSource> encoder = @@ -225,7 +224,6 @@ TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotOneBufferPass) ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), 0, 0, HAL_PIXEL_FORMAT_YV12)); - // OMX_COLOR_FormatYUV420Planar)); // )); ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); @@ -239,7 +237,6 @@ TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotWrongSizeBuffe // setting the client side buffer size different than the server size ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), 10, 10, HAL_PIXEL_FORMAT_YV12)); - // OMX_COLOR_FormatYUV420Planar)); // )); ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); @@ -258,6 +255,7 @@ TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPa 0, 0, HAL_PIXEL_FORMAT_YV12)); ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); + SimpleDummyRecorder writer(mSMS); writer.start(); @@ -276,10 +274,12 @@ TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPa // A dummy writer is used to simulate actual MPEG4Writer TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPassLag) { LOGV("Testing MultiBufferPass, Dummy Recorder Lagging **************"); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), 0, 0, HAL_PIXEL_FORMAT_YV12)); ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); + SimpleDummyRecorder writer(mSMS); writer.start(); @@ -322,10 +322,9 @@ TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPas TEST_F(SurfaceMediaSourceTest, DISABLED_EncodingFromCpuFilledYV12BufferNpotWrite) { LOGV("Testing the whole pipeline with actual Recorder"); ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), - 0, 0, HAL_PIXEL_FORMAT_YV12)); // OMX_COLOR_FormatYUV420Planar)); // )); + 0, 0, HAL_PIXEL_FORMAT_YV12)); ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); - OMXClient client; CHECK_EQ(OK, client.connect()); diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png Binary files differindex 48f61220686a..2aeb84a032d5 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png Binary files differdeleted file mode 100644 index 1439ecec6ae6..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png Binary files differdeleted file mode 100644 index 06c33695adae..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png Binary files differdeleted file mode 100644 index a1a712f44bdd..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png Binary files differdeleted file mode 100644 index 313f0f5bea15..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png Binary files differdeleted file mode 100644 index 75def4990912..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png Binary files differdeleted file mode 100644 index efbd535a4f11..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png Binary files differdeleted file mode 100644 index e0dca0bcc98c..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png Binary files differdeleted file mode 100644 index 54ee2e6ed6c3..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png Binary files differindex 686158bf62f9..2aeb84a032d5 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png Binary files differdeleted file mode 100644 index 76170a80f5ed..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png Binary files differdeleted file mode 100644 index 97d35f325f46..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png Binary files differdeleted file mode 100644 index 17423d2591ed..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png Binary files differdeleted file mode 100644 index ae58b57a832d..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png Binary files differdeleted file mode 100644 index 00e5bb8b2ca5..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png Binary files differdeleted file mode 100644 index b036a8922804..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png Binary files differdeleted file mode 100644 index bdae6fb2e0dd..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png Binary files differdeleted file mode 100644 index 2b7d95f24370..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png Binary files differindex 0cfdca07539c..d52cb1af4f12 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png Binary files differdeleted file mode 100644 index 7bbfbd1d0437..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png Binary files differdeleted file mode 100644 index 60b75ef3e36c..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png Binary files differdeleted file mode 100644 index 0fba69d24543..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png Binary files differdeleted file mode 100644 index da8a95705c85..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png Binary files differdeleted file mode 100644 index e19bf64ad869..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png Binary files differdeleted file mode 100644 index 838751428961..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png Binary files differdeleted file mode 100644 index 35f774136a97..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png Binary files differdeleted file mode 100644 index a8820e917fcf..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png Binary files differindex b65df27031ce..d52cb1af4f12 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png Binary files differdeleted file mode 100644 index 0478d7077bb5..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png Binary files differdeleted file mode 100644 index e78a0b148a10..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png Binary files differdeleted file mode 100644 index 24c75ec178b1..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png Binary files differdeleted file mode 100644 index 7027dc49a9a1..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png Binary files differdeleted file mode 100644 index b0e83dcdab96..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png Binary files differdeleted file mode 100644 index 01945fff6a04..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png Binary files differdeleted file mode 100644 index 725a507b40f4..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png Binary files differdeleted file mode 100644 index 193af25fba52..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png Binary files differindex ec4f934d72aa..726f7adf338d 100644 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png +++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png Binary files differdeleted file mode 100644 index fb98eef783d4..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_flowing.png Binary files differdeleted file mode 100644 index b86d47a24b44..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_flowing.png Binary files differdeleted file mode 100644 index 7269f9639766..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_flowing.png Binary files differdeleted file mode 100644 index f57e62d00b23..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_flowing.png Binary files differdeleted file mode 100644 index 3d513fbcc014..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_flowing.png Binary files differdeleted file mode 100644 index 32556f95665f..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_flowing.png Binary files differdeleted file mode 100644 index afac648ceea9..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_flowing.png Binary files differdeleted file mode 100644 index 60c0e7f550ab..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png Binary files differindex 0df470a3d6c1..726f7adf338d 100644 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png +++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_flowing.png Binary files differdeleted file mode 100644 index d8d5e8fe61e9..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully_flowing.png Binary files differdeleted file mode 100644 index 2b0b54fdca00..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_flowing.png Binary files differdeleted file mode 100644 index 85c65b44e8b7..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully_flowing.png Binary files differdeleted file mode 100644 index a7e9aafb011d..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_flowing.png Binary files differdeleted file mode 100644 index 21aba7e047f4..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully_flowing.png Binary files differdeleted file mode 100644 index 41db8dcc645e..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_flowing.png Binary files differdeleted file mode 100644 index ae95d2666b96..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully_flowing.png Binary files differdeleted file mode 100644 index 4ad2c5ce7f1c..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully_flowing.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0_fully.png Binary files differnew file mode 100644 index 000000000000..8a9deeadf90f --- /dev/null +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0_fully.png diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_null.png Binary files differnew file mode 100644 index 000000000000..8a9deeadf90f --- /dev/null +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_null.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0_fully.png Binary files differnew file mode 100644 index 000000000000..2de4515843a6 --- /dev/null +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0_fully.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_null.png Binary files differnew file mode 100644 index 000000000000..2de4515843a6 --- /dev/null +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_null.png diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0_fully.png Binary files differnew file mode 100644 index 000000000000..b9410f601b0c --- /dev/null +++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0_fully.png diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_null.png Binary files differnew file mode 100644 index 000000000000..b9410f601b0c --- /dev/null +++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_null.png diff --git a/packages/SystemUI/res/drawable/stat_sys_battery.xml b/packages/SystemUI/res/drawable/stat_sys_battery.xml new file mode 100644 index 000000000000..744ab93da9af --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_battery.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 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. +*/ +--> + +<level-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:maxLevel="4" android:drawable="@drawable/stat_sys_battery_0" /> + <item android:maxLevel="15" android:drawable="@drawable/stat_sys_battery_15" /> + <item android:maxLevel="35" android:drawable="@drawable/stat_sys_battery_28" /> + <item android:maxLevel="49" android:drawable="@drawable/stat_sys_battery_43" /> + <item android:maxLevel="60" android:drawable="@drawable/stat_sys_battery_57" /> + <item android:maxLevel="75" android:drawable="@drawable/stat_sys_battery_71" /> + <item android:maxLevel="90" android:drawable="@drawable/stat_sys_battery_85" /> + <item android:maxLevel="100" android:drawable="@drawable/stat_sys_battery_100" /> +</level-list> + diff --git a/packages/SystemUI/res/drawable/stat_sys_battery_charge.xml b/packages/SystemUI/res/drawable/stat_sys_battery_charge.xml new file mode 100644 index 000000000000..6918eb21ed9d --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_battery_charge.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 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. +*/ +--> + +<level-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:maxLevel="4" android:drawable="@drawable/stat_sys_battery_charge_anim0" /> + <item android:maxLevel="15" android:drawable="@drawable/stat_sys_battery_charge_anim15" /> + <item android:maxLevel="35" android:drawable="@drawable/stat_sys_battery_charge_anim28" /> + <item android:maxLevel="49" android:drawable="@drawable/stat_sys_battery_charge_anim43" /> + <item android:maxLevel="60" android:drawable="@drawable/stat_sys_battery_charge_anim57" /> + <item android:maxLevel="75" android:drawable="@drawable/stat_sys_battery_charge_anim71" /> + <item android:maxLevel="90" android:drawable="@drawable/stat_sys_battery_charge_anim85" /> + <item android:maxLevel="100" android:drawable="@drawable/stat_sys_battery_charge_anim100" /> +</level-list> + + diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml index 1e3099dc3571..17fa6537cb4a 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml @@ -126,27 +126,10 @@ android:layout_width="wrap_content" android:visibility="gone" /> - <FrameLayout - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_marginRight="4dp" - > - <ImageView - android:id="@+id/network_signal" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - /> - <ImageView - android:id="@+id/network_type" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - /> - <ImageView - android:id="@+id/network_direction" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - /> - </FrameLayout> + <include layout="@layout/stacked_signal_icons" + android:layout_width="32dp" + android:layout_height="24dp" + /> <ImageView android:id="@+id/battery" android:layout_height="wrap_content" diff --git a/packages/SystemUI/res/layout/stacked_signal_icons.xml b/packages/SystemUI/res/layout/stacked_signal_icons.xml new file mode 100644 index 000000000000..fdeb74b16c14 --- /dev/null +++ b/packages/SystemUI/res/layout/stacked_signal_icons.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* apps/common/assets/default/default/skins/StatusBar.xml +** +** Copyright 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. +*/ +--> + +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + > + <ImageView + android:id="@+id/mobile_signal" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:layout_centerVertical="true" + android:layout_alignLeft="@+id/wifi_signal" + android:layout_alignWithParentIfMissing="true" + /> + <ImageView + android:id="@+id/network_type" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:layout_alignRight="@id/mobile_signal" + android:layout_centerVertical="true" + /> + <ImageView + android:id="@+id/wifi_signal" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:layout_alignParentRight="true" + android:layout_centerVertical="true" + android:scaleType="center" + android:paddingLeft="7dp" + /> + <ImageView + android:id="@+id/network_direction" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:layout_alignParentRight="true" + android:layout_centerVertical="true" + /> +</RelativeLayout> diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml index c8f577219b5a..0f5aa93534bd 100644 --- a/packages/SystemUI/res/layout/status_bar.xml +++ b/packages/SystemUI/res/layout/status_bar.xml @@ -46,10 +46,29 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentRight="true" - android:paddingRight="6dip" android:gravity="center_vertical" android:orientation="horizontal"/> + <LinearLayout + android:id="@+id/signal_battery_cluster" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginRight="6dp" + android:orientation="horizontal" + android:gravity="center" + > + <include layout="@layout/stacked_signal_icons" + android:layout_width="24dp" + android:layout_height="match_parent" + /> + <ImageView + android:id="@+id/battery" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:paddingLeft="6dip" + /> + </LinearLayout> + <com.android.systemui.statusbar.policy.Clock android:textAppearance="@*android:style/TextAppearance.StatusBar.Icon" android:layout_width="wrap_content" diff --git a/packages/SystemUI/res/values-large/strings.xml b/packages/SystemUI/res/values-large/strings.xml index 35be53208008..f04dc04ed530 100644 --- a/packages/SystemUI/res/values-large/strings.xml +++ b/packages/SystemUI/res/values-large/strings.xml @@ -21,29 +21,9 @@ all of the currently visible notifications. [CHAR LIMIT=10]--> <string name="status_bar_clear_all_button">Clear all</string> - <!-- System panel ("Quick Settings") --> - - <!-- Text to display underneath the graphical signal strength meter when - no connection is available. [CHAR LIMIT=20] --> - <string name="status_bar_settings_signal_meter_disconnected"> - No Internet connection - </string> - - <!-- Text to display underneath the graphical signal strength meter when - it is displaying Wi-Fi status and Wi-Fi is connected to a network - whose SSID is not available. - [CHAR LIMIT=20] --> - <string name="status_bar_settings_signal_meter_wifi_nossid">Wi-Fi connected</string> - <!-- Separator for PLMN and SPN in network name. --> <string name="status_bar_network_name_separator" translatable="false">" – "</string> - <!-- Notification text: when GPS is getting a fix [CHAR LIMIT=50] --> - <string name="gps_notification_searching_text">Searching for GPS</string> - - <!-- Notification text: when GPS has found a fix [CHAR LIMIT=50] --> - <string name="gps_notification_found_text">Location set by GPS</string> - <!-- Title for the pseudo-notification shown when notifications are disabled (do-not-disturb mode) --> <string name="notifications_off_title">Notifications off</string> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 082dab312aeb..1b60b160e147 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -158,7 +158,7 @@ <!-- Checkbox label for application compatibility mode OFF (normal mode on tablets). [CHAR LIMIT=25] --> <string name="compat_mode_off">Stretch to fill screen</string> - + <!-- Compatibility mode help screen: header text. [CHAR LIMIT=50] --> <string name="compat_mode_help_header">Compatibility Zoom</string> @@ -168,7 +168,7 @@ <!-- toast message displayed when a screenshot is saved to the Gallery. --> <string name="screenshot_saving_toast">Screenshot saved to Gallery</string> <!-- toast message displayed when we fail to take a screenshot. --> - <string name="screenshot_failed_toast">Could not save screenshot</string> + <string name="screenshot_failed_toast">Could not save screenshot. External storage may be in use.</string> <!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] --> <string name="usb_preference_title">USB file transfer options</string> @@ -300,4 +300,22 @@ <!-- Content description of the ringer silent icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_ringer_silent">Ringer silent.</string> + <!-- Text to display underneath the graphical signal strength meter when + no connection is available. [CHAR LIMIT=20] --> + <string name="status_bar_settings_signal_meter_disconnected"> + No Internet connection + </string> + + <!-- Text to display underneath the graphical signal strength meter when + it is displaying Wi-Fi status and Wi-Fi is connected to a network + whose SSID is not available. + [CHAR LIMIT=20] --> + <string name="status_bar_settings_signal_meter_wifi_nossid">Wi-Fi connected</string> + + <!-- Notification text: when GPS is getting a fix [CHAR LIMIT=50] --> + <string name="gps_notification_searching_text">Searching for GPS</string> + + <!-- Notification text: when GPS has found a fix [CHAR LIMIT=50] --> + <string name="gps_notification_found_text">Location set by GPS</string> + </resources> diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java new file mode 100644 index 000000000000..eaffd1adb0e5 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -0,0 +1,317 @@ +/* + * 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.systemui; + +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.animation.Animator.AnimatorListener; +import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; +import android.graphics.RectF; +import android.util.Log; +import android.view.animation.LinearInterpolator; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; + +public class SwipeHelper { + static final String TAG = "com.android.systemui.SwipeHelper"; + private static final boolean DEBUG = true; + private static final boolean DEBUG_INVALIDATE = false; + private static final boolean SLOW_ANIMATIONS = false; // DEBUG; + + public static final int X = 0; + public static final int Y = 1; + + private boolean CONSTRAIN_SWIPE = true; + private boolean FADE_OUT_DURING_SWIPE = true; + private boolean DISMISS_IF_SWIPED_FAR_ENOUGH = true; + + private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec + private int MAX_ESCAPE_ANIMATION_DURATION = 500; // ms + private static final int SNAP_ANIM_LEN = SLOW_ANIMATIONS ? 1000 : 250; // ms + + public static float ALPHA_FADE_START = 0.8f; // fraction of thumbnail width + // where fade starts + static final float ALPHA_FADE_END = 0.5f; // fraction of thumbnail width + // beyond which alpha->0 + + private float mPagingTouchSlop; + private Callback mCallback; + private int mSwipeDirection; + private VelocityTracker mVelocityTracker; + + private float mInitialTouchPos; + private boolean mDragging; + private View mCurrView; + private float mDensityScale; + + public SwipeHelper(int swipeDirection, Callback callback, float densityScale, + float pagingTouchSlop) { + mCallback = callback; + mSwipeDirection = swipeDirection; + mVelocityTracker = VelocityTracker.obtain(); + mDensityScale = densityScale; + mPagingTouchSlop = pagingTouchSlop; + } + + public void setDensityScale(float densityScale) { + mDensityScale = densityScale; + } + + public void setPagingTouchSlop(float pagingTouchSlop) { + mPagingTouchSlop = pagingTouchSlop; + } + + private float getPos(MotionEvent ev) { + return mSwipeDirection == X ? ev.getX() : ev.getY(); + } + + private float getPos(View v) { + return mSwipeDirection == X ? v.getX() : v.getY(); + } + + private float getVelocity(VelocityTracker vt) { + return mSwipeDirection == X ? vt.getXVelocity() : + vt.getYVelocity(); + } + + private ObjectAnimator createTranslationAnimation(View v, float newPos) { + ObjectAnimator anim = ObjectAnimator.ofFloat(v, + mSwipeDirection == X ? "translationX" : "translationY", newPos); + return anim; + } + + private float getPerpendicularVelocity(VelocityTracker vt) { + return mSwipeDirection == X ? vt.getYVelocity() : + vt.getXVelocity(); + } + + private void setTranslation(View v, float translate) { + if (mSwipeDirection == X) { + v.setTranslationX(translate); + } else { + v.setTranslationY(translate); + } + } + + private float getSize(View v) { + return mSwipeDirection == X ? v.getMeasuredWidth() : + v.getMeasuredHeight(); + } + + private float getContentSize(View v) { + View content = mCallback.getChildContentView(v); + return getSize(content); + } + + private float getAlphaForOffset(View view, float thumbSize) { + final float fadeSize = ALPHA_FADE_END * thumbSize; + float result = 1.0f; + float pos = getPos(view); + if (pos >= thumbSize * ALPHA_FADE_START) { + result = 1.0f - (pos - thumbSize * ALPHA_FADE_START) / fadeSize; + } else if (pos < thumbSize * (1.0f - ALPHA_FADE_START)) { + result = 1.0f + (thumbSize * ALPHA_FADE_START + pos) / fadeSize; + } + return result; + } + + void invalidateGlobalRegion(View view) { + RectF childBounds = new RectF(view.getLeft(), view.getTop(), view.getRight(), view + .getBottom()); + childBounds.offset(view.getX(), view.getY()); + if (DEBUG_INVALIDATE) + Log.v(TAG, "-------------"); + while (view.getParent() != null && view.getParent() instanceof View) { + view = (View) view.getParent(); + view.getMatrix().mapRect(childBounds); + view.invalidate((int) Math.floor(childBounds.left), + (int) Math.floor(childBounds.top), + (int) Math.ceil(childBounds.right), + (int) Math.ceil(childBounds.bottom)); + if (DEBUG_INVALIDATE) { + Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left) + + "," + (int) Math.floor(childBounds.top) + + "," + (int) Math.ceil(childBounds.right) + + "," + (int) Math.ceil(childBounds.bottom)); + } + } + } + + public boolean onInterceptTouchEvent(MotionEvent ev) { + final int action = ev.getAction(); + + switch (action) { + case MotionEvent.ACTION_DOWN: + mDragging = false; + mCurrView = mCallback.getChildAtPosition(ev); + mVelocityTracker.clear(); + mVelocityTracker.addMovement(ev); + mInitialTouchPos = getPos(ev); + break; + case MotionEvent.ACTION_MOVE: + if (mCurrView != null) { + mVelocityTracker.addMovement(ev); + float pos = getPos(ev); + float delta = pos - mInitialTouchPos; + if (Math.abs(delta) > mPagingTouchSlop) { + mCallback.onBeginDrag(mCurrView); + mDragging = true; + mInitialTouchPos = getPos(ev) - getPos(mCurrView); + } + } + break; + case MotionEvent.ACTION_UP: + mDragging = false; + mCurrView = null; + break; + } + return mDragging; + } + + public void dismissChild(final View animView, float velocity) { + float newPos; + if (velocity < 0 || (velocity == 0 && getPos(animView) < 0)) { + newPos = -getSize(animView); + } else { + newPos = getSize(animView); + } + int duration = MAX_ESCAPE_ANIMATION_DURATION; + if (velocity != 0) { + duration = Math.min(duration, + (int) (Math.abs(newPos - getPos(animView)) * 1000f / Math + .abs(velocity))); + } + ObjectAnimator anim = createTranslationAnimation(animView, newPos); + anim.setInterpolator(new LinearInterpolator()); + anim.setDuration(duration); + anim.addListener(new AnimatorListener() { + public void onAnimationStart(Animator animation) { + } + + public void onAnimationRepeat(Animator animation) { + } + + public void onAnimationEnd(Animator animation) { + mCallback.onChildDismissed(animView); + } + + public void onAnimationCancel(Animator animation) { + mCallback.onChildDismissed(animView); + } + }); + anim.addUpdateListener(new AnimatorUpdateListener() { + public void onAnimationUpdate(ValueAnimator animation) { + if (FADE_OUT_DURING_SWIPE) { + animView.setAlpha(getAlphaForOffset(animView, getContentSize(animView))); + } + invalidateGlobalRegion(animView); + } + }); + anim.start(); + } + + public void snapChild(final View animView, float velocity) { + ObjectAnimator anim = createTranslationAnimation(animView, 0); + int duration = SNAP_ANIM_LEN; + anim.setDuration(duration); + anim.addUpdateListener(new AnimatorUpdateListener() { + public void onAnimationUpdate(ValueAnimator animation) { + if (FADE_OUT_DURING_SWIPE) { + animView.setAlpha(getAlphaForOffset(animView, getContentSize(animView))); + } + invalidateGlobalRegion(animView); + } + }); + anim.start(); + } + + public boolean onTouchEvent(MotionEvent ev) { + if (!mDragging) { + return false; + } + + mVelocityTracker.addMovement(ev); + final int action = ev.getAction(); + switch (action) { + case MotionEvent.ACTION_OUTSIDE: + case MotionEvent.ACTION_MOVE: + if (mCurrView != null) { + float delta = getPos(ev) - mInitialTouchPos; + // don't let items that can't be dismissed be dragged more than + // maxScrollDistance + if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) { + float size = getSize(mCurrView); + float maxScrollDistance = 0.15f * size; + if (Math.abs(delta) >= size) { + delta = delta > 0 ? maxScrollDistance : -maxScrollDistance; + } else { + delta = maxScrollDistance * (float) Math.sin((delta/size)*(Math.PI/2)); + } + } + setTranslation(mCurrView, delta); + if (FADE_OUT_DURING_SWIPE) { + mCurrView.setAlpha(getAlphaForOffset(mCurrView, getContentSize(mCurrView))); + } + invalidateGlobalRegion(mCurrView); + } + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + if (mCurrView != null) { + float maxVelocity = 1000; // px/sec + mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, maxVelocity); + float escapeVelocity = SWIPE_ESCAPE_VELOCITY * mDensityScale; + float velocity = getVelocity(mVelocityTracker); + float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker); + + // Decide whether to dismiss the current view + boolean childSwipedFarEnough = DISMISS_IF_SWIPED_FAR_ENOUGH && + Math.abs(getPos(mCurrView)) > 0.4 * getSize(mCurrView); + boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) && + (Math.abs(velocity) > Math.abs(perpendicularVelocity)) && + (velocity > 0) == (getPos(mCurrView) > 0); + + boolean dismissChild = mCallback.canChildBeDismissed(mCurrView) && + (childSwipedFastEnough || childSwipedFarEnough); + + if (dismissChild) { + // flingadingy + dismissChild(mCurrView, childSwipedFastEnough ? velocity : 0f); + } else { + // snappity + snapChild(mCurrView, velocity); + } + } + break; + } + return true; + } + + public interface Callback { + View getChildAtPosition(MotionEvent ev); + + View getChildContentView(View v); + + boolean canChildBeDismissed(View v); + + void onBeginDrag(View v); + + void onChildDismissed(View v); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java index a549f5122db6..fe7d5aaa2c18 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java @@ -45,6 +45,8 @@ import com.android.systemui.SystemUI; public class PowerUI extends SystemUI { static final String TAG = "PowerUI"; + static final boolean DEBUG = false; + Handler mHandler = new Handler(); int mBatteryLevel = 100; @@ -122,7 +124,7 @@ public class PowerUI extends SystemUI { int oldBucket = findBatteryLevelBucket(oldBatteryLevel); int bucket = findBatteryLevelBucket(mBatteryLevel); - if (false) { + if (DEBUG) { Slog.d(TAG, "buckets ....." + mLowBatteryAlertCloseLevel + " .. " + mLowBatteryReminderLevels[0] + " .. " + mLowBatteryReminderLevels[1]); @@ -149,8 +151,12 @@ public class PowerUI extends SystemUI { && (bucket < oldBucket || oldPlugged) && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN && bucket < 0) { - Slog.i(TAG, "showing low battery warning: level=" + mBatteryLevel); showLowBatteryWarning(); + + // only play SFX when the dialog comes up or the bucket changes + if (bucket != oldBucket || oldPlugged) { + playLowBatterySound(); + } } else if (plugged || (bucket > oldBucket && bucket > 0)) { dismissLowBatteryWarning(); } else if (mBatteryLevelTextView != null) { @@ -170,6 +176,11 @@ public class PowerUI extends SystemUI { } void showLowBatteryWarning() { + Slog.i(TAG, + ((mBatteryLevelTextView == null) ? "showing" : "updating") + + " low battery warning: level=" + mBatteryLevel + + " [" + findBatteryLevelBucket(mBatteryLevel) + "]"); + CharSequence levelText = mContext.getString( R.string.battery_low_percent_format, mBatteryLevel); @@ -198,9 +209,7 @@ public class PowerUI extends SystemUI { new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { mContext.startActivity(intent); - if (mLowBatteryDialog != null) { - mLowBatteryDialog.dismiss(); - } + dismissLowBatteryWarning(); } }); } @@ -216,6 +225,12 @@ public class PowerUI extends SystemUI { d.show(); mLowBatteryDialog = d; } + } + + void playLowBatterySound() { + if (DEBUG) { + Slog.i(TAG, "playing low battery sound. WOMP-WOMP!"); + } final ContentResolver cr = mContext.getContentResolver(); if (Settings.System.getInt(cr, Settings.System.POWER_SOUNDS_ENABLED, 1) == 1) { @@ -236,12 +251,13 @@ public class PowerUI extends SystemUI { void dismissInvalidChargerDialog() { if (mInvalidChargerDialog != null) { - Slog.d(TAG, "closing invalid charger warning"); mInvalidChargerDialog.dismiss(); } } void showInvalidChargerDialog() { + Slog.d(TAG, "showing invalid charger dialog"); + dismissLowBatteryWarning(); AlertDialog.Builder b = new AlertDialog.Builder(mContext); diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java index 797f94cceb1d..5609ead6e284 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java @@ -25,6 +25,6 @@ public interface RecentsCallback { static final int SWIPE_DOWN = 3; void handleOnClick(View selectedView); - void handleSwipe(View selectedView, int direction); + void handleSwipe(View selectedView); void handleLongPress(View selectedView, View anchorView); } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java index 2a5d1dd7ba70..14efdd0683c1 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java @@ -16,52 +16,35 @@ package com.android.systemui.recent; -import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter; - -import android.animation.Animator; -import android.animation.Animator.AnimatorListener; -import android.animation.AnimatorListenerAdapter; import android.animation.LayoutTransition; -import android.animation.ObjectAnimator; -import android.animation.ValueAnimator; -import android.animation.ValueAnimator.AnimatorUpdateListener; import android.content.Context; import android.content.res.Configuration; import android.database.DataSetObserver; -import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; -import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.LinearInterpolator; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; import com.android.systemui.R; +import com.android.systemui.SwipeHelper; +import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter; -public class RecentsHorizontalScrollView extends HorizontalScrollView { +public class RecentsHorizontalScrollView extends HorizontalScrollView + implements SwipeHelper.Callback { private static final String TAG = RecentsPanelView.TAG; - private static final boolean DEBUG_INVALIDATE = false; private static final boolean DEBUG = RecentsPanelView.DEBUG; private LinearLayout mLinearLayout; private ActivityDescriptionAdapter mAdapter; private RecentsCallback mCallback; protected int mLastScrollPosition; - private View mCurrentView; - private float mLastY; - private boolean mDragging; - private VelocityTracker mVelocityTracker; - private float mDensityScale; - private float mPagingTouchSlop; + private SwipeHelper mSwipeHelper; private OnLongClickListener mOnLongClick = new OnLongClickListener() { public boolean onLongClick(View v) { final View anchorView = v.findViewById(R.id.app_description); - mCurrentView = v; mCallback.handleLongPress(v, anchorView); - mCurrentView = null; // make sure we don't accept the return click from this return true; } }; @@ -72,8 +55,9 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView { public RecentsHorizontalScrollView(Context context, AttributeSet attrs) { super(context, attrs, 0); - mDensityScale = getResources().getDisplayMetrics().density; - mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); + float densityScale = getResources().getDisplayMetrics().density; + float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); + mSwipeHelper = new SwipeHelper(SwipeHelper.Y, this, densityScale, pagingTouchSlop); } private int scrollPositionOfMostRecent() { @@ -84,8 +68,16 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView { mLinearLayout.removeAllViews(); for (int i = 0; i < mAdapter.getCount(); i++) { final View view = mAdapter.getView(i, null, mLinearLayout); - view.setClickable(true); + view.setLongClickable(true); view.setOnLongClickListener(mOnLongClick); + + final View thumbnail = getChildContentView(view); + // thumbnail is set to clickable in the layout file + thumbnail.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + mCallback.handleOnClick(view); + } + }); mLinearLayout.addView(view); } // Scroll to end after layout. @@ -99,175 +91,52 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView { @Override public void removeViewInLayout(final View view) { - ObjectAnimator anim = animateClosed(view, Constants.MAX_ESCAPE_ANIMATION_DURATION, - "y", view.getY(), view.getY() + view.getHeight()); - anim.addListener(new AnimatorListenerAdapter() { - public void onAnimationEnd(Animator animation) { - RecentsHorizontalScrollView.super.removeView(view); - } - }); - anim.start(); + dismissChild(view); } - @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()"); - if (mVelocityTracker == null) { - mVelocityTracker = VelocityTracker.obtain(); - } - mVelocityTracker.addMovement(ev); - switch (ev.getAction()) { - case MotionEvent.ACTION_DOWN: - mDragging = false; - mLastY = ev.getY(); - final float x = ev.getX() + getScrollX(); - final float y = ev.getY() + getScrollY(); - mCurrentView = null; - for (int i = 0; i < mLinearLayout.getChildCount(); i++) { - View item = mLinearLayout.getChildAt(i); - if (x >= item.getLeft() && x < item.getRight() - && y >= item.getTop() && y < item.getBottom()) { - mCurrentView = item; - if (DEBUG) Log.v(TAG, "Hit item " + item); - break; - } - } - break; - - case MotionEvent.ACTION_MOVE: - float delta = ev.getY() - mLastY; - if (DEBUG) Log.v(TAG, "ACTION_MOVE : " + delta); - if (Math.abs(delta) > mPagingTouchSlop) { - mDragging = true; - } - break; - - case MotionEvent.ACTION_UP: - if (mCurrentView != null) { - mCallback.handleOnClick(mCurrentView); - } - mDragging = false; - break; - } - return mDragging ? true : super.onInterceptTouchEvent(ev); - } - - private float getAlphaForOffset(View view, float thumbHeight) { - final float fadeHeight = Constants.ALPHA_FADE_END * thumbHeight; - float result = 1.0f; - if (view.getY() >= thumbHeight * Constants.ALPHA_FADE_START) { - result = 1.0f - (view.getY() - thumbHeight * Constants.ALPHA_FADE_START) / fadeHeight; - } else if (view.getY() < thumbHeight * (1.0f - Constants.ALPHA_FADE_START)) { - result = 1.0f + (thumbHeight * Constants.ALPHA_FADE_START + view.getY()) / fadeHeight; - } - return result; + return mSwipeHelper.onInterceptTouchEvent(ev) || + super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent ev) { - if (!mDragging) { - return super.onTouchEvent(ev); - } - - mVelocityTracker.addMovement(ev); - - final View animView = mCurrentView; - - switch (ev.getAction()) { - case MotionEvent.ACTION_MOVE: - if (animView != null) { - final float delta = ev.getY() - mLastY; - final View thumb = animView.findViewById(R.id.app_thumbnail); - animView.setY(animView.getY() + delta); - animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight())); - invalidateGlobalRegion(animView); - } - mLastY = ev.getY(); - break; + return mSwipeHelper.onTouchEvent(ev) || + super.onTouchEvent(ev); + } - case MotionEvent.ACTION_UP: - final ObjectAnimator anim; - if (animView != null) { - final VelocityTracker velocityTracker = mVelocityTracker; - velocityTracker.computeCurrentVelocity(1000, 10000); - final float velocityX = velocityTracker.getXVelocity(); - final float velocityY = velocityTracker.getYVelocity(); - final float curY = animView.getY(); - final float newY = (velocityY >= 0.0f ? 1 : -1) * animView.getHeight(); - final float maxVelocity = Constants.ESCAPE_VELOCITY * mDensityScale; - if (Math.abs(velocityY) > Math.abs(velocityX) - && Math.abs(velocityY) > maxVelocity - && (velocityY >= 0.0f) == (animView.getY() >= 0)) { - long duration = - (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY)); - duration = Math.min(duration, Constants.MAX_ESCAPE_ANIMATION_DURATION); - anim = animateClosed(animView, duration, "y", curY, newY); - } else { // Animate back to position - long duration = Math.abs(velocityY) > 0.0f ? - (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY)) - : Constants.SNAP_BACK_DURATION; - duration = Math.min(duration, Constants.SNAP_BACK_DURATION); - anim = ObjectAnimator.ofFloat(animView, "y", animView.getY(), 0.0f); - anim.setInterpolator(new DecelerateInterpolator(4.0f)); - anim.setDuration(duration); - } + public boolean canChildBeDismissed(View v) { + return true; + } - final View thumb = animView.findViewById(R.id.app_thumbnail); - anim.addUpdateListener(new AnimatorUpdateListener() { - public void onAnimationUpdate(ValueAnimator animation) { - animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight())); - invalidateGlobalRegion(animView); - } - }); - anim.start(); - } + public void dismissChild(View v) { + mSwipeHelper.dismissChild(v, 0); + } - mVelocityTracker.recycle(); - mVelocityTracker = null; - break; - } - return true; + public void onChildDismissed(View v) { + mLinearLayout.removeView(v); + mCallback.handleSwipe(v); } - private ObjectAnimator animateClosed(final View animView, long duration, - String attr, float from, float to) { - ObjectAnimator anim = ObjectAnimator.ofFloat(animView, attr, from, to); - anim.setInterpolator(new LinearInterpolator()); - final int swipeDirection = animView.getX() >= 0.0f ? - RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT; - anim.addListener(new AnimatorListenerAdapter() { - public void onAnimationEnd(Animator animation) { - mLinearLayout.removeView(animView); - mCallback.handleSwipe(animView, swipeDirection); - } - public void onAnimationCancel(Animator animation) { - mLinearLayout.removeView(animView); - mCallback.handleSwipe(animView, swipeDirection); - } - }); - anim.setDuration(duration); - return anim; + public void onBeginDrag(View v) { } - void invalidateGlobalRegion(View view) { - RectF childBounds - = new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); - childBounds.offset(view.getX(), view.getY()); - if (DEBUG_INVALIDATE) Log.v(TAG, "-------------"); - while (view.getParent() != null && view.getParent() instanceof View) { - view = (View) view.getParent(); - view.getMatrix().mapRect(childBounds); - view.invalidate((int) Math.floor(childBounds.left), - (int) Math.floor(childBounds.top), - (int) Math.ceil(childBounds.right), - (int) Math.ceil(childBounds.bottom)); - if (DEBUG_INVALIDATE) { - Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left) - + "," + (int) Math.floor(childBounds.top) - + "," + (int) Math.ceil(childBounds.right) - + "," + (int) Math.ceil(childBounds.bottom)); + public View getChildAtPosition(MotionEvent ev) { + final float x = ev.getX() + getScrollX(); + final float y = ev.getY() + getScrollY(); + for (int i = 0; i < mLinearLayout.getChildCount(); i++) { + View item = mLinearLayout.getChildAt(i); + if (x >= item.getLeft() && x < item.getRight() + && y >= item.getTop() && y < item.getBottom()) { + return item; } } + return null; + } + + public View getChildContentView(View v) { + return v.findViewById(R.id.app_thumbnail); } @Override @@ -283,8 +152,10 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - mDensityScale = getResources().getDisplayMetrics().density; - mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); + float densityScale = getResources().getDisplayMetrics().density; + mSwipeHelper.setDensityScale(densityScale); + float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); + mSwipeHelper.setPagingTouchSlop(pagingTouchSlop); } private void setOverScrollEffectPadding(int leftPadding, int i) { diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index ea544456430d..e988b688a71f 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -529,7 +529,7 @@ public class RecentsPanelView extends RelativeLayout handleOnClick(view); } - public void handleSwipe(View view, int direction) { + public void handleSwipe(View view) { ActivityDescription ad = ((ViewHolder) view.getTag()).activityDescription; if (DEBUG) Log.v(TAG, "Jettison " + ad.label); mActivityDescriptions.remove(ad); diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java index 47ee4aa3f8f0..1bcc413cd15b 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java @@ -16,53 +16,35 @@ package com.android.systemui.recent; -import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter; - -import android.animation.Animator; -import android.animation.Animator.AnimatorListener; -import android.animation.AnimatorListenerAdapter; import android.animation.LayoutTransition; -import android.animation.ObjectAnimator; -import android.animation.ValueAnimator; -import android.animation.ValueAnimator.AnimatorUpdateListener; import android.content.Context; import android.content.res.Configuration; import android.database.DataSetObserver; -import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; -import android.view.LayoutInflater; import android.view.MotionEvent; -import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.LinearInterpolator; import android.widget.LinearLayout; import android.widget.ScrollView; import com.android.systemui.R; +import com.android.systemui.SwipeHelper; +import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter; -public class RecentsVerticalScrollView extends ScrollView { +public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper.Callback { private static final String TAG = RecentsPanelView.TAG; - private static final boolean DEBUG_INVALIDATE = false; private static final boolean DEBUG = RecentsPanelView.DEBUG; private LinearLayout mLinearLayout; private ActivityDescriptionAdapter mAdapter; private RecentsCallback mCallback; protected int mLastScrollPosition; - private View mCurrentView; - private float mLastX; - private boolean mDragging; - private VelocityTracker mVelocityTracker; - private float mDensityScale; - private float mPagingTouchSlop; + private SwipeHelper mSwipeHelper; + private OnLongClickListener mOnLongClick = new OnLongClickListener() { public boolean onLongClick(View v) { final View anchorView = v.findViewById(R.id.app_description); - mCurrentView = v; mCallback.handleLongPress(v, anchorView); - mCurrentView = null; // make sure we don't accept the return click from this return true; } }; @@ -73,8 +55,9 @@ public class RecentsVerticalScrollView extends ScrollView { public RecentsVerticalScrollView(Context context, AttributeSet attrs) { super(context, attrs, 0); - mDensityScale = getResources().getDisplayMetrics().density; - mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); + float densityScale = getResources().getDisplayMetrics().density; + float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); + mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop); } private int scrollPositionOfMostRecent() { @@ -87,6 +70,15 @@ public class RecentsVerticalScrollView extends ScrollView { final View view = mAdapter.getView(i, null, mLinearLayout); view.setClickable(true); view.setOnLongClickListener(mOnLongClick); + + final View thumbnail = getChildContentView(view); + // thumbnail is set to clickable in the layout file + thumbnail.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + mCallback.handleOnClick(view); + } + }); + mLinearLayout.addView(view); } // Scroll to end after layout. @@ -100,175 +92,52 @@ public class RecentsVerticalScrollView extends ScrollView { @Override public void removeViewInLayout(final View view) { - ObjectAnimator anim = animateClosed(view, Constants.MAX_ESCAPE_ANIMATION_DURATION, - "x", view.getX(), view.getX() + view.getWidth()); - anim.addListener(new AnimatorListenerAdapter() { - public void onAnimationEnd(Animator animation) { - RecentsVerticalScrollView.super.removeView(view); - } - }); - anim.start(); + dismissChild(view); } - @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()"); - if (mVelocityTracker == null) { - mVelocityTracker = VelocityTracker.obtain(); - } - mVelocityTracker.addMovement(ev); - switch (ev.getAction()) { - case MotionEvent.ACTION_DOWN: - mDragging = false; - mLastX = ev.getX(); - final float x = ev.getX() + getScrollX(); - final float y = ev.getY() + getScrollY(); - mCurrentView = null; - for (int i = 0; i < mLinearLayout.getChildCount(); i++) { - View item = mLinearLayout.getChildAt(i); - if (x >= item.getLeft() && x < item.getRight() - && y >= item.getTop() && y < item.getBottom()) { - mCurrentView = item; - Log.v(TAG, "Hit item " + item); - break; - } - } - break; - - case MotionEvent.ACTION_MOVE: - float delta = ev.getX() - mLastX; - if (DEBUG) Log.v(TAG, "ACTION_MOVE : " + delta); - if (Math.abs(delta) > mPagingTouchSlop) { - mDragging = true; - } - break; - - case MotionEvent.ACTION_UP: - if (mCurrentView != null) { - mCallback.handleOnClick(mCurrentView); - } - mDragging = false; - break; - } - return mDragging ? true : super.onInterceptTouchEvent(ev); - } - - private float getAlphaForOffset(View view, float thumbWidth) { - final float fadeWidth = Constants.ALPHA_FADE_END * thumbWidth; - float result = 1.0f; - if (view.getX() >= thumbWidth*Constants.ALPHA_FADE_START) { - result = 1.0f - (view.getX() - thumbWidth*Constants.ALPHA_FADE_START) / fadeWidth; - } else if (view.getX() < thumbWidth* (1.0f - Constants.ALPHA_FADE_START)) { - result = 1.0f + (thumbWidth*Constants.ALPHA_FADE_START + view.getX()) / fadeWidth; - } - return result; + return mSwipeHelper.onInterceptTouchEvent(ev) || + super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent ev) { - if (!mDragging) { - return super.onTouchEvent(ev); - } - - mVelocityTracker.addMovement(ev); - - final View animView = mCurrentView; - - switch (ev.getAction()) { - case MotionEvent.ACTION_MOVE: - if (animView != null) { - final float delta = ev.getX() - mLastX; - final View thumb = animView.findViewById(R.id.app_thumbnail); - animView.setX(animView.getX() + delta); - animView.setAlpha(getAlphaForOffset(animView, thumb.getWidth())); - invalidateGlobalRegion(animView); - } - mLastX = ev.getX(); - break; + return mSwipeHelper.onTouchEvent(ev) || + super.onTouchEvent(ev); + } - case MotionEvent.ACTION_UP: - final ObjectAnimator anim; - if (animView != null) { - final VelocityTracker velocityTracker = mVelocityTracker; - velocityTracker.computeCurrentVelocity(1000, 10000); - final float velocityX = velocityTracker.getXVelocity(); - final float velocityY = velocityTracker.getYVelocity(); - final float curX = animView.getX(); - final float newX = (velocityX >= 0.0f ? 1 : -1) * animView.getWidth(); - final float maxVelocity = Constants.ESCAPE_VELOCITY * mDensityScale; - if (Math.abs(velocityX) > Math.abs(velocityY) - && Math.abs(velocityX) > maxVelocity - && (velocityX >= 0.0f) == (animView.getX() >= 0)) { - long duration = - (long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX)); - duration = Math.min(duration, Constants.MAX_ESCAPE_ANIMATION_DURATION); - anim = animateClosed(animView, duration, "x", curX, newX); - } else { // Animate back to position - long duration = Math.abs(velocityX) > 0.0f ? - (long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX)) - : Constants.SNAP_BACK_DURATION; - duration = Math.min(duration, Constants.SNAP_BACK_DURATION); - anim = ObjectAnimator.ofFloat(animView, "x", animView.getX(), 0.0f); - anim.setInterpolator(new DecelerateInterpolator(4.0f)); - anim.setDuration(duration); - } + public boolean canChildBeDismissed(View v) { + return true; + } - final View thumb = animView.findViewById(R.id.app_thumbnail); - anim.addUpdateListener(new AnimatorUpdateListener() { - public void onAnimationUpdate(ValueAnimator animation) { - animView.setAlpha(getAlphaForOffset(animView, thumb.getWidth())); - invalidateGlobalRegion(animView); - } - }); - anim.start(); - } + public void dismissChild(View v) { + mSwipeHelper.dismissChild(v, 0); + } - mVelocityTracker.recycle(); - mVelocityTracker = null; - break; - } - return true; + public void onChildDismissed(View v) { + mLinearLayout.removeView(v); + mCallback.handleSwipe(v); } - private ObjectAnimator animateClosed(final View animView, long duration, - String attr, float from, float to) { - ObjectAnimator anim = ObjectAnimator.ofFloat(animView, attr, from, to); - anim.setInterpolator(new LinearInterpolator()); - final int swipeDirection = animView.getX() >= 0.0f ? - RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT; - anim.addListener(new AnimatorListenerAdapter() { - public void onAnimationEnd(Animator animation) { - mLinearLayout.removeView(animView); - mCallback.handleSwipe(animView, swipeDirection); - } - public void onAnimationCancel(Animator animation) { - mLinearLayout.removeView(animView); - mCallback.handleSwipe(animView, swipeDirection); - } - }); - anim.setDuration(duration); - return anim; + public void onBeginDrag(View v) { } - void invalidateGlobalRegion(View view) { - RectF childBounds - = new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); - childBounds.offset(view.getX(), view.getY()); - if (DEBUG_INVALIDATE) Log.v(TAG, "-------------"); - while (view.getParent() != null && view.getParent() instanceof View) { - view = (View) view.getParent(); - view.getMatrix().mapRect(childBounds); - view.invalidate((int) Math.floor(childBounds.left), - (int) Math.floor(childBounds.top), - (int) Math.ceil(childBounds.right), - (int) Math.ceil(childBounds.bottom)); - if (DEBUG_INVALIDATE) { - Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left) - + "," + (int) Math.floor(childBounds.top) - + "," + (int) Math.ceil(childBounds.right) - + "," + (int) Math.ceil(childBounds.bottom)); + public View getChildAtPosition(MotionEvent ev) { + final float x = ev.getX() + getScrollX(); + final float y = ev.getY() + getScrollY(); + for (int i = 0; i < mLinearLayout.getChildCount(); i++) { + View item = mLinearLayout.getChildAt(i); + if (x >= item.getLeft() && x < item.getRight() + && y >= item.getTop() && y < item.getBottom()) { + return item; } } + return null; + } + + public View getChildContentView(View v) { + return v.findViewById(R.id.app_thumbnail); } @Override @@ -284,8 +153,10 @@ public class RecentsVerticalScrollView extends ScrollView { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - mDensityScale = getResources().getDisplayMetrics().density; - mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); + float densityScale = getResources().getDisplayMetrics().density; + mSwipeHelper.setDensityScale(densityScale); + float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); + mSwipeHelper.setPagingTouchSlop(pagingTouchSlop); } private void setOverScrollEffectPadding(int leftPadding, int i) { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java index 83a5578cfa36..3e037c14b804 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java @@ -78,7 +78,8 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi SaveImageInBackgroundData> { private static final String TAG = "SaveImageInBackgroundTask"; private static final String SCREENSHOTS_DIR_NAME = "Screenshots"; - private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/Screenshot_%s-%d.png"; + private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png"; + private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/%s"; @Override protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) { @@ -87,20 +88,20 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi Context context = params[0].context; Bitmap image = params[0].image; - try{ + try { long currentTime = System.currentTimeMillis(); - String date = new SimpleDateFormat("MM-dd-yy-kk-mm-ss").format(new Date(currentTime)); + String date = new SimpleDateFormat("yyyy-MM-dd-kk-mm-ss").format(new Date(currentTime)); String imageDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES).getAbsolutePath(); - String imageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, - imageDir, SCREENSHOTS_DIR_NAME, - date, currentTime % 1000); + String imageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, date); + String imageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, imageDir, + SCREENSHOTS_DIR_NAME, imageFileName); // Save the screenshot to the MediaStore ContentValues values = new ContentValues(); values.put(MediaStore.Images.ImageColumns.DATA, imageFilePath); - values.put(MediaStore.Images.ImageColumns.TITLE, "Screenshot"); - values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, "Screenshot"); + values.put(MediaStore.Images.ImageColumns.TITLE, imageFileName); + values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, imageFileName); values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, currentTime); values.put(MediaStore.Images.ImageColumns.DATE_ADDED, currentTime); values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, currentTime); @@ -114,7 +115,9 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi out.close(); params[0].result = 0; - }catch(IOException e){ + } catch (Exception e) { + // IOException/UnsupportedOperationException may be thrown if external storage is not + // mounted params[0].result = 1; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index b93ad684311b..21b774c0127d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -82,7 +82,9 @@ import com.android.systemui.statusbar.NotificationData; import com.android.systemui.statusbar.StatusBar; import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.policy.DateView; - +import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.LocationController; +import com.android.systemui.statusbar.policy.NetworkController; public class PhoneStatusBar extends StatusBar { static final String TAG = "PhoneStatusBar"; @@ -107,6 +109,11 @@ public class PhoneStatusBar extends StatusBar { PhoneStatusBarPolicy mIconPolicy; + // These are no longer handled by the policy, because we need custom strategies for them + BatteryController mBatteryController; + LocationController mLocationController; + NetworkController mNetworkController; + int mIconSize; Display mDisplay; @@ -306,6 +313,32 @@ public class PhoneStatusBar extends StatusBar { setAreThereNotifications(); mDateView.setVisibility(View.INVISIBLE); + // Other icons + mLocationController = new LocationController(mContext); // will post a notification + mBatteryController = new BatteryController(mContext); + mBatteryController.addIconView((ImageView)sb.findViewById(R.id.battery)); + mNetworkController = new NetworkController(mContext); + final ImageView comboRSSI = + (ImageView)sb.findViewById(R.id.network_signal); + if (comboRSSI != null) { + mNetworkController.addCombinedSignalIconView(comboRSSI); + } + final ImageView mobileRSSI = + (ImageView)sb.findViewById(R.id.mobile_signal); + if (mobileRSSI != null) { + mNetworkController.addPhoneSignalIconView(mobileRSSI); + } + final ImageView wifiRSSI = + (ImageView)sb.findViewById(R.id.wifi_signal); + if (wifiRSSI != null) { + mNetworkController.addWifiIconView(wifiRSSI); + } + mNetworkController.addDataTypeIconView( + (ImageView)sb.findViewById(R.id.network_type)); + mNetworkController.addDataDirectionOverlayIconView( + (ImageView)sb.findViewById(R.id.network_direction)); + mNetworkController.setStackedMode(true); + // Recents Panel updateRecentsPanel(); @@ -612,6 +645,14 @@ public class PhoneStatusBar extends StatusBar { handleNotificationError(key, notification, "Couldn't update icon: " + ic); return; } + // Update the large icon + if (notification.notification.largeIcon != null) { + oldEntry.largeIcon.setImageBitmap(notification.notification.largeIcon); + } else { + oldEntry.largeIcon.getLayoutParams().width = 0; + oldEntry.largeIcon.setVisibility(View.INVISIBLE); + } + } catch (RuntimeException e) { // It failed to add cleanly. Log, and remove the view from the panel. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index 7b5098534915..322a8c83e0bd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -38,7 +38,6 @@ import android.telephony.SignalStrength; import android.telephony.TelephonyManager; import android.util.Slog; -import com.android.internal.app.IBatteryStats; import com.android.internal.telephony.IccCard; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.cdma.EriInfo; @@ -68,403 +67,14 @@ public class PhoneStatusBarPolicy { private final Context mContext; private final StatusBarManager mService; private final Handler mHandler = new Handler(); - private final IBatteryStats mBatteryStats; // storage private StorageManager mStorageManager; - // phone - private TelephonyManager mPhone; - private int mPhoneSignalIconId; - - //***** Signal strength icons - //GSM/UMTS - private static final int[][] sSignalImages = { - { R.drawable.stat_sys_signal_0, - R.drawable.stat_sys_signal_1, - R.drawable.stat_sys_signal_2, - R.drawable.stat_sys_signal_3, - R.drawable.stat_sys_signal_4 }, - { R.drawable.stat_sys_signal_0_fully, - R.drawable.stat_sys_signal_1_fully, - R.drawable.stat_sys_signal_2_fully, - R.drawable.stat_sys_signal_3_fully, - R.drawable.stat_sys_signal_4_fully } - }; - private static final int[][] sSignalImages_r = { - { R.drawable.stat_sys_r_signal_0, - R.drawable.stat_sys_r_signal_1, - R.drawable.stat_sys_r_signal_2, - R.drawable.stat_sys_r_signal_3, - R.drawable.stat_sys_r_signal_4 }, - { R.drawable.stat_sys_r_signal_0_fully, - R.drawable.stat_sys_r_signal_1_fully, - R.drawable.stat_sys_r_signal_2_fully, - R.drawable.stat_sys_r_signal_3_fully, - R.drawable.stat_sys_r_signal_4_fully } - }; - private static final int[] sRoamingIndicatorImages_cdma = new int[] { - R.drawable.stat_sys_roaming_cdma_0, //Standard Roaming Indicator - // 1 is Standard Roaming Indicator OFF - // TODO T: image never used, remove and put 0 instead? - R.drawable.stat_sys_roaming_cdma_0, - - // 2 is Standard Roaming Indicator FLASHING - // TODO T: image never used, remove and put 0 instead? - R.drawable.stat_sys_roaming_cdma_0, - - // 3-12 Standard ERI - R.drawable.stat_sys_roaming_cdma_0, //3 - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - - // 13-63 Reserved for Standard ERI - R.drawable.stat_sys_roaming_cdma_0, //13 - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - - // 64-127 Reserved for Non Standard (Operator Specific) ERI - R.drawable.stat_sys_roaming_cdma_0, //64 - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, //83 - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0 //239 - - // 240-255 Reserved - }; - - //***** Data connection icons - private int[] mDataIconList = sDataNetType_g[0]; - //GSM/UMTS - private static final int[][] sDataNetType_g = { - { R.drawable.stat_sys_data_connected_g, - R.drawable.stat_sys_data_in_g, - R.drawable.stat_sys_data_out_g, - R.drawable.stat_sys_data_inandout_g }, - { R.drawable.stat_sys_data_fully_connected_g, - R.drawable.stat_sys_data_fully_in_g, - R.drawable.stat_sys_data_fully_out_g, - R.drawable.stat_sys_data_fully_inandout_g } - }; - private static final int[][] sDataNetType_3g = { - { R.drawable.stat_sys_data_connected_3g, - R.drawable.stat_sys_data_in_3g, - R.drawable.stat_sys_data_out_3g, - R.drawable.stat_sys_data_inandout_3g }, - { R.drawable.stat_sys_data_fully_connected_3g, - R.drawable.stat_sys_data_fully_in_3g, - R.drawable.stat_sys_data_fully_out_3g, - R.drawable.stat_sys_data_fully_inandout_3g } - }; - private static final int[][] sDataNetType_4g = { - { R.drawable.stat_sys_data_connected_4g, - R.drawable.stat_sys_data_in_4g, - R.drawable.stat_sys_data_out_4g, - R.drawable.stat_sys_data_inandout_4g }, - { R.drawable.stat_sys_data_fully_connected_4g, - R.drawable.stat_sys_data_fully_in_4g, - R.drawable.stat_sys_data_fully_out_4g, - R.drawable.stat_sys_data_fully_inandout_4g } - }; - private static final int[][] sDataNetType_e = { - { R.drawable.stat_sys_data_connected_e, - R.drawable.stat_sys_data_in_e, - R.drawable.stat_sys_data_out_e, - R.drawable.stat_sys_data_inandout_e }, - { R.drawable.stat_sys_data_fully_connected_e, - R.drawable.stat_sys_data_fully_in_e, - R.drawable.stat_sys_data_fully_out_e, - R.drawable.stat_sys_data_fully_inandout_e } - }; - //3.5G - private static final int[][] sDataNetType_h = { - { R.drawable.stat_sys_data_connected_h, - R.drawable.stat_sys_data_in_h, - R.drawable.stat_sys_data_out_h, - R.drawable.stat_sys_data_inandout_h }, - { R.drawable.stat_sys_data_fully_connected_h, - R.drawable.stat_sys_data_fully_in_h, - R.drawable.stat_sys_data_fully_out_h, - R.drawable.stat_sys_data_fully_inandout_h } - }; - - //CDMA - // Use 3G icons for EVDO data and 1x icons for 1XRTT data - private static final int[][] sDataNetType_1x = { - { R.drawable.stat_sys_data_connected_1x, - R.drawable.stat_sys_data_in_1x, - R.drawable.stat_sys_data_out_1x, - R.drawable.stat_sys_data_inandout_1x }, - { R.drawable.stat_sys_data_fully_connected_1x, - R.drawable.stat_sys_data_fully_in_1x, - R.drawable.stat_sys_data_fully_out_1x, - R.drawable.stat_sys_data_fully_inandout_1x } - }; - - // Accessibility; - - private static final int[] sPhoneSignalStrength = { - R.string.accessibility_no_phone, - R.string.accessibility_phone_one_bar, - R.string.accessibility_phone_two_bars, - R.string.accessibility_phone_three_bars, - R.string.accessibility_phone_signal_full - }; - - private static final int[] sDataConnectionStrength = { - R.string.accessibility_no_data, - R.string.accessibility_data_one_bar, - R.string.accessibility_data_two_bars, - R.string.accessibility_data_three_bars, - R.string.accessibility_data_signal_full - }; - - private static final int[] sWifiConnectionStrength = { - R.string.accessibility_no_wifi, - R.string.accessibility_wifi_one_bar, - R.string.accessibility_wifi_two_bars, - R.string.accessibility_wifi_three_bars, - R.string.accessibility_wifi_signal_full - }; // Assume it's all good unless we hear otherwise. We don't always seem // to get broadcasts that it *is* there. IccCard.State mSimState = IccCard.State.READY; - int mPhoneState = TelephonyManager.CALL_STATE_IDLE; - int mDataState = TelephonyManager.DATA_DISCONNECTED; - int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE; - ServiceState mServiceState; - SignalStrength mSignalStrength; - - // data connection - private boolean mDataIconVisible; - private boolean mHspaDataDistinguishable; // ringer volume private boolean mVolumeVisible; @@ -500,10 +110,7 @@ public class PhoneStatusBarPolicy { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { - updateBattery(intent); - } - else if (action.equals(Intent.ACTION_ALARM_CHANGED)) { + if (action.equals(Intent.ACTION_ALARM_CHANGED)) { updateAlarm(intent); } else if (action.equals(Intent.ACTION_SYNC_STATE_CHANGED)) { @@ -513,15 +120,6 @@ public class PhoneStatusBarPolicy { action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) { updateBluetooth(intent); } - else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION) || - action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) || - action.equals(WifiManager.RSSI_CHANGED_ACTION)) { - updateWifi(intent); - } - else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) || - action.equals(LocationManager.GPS_FIX_CHANGE_ACTION)) { - updateGps(intent); - } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION) || action.equals(AudioManager.VIBRATE_SETTING_CHANGED_ACTION)) { updateVolume(); @@ -532,52 +130,18 @@ public class PhoneStatusBarPolicy { else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) { updateTTY(intent); } - else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) || - action.equals(ConnectivityManager.INET_CONDITION_ACTION)) { - // TODO - stop using other means to get wifi/mobile info - updateConnectivity(intent); - } } }; public PhoneStatusBarPolicy(Context context) { mContext = context; mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE); - mSignalStrength = new SignalStrength(); - mBatteryStats = BatteryStatsService.getService(); // storage mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); mStorageManager.registerListener( new com.android.systemui.usb.StorageNotification(context)); - // battery - mService.setIcon("battery", com.android.internal.R.drawable.stat_sys_battery_unknown, 0, - null); - - // phone_signal - mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); - mPhoneSignalIconId = R.drawable.stat_sys_signal_null; - mService.setIcon("phone_signal", mPhoneSignalIconId, 0, null); - - // register for phone state notifications. - ((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE)) - .listen(mPhoneStateListener, - PhoneStateListener.LISTEN_SERVICE_STATE - | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS - | PhoneStateListener.LISTEN_CALL_STATE - | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE - | PhoneStateListener.LISTEN_DATA_ACTIVITY); - - // data_connection - mService.setIcon("data_connection", R.drawable.stat_sys_data_connected_g, 0, null); - mService.setIconVisibility("data_connection", false); - - // wifi - mService.setIcon("wifi", sWifiSignalImages[0][0], 0, null); - mService.setIconVisibility("wifi", false); - // wifi will get updated by the sticky intents - // TTY status mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0, null); mService.setIconVisibility("tty", false); @@ -596,10 +160,6 @@ public class PhoneStatusBarPolicy { } mService.setIconVisibility("bluetooth", mBluetoothEnabled); - // Gps status - mService.setIcon("gps", R.drawable.stat_sys_gps_acquiring_anim, 0, null); - mService.setIconVisibility("gps", false); - // Alarm clock mService.setIcon("alarm_clock", R.drawable.stat_notify_alarm, 0, null); mService.setIconVisibility("alarm_clock", false); @@ -620,32 +180,15 @@ public class PhoneStatusBarPolicy { IntentFilter filter = new IntentFilter(); // Register for Intent broadcasts for... - filter.addAction(Intent.ACTION_BATTERY_CHANGED); filter.addAction(Intent.ACTION_ALARM_CHANGED); filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED); filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); filter.addAction(AudioManager.VIBRATE_SETTING_CHANGED_ACTION); filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); - filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); - filter.addAction(WifiManager.RSSI_CHANGED_ACTION); - filter.addAction(LocationManager.GPS_ENABLED_CHANGE_ACTION); - filter.addAction(LocationManager.GPS_FIX_CHANGE_ACTION); filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION); - filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); - - // load config to determine if to distinguish Hspa data icon - try { - mHspaDataDistinguishable = mContext.getResources().getBoolean( - R.bool.config_hspa_data_distinguishable); - } catch (Exception e) { - mHspaDataDistinguishable = false; - } } private final void updateAlarm(Intent intent) { @@ -661,96 +204,6 @@ public class PhoneStatusBarPolicy { //mService.setIconVisibility("sync_failing", isFailing && !isActive); } - private final void updateBattery(Intent intent) { - final int id = intent.getIntExtra("icon-small", 0); - int level = intent.getIntExtra("level", 0); - String contentDescription = mContext.getString(R.string.accessibility_battery_level, level); - mService.setIcon("battery", id, level, contentDescription); - } - - private void updateConnectivity(Intent intent) { - NetworkInfo info = (NetworkInfo)(intent.getParcelableExtra( - ConnectivityManager.EXTRA_NETWORK_INFO)); - int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0); - - int inetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0); - - switch (info.getType()) { - case ConnectivityManager.TYPE_MOBILE: - mInetCondition = inetCondition; - updateDataNetType(info.getSubtype()); - updateDataIcon(); - updateSignalStrength(); // apply any change in connectionStatus - break; - case ConnectivityManager.TYPE_WIFI: - mInetCondition = inetCondition; - if (info.isConnected()) { - mIsWifiConnected = true; - int iconId; - String contentDescription = null; - if (mLastWifiSignalLevel == -1) { - iconId = sWifiSignalImages[mInetCondition][0]; - contentDescription = mContext.getString(sWifiConnectionStrength[0]); - } else { - iconId = sWifiSignalImages[mInetCondition][mLastWifiSignalLevel]; - contentDescription = mContext.getString( - sWifiConnectionStrength[mLastWifiSignalLevel]); - } - mService.setIcon("wifi", iconId, 0, contentDescription); - // Show the icon since wi-fi is connected - mService.setIconVisibility("wifi", true); - } else { - mLastWifiSignalLevel = -1; - mIsWifiConnected = false; - int iconId = sWifiSignalImages[0][0]; - - String contentDescription = mContext.getString(R.string.accessibility_no_wifi); - mService.setIcon("wifi", iconId, 0, contentDescription); - // Hide the icon since we're not connected - mService.setIconVisibility("wifi", false); - } - updateSignalStrength(); // apply any change in mInetCondition - break; - } - } - - private PhoneStateListener mPhoneStateListener = new PhoneStateListener() { - @Override - public void onSignalStrengthsChanged(SignalStrength signalStrength) { - mSignalStrength = signalStrength; - updateSignalStrength(); - } - - @Override - public void onServiceStateChanged(ServiceState state) { - mServiceState = state; - updateSignalStrength(); - updateCdmaRoamingIcon(state); - updateDataIcon(); - } - - @Override - public void onCallStateChanged(int state, String incomingNumber) { - // In cdma, if a voice call is made, RSSI should switch to 1x. - if (isCdma()) { - updateSignalStrength(); - } - } - - @Override - public void onDataConnectionStateChanged(int state, int networkType) { - mDataState = state; - updateDataNetType(networkType); - updateDataIcon(); - } - - @Override - public void onDataActivity(int direction) { - mDataActivity = direction; - updateDataIcon(); - } - }; - private final void updateSimState(Intent intent) { String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE); if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { @@ -773,171 +226,6 @@ public class PhoneStatusBarPolicy { } else { mSimState = IccCard.State.UNKNOWN; } - updateDataIcon(); - } - - private boolean isCdma() { - return (mSignalStrength != null) && !mSignalStrength.isGsm(); - } - - private boolean hasService() { - if (mServiceState != null) { - switch (mServiceState.getState()) { - case ServiceState.STATE_OUT_OF_SERVICE: - case ServiceState.STATE_POWER_OFF: - return false; - default: - return true; - } - } else { - return false; - } - } - - private final void updateSignalStrength() { - int[] iconList; - String contentDescription = null; - - // Display signal strength while in "emergency calls only" mode - if (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly())) { - //Slog.d(TAG, "updateSignalStrength: no service"); - if (Settings.System.getInt(mContext.getContentResolver(), - Settings.System.AIRPLANE_MODE_ON, 0) == 1) { - mPhoneSignalIconId = R.drawable.stat_sys_signal_flightmode; - contentDescription = mContext.getString(R.string.accessibility_airplane_mode); - } else { - mPhoneSignalIconId = R.drawable.stat_sys_signal_null; - contentDescription = mContext.getString(R.string.accessibility_no_phone); - } - mService.setIcon("phone_signal", mPhoneSignalIconId, 0, contentDescription); - return; - } - - if (!isCdma()) { - // Though mPhone is a Manager, this call is not an IPC - if (mPhone.isNetworkRoaming()) { - iconList = sSignalImages_r[mInetCondition]; - } else { - iconList = sSignalImages[mInetCondition]; - } - } else { - iconList = sSignalImages[mInetCondition]; - } - - final int signalLevel = mSignalStrength.getLevel(); - mPhoneSignalIconId = iconList[signalLevel]; - contentDescription = mContext.getString(sPhoneSignalStrength[signalLevel]); - mService.setIcon("phone_signal", mPhoneSignalIconId, 0, contentDescription); - } - - private final void updateDataNetType(int net) { - switch (net) { - case TelephonyManager.NETWORK_TYPE_EDGE: - mDataIconList = sDataNetType_e[mInetCondition]; - break; - case TelephonyManager.NETWORK_TYPE_UMTS: - mDataIconList = sDataNetType_3g[mInetCondition]; - break; - case TelephonyManager.NETWORK_TYPE_HSDPA: - case TelephonyManager.NETWORK_TYPE_HSUPA: - case TelephonyManager.NETWORK_TYPE_HSPA: - if (mHspaDataDistinguishable) { - mDataIconList = sDataNetType_h[mInetCondition]; - } else { - mDataIconList = sDataNetType_3g[mInetCondition]; - } - break; - case TelephonyManager.NETWORK_TYPE_CDMA: - // display 1xRTT for IS95A/B - mDataIconList = sDataNetType_1x[mInetCondition]; - break; - case TelephonyManager.NETWORK_TYPE_1xRTT: - mDataIconList = sDataNetType_1x[mInetCondition]; - break; - case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through - case TelephonyManager.NETWORK_TYPE_EVDO_A: - case TelephonyManager.NETWORK_TYPE_EVDO_B: - case TelephonyManager.NETWORK_TYPE_EHRPD: - mDataIconList = sDataNetType_3g[mInetCondition]; - break; - case TelephonyManager.NETWORK_TYPE_LTE: - mDataIconList = sDataNetType_4g[mInetCondition]; - break; - default: - mDataIconList = sDataNetType_g[mInetCondition]; - break; - } - } - - private final void updateDataIcon() { - int iconId; - String contentDescription = null; - boolean visible = true; - - if (!isCdma()) { - // GSM case, we have to check also the sim state - if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) { - if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) { - switch (mDataActivity) { - case TelephonyManager.DATA_ACTIVITY_IN: - iconId = mDataIconList[1]; - break; - case TelephonyManager.DATA_ACTIVITY_OUT: - iconId = mDataIconList[2]; - break; - case TelephonyManager.DATA_ACTIVITY_INOUT: - iconId = mDataIconList[3]; - break; - default: - iconId = mDataIconList[0]; - break; - } - contentDescription = mContext.getString(sDataConnectionStrength[mDataActivity]); - mService.setIcon("data_connection", iconId, 0, contentDescription); - } else { - visible = false; - } - } else { - iconId = R.drawable.stat_sys_no_sim; - contentDescription = mContext.getString(R.string.accessibility_no_sim); - mService.setIcon("data_connection", iconId, 0, contentDescription); - } - } else { - // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT - if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) { - switch (mDataActivity) { - case TelephonyManager.DATA_ACTIVITY_IN: - iconId = mDataIconList[1]; - break; - case TelephonyManager.DATA_ACTIVITY_OUT: - iconId = mDataIconList[2]; - break; - case TelephonyManager.DATA_ACTIVITY_INOUT: - iconId = mDataIconList[3]; - break; - case TelephonyManager.DATA_ACTIVITY_DORMANT: - default: - iconId = mDataIconList[0]; - break; - } - mService.setIcon("data_connection", iconId, 0, null); - } else { - visible = false; - } - } - - long ident = Binder.clearCallingIdentity(); - try { - mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible); - } catch (RemoteException e) { - } finally { - Binder.restoreCallingIdentity(ident); - } - - if (mDataIconVisible != visible) { - mService.setIconVisibility("data_connection", visible); - mDataIconVisible = visible; - } } private final void updateVolume() { @@ -990,65 +278,6 @@ public class PhoneStatusBarPolicy { mService.setIconVisibility("bluetooth", mBluetoothEnabled); } - private final void updateWifi(Intent intent) { - final String action = intent.getAction(); - if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { - - final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, - WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED; - - if (!enabled) { - // If disabled, hide the icon. (We show icon when connected.) - mService.setIconVisibility("wifi", false); - } - - } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) { - final boolean enabled = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, - false); - if (!enabled) { - mService.setIconVisibility("wifi", false); - } - } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { - int iconId; - String contentDescription = null; - final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200); - int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, - sWifiSignalImages[0].length); - if (newSignalLevel != mLastWifiSignalLevel) { - mLastWifiSignalLevel = newSignalLevel; - if (mIsWifiConnected) { - iconId = sWifiSignalImages[mInetCondition][newSignalLevel]; - contentDescription = mContext.getString( - sWifiConnectionStrength[newSignalLevel]); - } else { - iconId = sWifiTemporarilyNotConnectedImage; - contentDescription = mContext.getString(R.string.accessibility_no_wifi); - } - mService.setIcon("wifi", iconId, 0, contentDescription); - } - } - } - - private final void updateGps(Intent intent) { - final String action = intent.getAction(); - final boolean enabled = intent.getBooleanExtra(LocationManager.EXTRA_GPS_ENABLED, false); - - if (action.equals(LocationManager.GPS_FIX_CHANGE_ACTION) && enabled) { - // GPS is getting fixes - mService.setIcon("gps", com.android.internal.R.drawable.stat_sys_gps_on, 0, - mContext.getString(R.string.accessibility_gps_enabled)); - mService.setIconVisibility("gps", true); - } else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) && !enabled) { - // GPS is off - mService.setIconVisibility("gps", false); - } else { - // GPS is on, but not receiving fixes - mService.setIcon("gps", R.drawable.stat_sys_gps_acquiring_anim, 0, - mContext.getString(R.string.accessibility_gps_acquiring)); - mService.setIconVisibility("gps", true); - } - } - private final void updateTTY(Intent intent) { final String action = intent.getAction(); final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false); @@ -1067,49 +296,4 @@ public class PhoneStatusBarPolicy { mService.setIconVisibility("tty", false); } } - - private final void updateCdmaRoamingIcon(ServiceState state) { - if (!hasService()) { - mService.setIconVisibility("cdma_eri", false); - return; - } - - if (!isCdma()) { - mService.setIconVisibility("cdma_eri", false); - return; - } - - int[] iconList = sRoamingIndicatorImages_cdma; - int iconIndex = state.getCdmaEriIconIndex(); - int iconMode = state.getCdmaEriIconMode(); - - if (iconIndex == -1) { - Slog.e(TAG, "getCdmaEriIconIndex returned null, skipping ERI icon update"); - return; - } - - if (iconMode == -1) { - Slog.e(TAG, "getCdmeEriIconMode returned null, skipping ERI icon update"); - return; - } - - if (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) { - if (false) Slog.v(TAG, "Cdma ROAMING_INDICATOR_OFF, removing ERI icon"); - mService.setIconVisibility("cdma_eri", false); - return; - } - - switch (iconMode) { - case EriInfo.ROAMING_ICON_MODE_NORMAL: - mService.setIcon("cdma_eri", iconList[iconIndex], 0, null); - mService.setIconVisibility("cdma_eri", true); - break; - case EriInfo.ROAMING_ICON_MODE_FLASH: - mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_flash, 0, null); - mService.setIconVisibility("cdma_eri", true); - break; - - } - mService.setIcon("phone_signal", mPhoneSignalIconId, 0, null); - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java index 3957c1b80ab3..ff418c4500e9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java @@ -56,9 +56,11 @@ public class BatteryController extends BroadcastReceiver { final String action = intent.getAction(); if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { final int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); + final boolean plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0; + final int icon = plugged ? R.drawable.stat_sys_battery_charge + : R.drawable.stat_sys_battery; int N = mIconViews.size(); for (int i=0; i<N; i++) { - final int icon = intent.getIntExtra(BatteryManager.EXTRA_ICON_SMALL, 0); ImageView v = mIconViews.get(i); v.setImageResource(icon); v.setImageLevel(level); @@ -67,7 +69,6 @@ public class BatteryController extends BroadcastReceiver { } N = mLabelViews.size(); for (int i=0; i<N; i++) { - //final boolean plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0; TextView v = mLabelViews.get(i); v.setText(mContext.getString(R.string.status_bar_settings_battery_meter_format, level)); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 829855b697ad..f32c6021386f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -127,6 +127,8 @@ public class NetworkController extends BroadcastReceiver { int mLastDataTypeIconId = -1; String mLastLabel = ""; + boolean mDataAndWifiStacked = false; + // yuck -- stop doing this here and put it in the framework IBatteryStats mBatteryStats; @@ -211,6 +213,10 @@ public class NetworkController extends BroadcastReceiver { mLabelViews.add(v); } + public void setStackedMode(boolean stacked) { + mDataAndWifiStacked = true; + } + @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); @@ -648,7 +654,11 @@ public class NetworkController extends BroadcastReceiver { mContentDescriptionWifi = mContext.getString( AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH[mWifiLevel]); } else { - mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]; + if (mDataAndWifiStacked) { + mWifiIconId = 0; + } else { + mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]; + } mContentDescriptionWifi = mContext.getString(R.string.accessibility_no_wifi); } } @@ -823,8 +833,13 @@ public class NetworkController extends BroadcastReceiver { N = mWifiIconViews.size(); for (int i=0; i<N; i++) { final ImageView v = mWifiIconViews.get(i); - v.setImageResource(mWifiIconId); - v.setContentDescription(mContentDescriptionWifi); + if (mWifiIconId == 0) { + v.setVisibility(View.INVISIBLE); + } else { + v.setVisibility(View.VISIBLE); + v.setImageResource(mWifiIconId); + v.setContentDescription(mContentDescriptionWifi); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java index d5885bb81c25..90234c77560c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java @@ -21,47 +21,33 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.TimeAnimator; -import android.animation.ValueAnimator; import android.content.Context; -import android.content.res.Resources; +import android.content.res.Configuration; import android.content.res.TypedArray; -import android.graphics.Canvas; import android.graphics.Rect; -import android.graphics.drawable.Drawable; import android.util.AttributeSet; +import android.util.Log; import android.util.Slog; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; -import android.view.animation.AccelerateInterpolator; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import java.util.HashSet; import com.android.systemui.R; +import com.android.systemui.SwipeHelper; + +import java.util.HashSet; -public class NotificationRowLayout extends ViewGroup { +public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Callback { private static final String TAG = "NotificationRowLayout"; private static final boolean DEBUG = false; private static final boolean SLOW_ANIMATIONS = false; // DEBUG; private static final boolean ANIMATE_LAYOUT = true; - private static final boolean CLEAR_IF_SWIPED_FAR_ENOUGH = true; - - private static final boolean CONSTRAIN_SWIPE_ON_PERMANENT = true; - private static final int APPEAR_ANIM_LEN = SLOW_ANIMATIONS ? 5000 : 250; private static final int DISAPPEAR_ANIM_LEN = APPEAR_ANIM_LEN; - private static final int SNAP_ANIM_LEN = SLOW_ANIMATIONS ? 1000 : 250; - - private static final float SWIPE_ESCAPE_VELOCITY = 1500f; - private static final float SWIPE_ANIM_VELOCITY_MIN = 1000f; Rect mTmpRect = new Rect(); int mNumRows = 0; @@ -71,10 +57,7 @@ public class NotificationRowLayout extends ViewGroup { HashSet<View> mAppearingViews = new HashSet<View>(); HashSet<View> mDisappearingViews = new HashSet<View>(); - VelocityTracker mVT; - float mInitialTouchX, mInitialTouchY; - View mSlidingChild = null; - float mLiftoffVelocity; + private SwipeHelper mSwipeHelper; public NotificationRowLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); @@ -83,8 +66,6 @@ public class NotificationRowLayout extends ViewGroup { public NotificationRowLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - mVT = VelocityTracker.obtain(); - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NotificationRowLayout, defStyle, 0); mRowHeight = a.getDimensionPixelSize(R.styleable.NotificationRowLayout_rowHeight, 0); @@ -107,117 +88,71 @@ public class NotificationRowLayout extends ViewGroup { setBackgroundColor(0x80FF8000); } + float densityScale = getResources().getDisplayMetrics().density; + float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); + mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop); } - // Swipey code @Override public boolean onInterceptTouchEvent(MotionEvent ev) { - final int action = ev.getAction(); -// if (DEBUG) Slog.d(TAG, "intercepting touch event: " + ev); - switch (action) { - case MotionEvent.ACTION_DOWN: - mVT.clear(); - mVT.addMovement(ev); - mInitialTouchX = ev.getX(); - mInitialTouchY = ev.getY(); - mSlidingChild = null; - break; - case MotionEvent.ACTION_MOVE: - mVT.addMovement(ev); - if (mSlidingChild == null) { - if (Math.abs(ev.getX() - mInitialTouchX) > 4) { // slide slop - - // find the view under the pointer, accounting for GONE views - final int count = getChildCount(); - int y = 0; - int childIdx = 0; - for (; childIdx < count; childIdx++) { - mSlidingChild = getChildAt(childIdx); - if (mSlidingChild.getVisibility() == GONE) { - continue; - } - y += mRowHeight; - if (mInitialTouchY < y) break; - } - - mInitialTouchX -= mSlidingChild.getTranslationX(); - mSlidingChild.animate().cancel(); - - if (DEBUG) { - Slog.d(TAG, String.format( - "now sliding child %d: %s (touchY=%.1f, rowHeight=%d, count=%d)", - childIdx, mSlidingChild, mInitialTouchY, mRowHeight, count)); - } - - - // We need to prevent the surrounding ScrollView from intercepting us now; - // the scroll position will be locked while we swipe - requestDisallowInterceptTouchEvent(true); - } - } - break; - } - return mSlidingChild != null; + if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()"); + return mSwipeHelper.onInterceptTouchEvent(ev) || + super.onInterceptTouchEvent(ev); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + return mSwipeHelper.onTouchEvent(ev) || + super.onTouchEvent(ev); } - protected boolean canBeCleared(View v) { + public boolean canChildBeDismissed(View v) { final View veto = v.findViewById(R.id.veto); return (veto != null && veto.getVisibility() != View.GONE); } - protected boolean clear(View v) { + public void onChildDismissed(View v) { final View veto = v.findViewById(R.id.veto); if (veto != null && veto.getVisibility() != View.GONE) { veto.performClick(); - return true; } - return false; } - @Override - public boolean onTouchEvent(MotionEvent ev) { - final int action = ev.getAction(); -// if (DEBUG) Slog.d(TAG, "touch event: " + ev + " sliding: " + mSlidingChild); - if (mSlidingChild != null) { - switch (action) { - case MotionEvent.ACTION_OUTSIDE: - case MotionEvent.ACTION_MOVE: - mVT.addMovement(ev); - - float delta = (ev.getX() - mInitialTouchX); - if (CONSTRAIN_SWIPE_ON_PERMANENT && !canBeCleared(mSlidingChild)) { - delta = Math.copySign( - Math.min(Math.abs(delta), - mSlidingChild.getMeasuredWidth() * 0.2f), delta); - } - mSlidingChild.setTranslationX(delta); - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - mVT.addMovement(ev); - mVT.computeCurrentVelocity(1000 /* px/sec */); - if (DEBUG) Slog.d(TAG, "exit velocity: " + mVT.getXVelocity()); - boolean restore = true; - mLiftoffVelocity = mVT.getXVelocity(); - if (Math.abs(mLiftoffVelocity) > SWIPE_ESCAPE_VELOCITY - || (CLEAR_IF_SWIPED_FAR_ENOUGH && - (mSlidingChild.getTranslationX() * 2) > mSlidingChild.getMeasuredWidth())) - { - - // flingadingy - restore = ! clear(mSlidingChild); - } - if (restore) { - // snappity - mSlidingChild.animate().translationX(0) - .setDuration(SNAP_ANIM_LEN) - .start(); - } - break; + public void onBeginDrag(View v) { + // We need to prevent the surrounding ScrollView from intercepting us now; + // the scroll position will be locked while we swipe + requestDisallowInterceptTouchEvent(true); + } + + public View getChildAtPosition(MotionEvent ev) { + // find the view under the pointer, accounting for GONE views + final int count = getChildCount(); + int y = 0; + int touchY = (int) ev.getY(); + int childIdx = 0; + View slidingChild; + for (; childIdx < count; childIdx++) { + slidingChild = getChildAt(childIdx); + if (slidingChild.getVisibility() == GONE) { + continue; } - return true; + y += mRowHeight; + if (touchY < y) return slidingChild; } - return false; + return null; + } + + public View getChildContentView(View v) { + return v; + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + float densityScale = getResources().getDisplayMetrics().density; + mSwipeHelper.setDensityScale(densityScale); + float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); + mSwipeHelper.setPagingTouchSlop(pagingTouchSlop); } //** @@ -260,9 +195,10 @@ public class NotificationRowLayout extends ViewGroup { child.setPivotY(0); - final float velocity = (mSlidingChild == child) - ? Math.min(mLiftoffVelocity, SWIPE_ANIM_VELOCITY_MIN) - : SWIPE_ESCAPE_VELOCITY; + //final float velocity = (mSlidingChild == child) + // ? Math.min(mLiftoffVelocity, SWIPE_ANIM_VELOCITY_MIN) + // : SWIPE_ESCAPE_VELOCITY; + final float velocity = 0f; final TimeAnimator zoom = new TimeAnimator(); zoom.setTimeListener(new TimeAnimator.TimeListener() { @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java index 9093b3e18267..449ea997283c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java @@ -50,19 +50,6 @@ class TelephonyIcons { static final int[][] DATA_SIGNAL_STRENGTH = TELEPHONY_SIGNAL_STRENGTH; - static final int[][] DATA_SIGNAL_STRENGTH_ACTIVE = { - { R.drawable.stat_sys_signal_0, - R.drawable.stat_sys_signal_1_flowing, - R.drawable.stat_sys_signal_2_flowing, - R.drawable.stat_sys_signal_3_flowing, - R.drawable.stat_sys_signal_4_flowing }, - { R.drawable.stat_sys_signal_0_fully, - R.drawable.stat_sys_signal_1_fully_flowing, - R.drawable.stat_sys_signal_2_fully_flowing, - R.drawable.stat_sys_signal_3_fully_flowing, - R.drawable.stat_sys_signal_4_fully_flowing } - }; - //***** Data connection icons //GSM/UMTS diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java index 13846ed1e237..1d41ce024067 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -188,14 +188,33 @@ public class TabletStatusBar extends StatusBar implements mNotificationPanel.setOnTouchListener( new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PANEL, mNotificationPanel)); - // the battery and network icons + // the battery icon mBatteryController.addIconView((ImageView)mNotificationPanel.findViewById(R.id.battery)); mBatteryController.addLabelView( (TextView)mNotificationPanel.findViewById(R.id.battery_text)); + + // Bt mBluetoothController.addIconView( (ImageView)mNotificationPanel.findViewById(R.id.bluetooth)); - mNetworkController.addCombinedSignalIconView( - (ImageView)mNotificationPanel.findViewById(R.id.network_signal)); + + // network icons: either a combo icon that switches between mobile and data, or distinct + // mobile and data icons + final ImageView comboRSSI = + (ImageView)mNotificationPanel.findViewById(R.id.network_signal); + if (comboRSSI != null) { + mNetworkController.addCombinedSignalIconView(comboRSSI); + } + final ImageView mobileRSSI = + (ImageView)mNotificationPanel.findViewById(R.id.mobile_signal); + if (mobileRSSI != null) { + mNetworkController.addPhoneSignalIconView(mobileRSSI); + } + final ImageView wifiRSSI = + (ImageView)mNotificationPanel.findViewById(R.id.wifi_signal); + if (wifiRSSI != null) { + mNetworkController.addWifiIconView(wifiRSSI); + } + mNetworkController.addDataTypeIconView( (ImageView)mNotificationPanel.findViewById(R.id.network_type)); mNetworkController.addDataDirectionOverlayIconView( @@ -444,9 +463,23 @@ public class TabletStatusBar extends StatusBar implements mBatteryController.addIconView((ImageView)sb.findViewById(R.id.battery)); mBluetoothController = new BluetoothController(mContext); mBluetoothController.addIconView((ImageView)sb.findViewById(R.id.bluetooth)); + mNetworkController = new NetworkController(mContext); - mNetworkController.addCombinedSignalIconView( - (ImageView)sb.findViewById(R.id.network_signal)); + final ImageView comboRSSI = + (ImageView)sb.findViewById(R.id.network_signal); + if (comboRSSI != null) { + mNetworkController.addCombinedSignalIconView(comboRSSI); + } + final ImageView mobileRSSI = + (ImageView)sb.findViewById(R.id.mobile_signal); + if (mobileRSSI != null) { + mNetworkController.addPhoneSignalIconView(mobileRSSI); + } + final ImageView wifiRSSI = + (ImageView)sb.findViewById(R.id.wifi_signal); + if (wifiRSSI != null) { + mNetworkController.addWifiIconView(wifiRSSI); + } mNetworkController.addDataTypeIconView( (ImageView)sb.findViewById(R.id.network_type)); mNetworkController.addDataDirectionOverlayIconView( diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index e0debf7ca994..bfc3cddb334f 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -2040,13 +2040,14 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { mActionModePopup = new PopupWindow(mContext, null, com.android.internal.R.attr.actionModePopupWindowStyle); mActionModePopup.setLayoutInScreenEnabled(true); + mActionModePopup.setLayoutInsetDecor(true); mActionModePopup.setClippingEnabled(false); mActionModePopup.setContentView(mActionModeView); mActionModePopup.setWidth(MATCH_PARENT); TypedValue heightValue = new TypedValue(); mContext.getTheme().resolveAttribute( - com.android.internal.R.attr.actionBarSize, heightValue, false); + com.android.internal.R.attr.actionBarSize, heightValue, true); final int height = TypedValue.complexToDimensionPixelSize(heightValue.data, mContext.getResources().getDisplayMetrics()); mActionModePopup.setHeight(height); diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index ae13ab5a17a9..b7f6adffca1a 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -2444,20 +2444,22 @@ public class PhoneWindowManager implements WindowManagerPolicy { switch (keyCode) { case KeyEvent.KEYCODE_VOLUME_DOWN: if (down) { - // If the power key down was already triggered, take the screenshot - if (mPowerDownTriggered) { - // Dismiss the power-key longpress - mHandler.removeCallbacks(mPowerLongPress); - mPowerKeyHandled = true; - - // Take the screenshot - takeScreenshot(); - - // Prevent the event from being passed through to the current activity - result &= ~ACTION_PASS_TO_USER; - break; + if (isScreenOn) { + // If the power key down was already triggered, take the screenshot + if (mPowerDownTriggered) { + // Dismiss the power-key longpress + mHandler.removeCallbacks(mPowerLongPress); + mPowerKeyHandled = true; + + // Take the screenshot + takeScreenshot(); + + // Prevent the event from being passed through to the current activity + result &= ~ACTION_PASS_TO_USER; + break; + } + mVolumeDownTriggered = true; } - mVolumeDownTriggered = true; } else { mVolumeDownTriggered = false; } @@ -2541,17 +2543,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_POWER: { result &= ~ACTION_PASS_TO_USER; if (down) { - // If the volume down key has been triggered, then just take the screenshot - if (mVolumeDownTriggered) { - // Take the screenshot - takeScreenshot(); - mPowerKeyHandled = true; - - // Prevent the event from being passed through to the current activity - break; + if (isScreenOn) { + // If the volume down key has been triggered, then just take the screenshot + if (mVolumeDownTriggered) { + // Take the screenshot + takeScreenshot(); + mPowerKeyHandled = true; + + // Prevent the event from being passed through to the current activity + break; + } + mPowerDownTriggered = true; } - mPowerDownTriggered = true; - ITelephony telephonyService = getTelephonyService(); boolean hungUp = false; diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 0323fe0001a3..cb1f92134135 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -1043,6 +1043,25 @@ status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args return NO_ERROR; } +status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& args) +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + + snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size()); + write(fd, buffer, strlen(buffer)); + + for (size_t i = 0; i < mEffectChains.size(); ++i) { + sp<EffectChain> chain = mEffectChains[i]; + if (chain != 0) { + chain->dump(fd, args); + } + } + return NO_ERROR; +} + + // ---------------------------------------------------------------------------- AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, @@ -1111,24 +1130,6 @@ status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16> return NO_ERROR; } -status_t AudioFlinger::PlaybackThread::dumpEffectChains(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size()); - write(fd, buffer, strlen(buffer)); - - for (size_t i = 0; i < mEffectChains.size(); ++i) { - sp<EffectChain> chain = mEffectChains[i]; - if (chain != 0) { - chain->dump(fd, args); - } - } - return NO_ERROR; -} - status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args) { const size_t SIZE = 256; @@ -4178,6 +4179,7 @@ status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args) write(fd, result.string(), result.size()); dumpBase(fd, args); + dumpEffectChains(fd, args); return NO_ERROR; } diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index fff4f06ace47..e2cf946d0ace 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -285,6 +285,7 @@ private: }; status_t dumpBase(int fd, const Vector<String16>& args); + status_t dumpEffectChains(int fd, const Vector<String16>& args); // base for record and playback class TrackBase : public AudioBufferProvider, public RefBase { @@ -724,7 +725,6 @@ private: virtual status_t dumpInternals(int fd, const Vector<String16>& args); status_t dumpTracks(int fd, const Vector<String16>& args); - status_t dumpEffectChains(int fd, const Vector<String16>& args); SortedVector< sp<Track> > mTracks; // mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp index dd1e153621c7..6d06d83fab12 100644 --- a/services/audioflinger/AudioPolicyService.cpp +++ b/services/audioflinger/AudioPolicyService.cpp @@ -497,6 +497,43 @@ bool AudioPolicyService::isStreamActive(int stream, uint32_t inPastMs) const return mpAudioPolicy->is_stream_active(mpAudioPolicy, stream, inPastMs); } +status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession, + effect_descriptor_t *descriptors, + uint32_t *count) +{ + + if (mpAudioPolicy == NULL) { + *count = 0; + return NO_INIT; + } + Mutex::Autolock _l(mLock); + status_t status = NO_ERROR; + + size_t index; + for (index = 0; index < mInputs.size(); index++) { + if (mInputs.valueAt(index)->mSessionId == audioSession) { + break; + } + } + if (index == mInputs.size()) { + *count = 0; + return BAD_VALUE; + } + Vector< sp<AudioEffect> > effects = mInputs.valueAt(index)->mEffects; + + for (size_t i = 0; i < effects.size(); i++) { + effect_descriptor_t desc = effects[i]->descriptor(); + if (i < *count) { + memcpy(descriptors + i, &desc, sizeof(effect_descriptor_t)); + } + } + if (effects.size() > *count) { + status = NO_MEMORY; + } + *count = effects.size(); + return status; +} + void AudioPolicyService::binderDied(const wp<IBinder>& who) { LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid()); diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h index 62ad29ee5219..834b79421c78 100644 --- a/services/audioflinger/AudioPolicyService.h +++ b/services/audioflinger/AudioPolicyService.h @@ -104,6 +104,9 @@ public: virtual status_t unregisterEffect(int id); virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const; + virtual status_t queryDefaultPreProcessing(int audioSession, + effect_descriptor_t *descriptors, + uint32_t *count); virtual status_t onTransact( uint32_t code, const Parcel& data, diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 79c067570982..0843948df667 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -1926,7 +1926,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { } // Caller must grab mDnsLock. - private boolean updateDns(String network, Collection<InetAddress> dnses, String domains) { + private boolean updateDns(String network, String iface, + Collection<InetAddress> dnses, String domains) { boolean changed = false; int last = 0; if (dnses.size() == 0 && mDefaultDns != null) { @@ -1962,6 +1963,14 @@ public class ConnectivityService extends IConnectivityManager.Stub { } mNumDnsEntries = last; + if (changed) { + try { + mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses)); + mNetd.setDefaultInterfaceForDns(iface); + } catch (Exception e) { + Slog.e(TAG, "exception setting default dns interface: " + e); + } + } if (!domains.equals(SystemProperties.get("net.dns.search"))) { SystemProperties.set("net.dns.search", domains); changed = true; @@ -1981,10 +1990,16 @@ public class ConnectivityService extends IConnectivityManager.Stub { String network = nt.getNetworkInfo().getTypeName(); synchronized (mDnsLock) { if (!mDnsOverridden) { - changed = updateDns(network, dnses, ""); + changed = updateDns(network, p.getInterfaceName(), dnses, ""); } } } else { + try { + mNetd.setDnsServersForInterface(Integer.toString(netType), + NetworkUtils.makeStrings(dnses)); + } catch (Exception e) { + Slog.e(TAG, "exception setting dns servers: " + e); + } // set per-pid dns for attached secondary nets List pids = mNetRequestersPids[netType]; for (int y=0; y< pids.size(); y++) { @@ -2686,7 +2701,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { // Apply DNS changes. boolean changed = false; synchronized (mDnsLock) { - changed = updateDns("VPN", addresses, domains); + changed = updateDns("VPN", "VPN", addresses, domains); mDnsOverridden = true; } if (changed) { diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 5d7a48f491f4..8031c4e1f53e 100755 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -469,6 +469,24 @@ public class NotificationManagerService extends INotificationManager.Stub record = mToastQueue.get(index); record.update(duration); } else { + // Limit the number of toasts that any given package except the android + // package can enqueue. Prevents DOS attacks and deals with leaks. + if (!"android".equals(pkg)) { + int count = 0; + final int N = mToastQueue.size(); + for (int i=0; i<N; i++) { + final ToastRecord r = mToastQueue.get(i); + if (r.pkg.equals(pkg)) { + count++; + if (count >= MAX_PACKAGE_NOTIFICATIONS) { + Slog.e(TAG, "Package has already posted " + count + + " toasts. Not showing more. Package=" + pkg); + return; + } + } + } + } + record = new ToastRecord(callingPid, pkg, callback, duration); mToastQueue.add(record); index = mToastQueue.size() - 1; diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java index ffdc288db05d..3e76a3a1ae4e 100644 --- a/services/java/com/android/server/TextServicesManagerService.java +++ b/services/java/com/android/server/TextServicesManagerService.java @@ -81,14 +81,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap); // TODO: Update for each locale SpellCheckerInfo sci = getCurrentSpellChecker(null); - if (sci == null) { - sci = findAvailSpellCheckerLocked(null, null); - if (sci == null) return; - // Set the current spell checker if there is one or more spell checkers - // available. In this case, "sci" is the first one in the available spell - // checkers. - setCurrentSpellChecker(sci); - } + if (sci == null) return; final String packageName = sci.getPackageName(); final int change = isPackageDisappearing(packageName); if (change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE) { @@ -125,6 +118,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { list.add(sci); map.put(sci.getId(), sci); } + if (DBG) { + Slog.d(TAG, "buildSpellCheckerMapLocked: " + list.size() + "," + map.size()); + } } // TODO: find an appropriate spell checker for specified locale @@ -138,6 +134,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { for (int i = 0; i < spellCheckersCount; ++i) { final SpellCheckerInfo sci = mSpellCheckerList.get(i); if (prefPackage.equals(sci.getPackageName())) { + if (DBG) { + Slog.d(TAG, "findAvailSpellCheckerLocked: " + sci.getPackageName()); + } return sci; } } @@ -153,14 +152,20 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { @Override public SpellCheckerInfo getCurrentSpellChecker(String locale) { synchronized (mSpellCheckerMap) { - final String curSpellCheckerId = + String curSpellCheckerId = Settings.Secure.getString(mContext.getContentResolver(), Settings.Secure.SPELL_CHECKER_SERVICE); if (DBG) { Slog.w(TAG, "getCurrentSpellChecker: " + curSpellCheckerId); } if (TextUtils.isEmpty(curSpellCheckerId)) { - return null; + final SpellCheckerInfo sci = findAvailSpellCheckerLocked(null, null); + if (sci == null) return null; + // Set the current spell checker if there is one or more spell checkers + // available. In this case, "sci" is the first one in the available spell + // checkers. + setCurrentSpellChecker(sci); + return sci; } return mSpellCheckerMap.get(curSpellCheckerId); } @@ -202,11 +207,20 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { @Override public SpellCheckerInfo[] getEnabledSpellCheckers() { + if (DBG) { + Slog.d(TAG, "getEnabledSpellCheckers: " + mSpellCheckerList.size()); + for (int i = 0; i < mSpellCheckerList.size(); ++i) { + Slog.d(TAG, "EnabledSpellCheckers: " + mSpellCheckerList.get(i).getPackageName()); + } + } return mSpellCheckerList.toArray(new SpellCheckerInfo[mSpellCheckerList.size()]); } @Override public void finishSpellCheckerService(ISpellCheckerSessionListener listener) { + if (DBG) { + Slog.d(TAG, "FinishSpellCheckerService"); + } synchronized(mSpellCheckerMap) { for (SpellCheckerBindGroup group : mSpellCheckerBindGroups.values()) { if (group == null) continue; @@ -240,6 +254,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } public void onServiceConnected(ISpellCheckerService spellChecker) { + if (DBG) { + Slog.d(TAG, "onServiceConnected"); + } synchronized(mSpellCheckerMap) { for (InternalDeathRecipient listener : mListeners) { try { @@ -254,6 +271,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { public void addListener(ITextServicesSessionListener tsListener, String locale, ISpellCheckerSessionListener scListener) { + if (DBG) { + Slog.d(TAG, "addListener: " + locale); + } synchronized(mSpellCheckerMap) { try { final int size = mListeners.size(); @@ -276,6 +296,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } public void removeListener(ISpellCheckerSessionListener listener) { + if (DBG) { + Slog.d(TAG, "remove listener"); + } synchronized(mSpellCheckerMap) { final int size = mListeners.size(); final ArrayList<InternalDeathRecipient> removeList = @@ -295,6 +318,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } private void cleanLocked() { + if (DBG) { + Slog.d(TAG, "cleanLocked"); + } if (mListeners.isEmpty()) { mSpellCheckerBindGroups.remove(this); // Unbind service when there is no active clients. diff --git a/services/java/com/android/server/VibratorService.java b/services/java/com/android/server/VibratorService.java index c39dc805e684..de25747d476f 100755 --- a/services/java/com/android/server/VibratorService.java +++ b/services/java/com/android/server/VibratorService.java @@ -383,6 +383,12 @@ public class VibratorService extends IVibratorService.Stub { if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { synchronized (mVibrations) { doCancelVibrateLocked(); + + int size = mVibrations.size(); + for(int i = 0; i < size; i++) { + unlinkVibration(mVibrations.get(i)); + } + mVibrations.clear(); } } diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java index bb9d15b3ca05..92647e65368b 100644 --- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -49,6 +49,7 @@ import android.util.SparseArray; import android.view.IWindow; import android.view.View; import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.IAccessibilityInteractionConnection; import android.view.accessibility.IAccessibilityInteractionConnectionCallback; @@ -129,10 +130,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub private boolean mIsAccessibilityEnabled; - private boolean mIsTouchExplorationRequested; - private AccessibilityInputFilter mInputFilter; + private boolean mHasInputFilter; + private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList = new ArrayList<AccessibilityServiceInfo>(); private boolean mIsTouchExplorationEnabled; @@ -189,7 +190,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub manageServicesLocked(); } } - + @Override public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) { @@ -236,17 +237,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub mIsAccessibilityEnabled = Settings.Secure.getInt( mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1; - // if accessibility is enabled inform our clients we are on - if (mIsAccessibilityEnabled) { - sendAccessibilityEnabledToClientsLocked(); - } + manageServicesLocked(); // get touch exploration enabled setting on boot - mIsTouchExplorationRequested = Settings.Secure.getInt( + mIsTouchExplorationEnabled = Settings.Secure.getInt( mContext.getContentResolver(), - Settings.Secure.TOUCH_EXPLORATION_REQUESTED, 0) == 1; - updateTouchExplorationEnabledLocked(); + Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1; + updateInputFilterLocked(); + + sendStateToClientsLocked(); } return; @@ -288,13 +288,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } else { unbindAllServicesLocked(); } - sendAccessibilityEnabledToClientsLocked(); + sendStateToClientsLocked(); } } }); Uri touchExplorationRequestedUri = Settings.Secure.getUriFor( - Settings.Secure.TOUCH_EXPLORATION_REQUESTED); + Settings.Secure.TOUCH_EXPLORATION_ENABLED); contentResolver.registerContentObserver(touchExplorationRequestedUri, false, new ContentObserver(new Handler()) { @Override @@ -302,10 +302,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub super.onChange(selfChange); synchronized (mLock) { - mIsTouchExplorationRequested = Settings.Secure.getInt( + mIsTouchExplorationEnabled = Settings.Secure.getInt( mContext.getContentResolver(), - Settings.Secure.TOUCH_EXPLORATION_REQUESTED, 0) == 1; - updateTouchExplorationEnabledLocked(); + Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1; + updateInputFilterLocked(); + sendStateToClientsLocked(); } } }); @@ -325,7 +326,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub }); } - public boolean addClient(IAccessibilityManagerClient client) throws RemoteException { + public int addClient(IAccessibilityManagerClient client) throws RemoteException { synchronized (mLock) { final IAccessibilityManagerClient addedClient = client; mClients.add(addedClient); @@ -338,7 +339,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } }, 0); - return mIsAccessibilityEnabled; + return getState(); } } @@ -628,7 +629,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub service.linkToOwnDeath(); mServices.add(service); mComponentNameToServiceMap.put(service.mComponentName, service); - updateTouchExplorationEnabledLocked(); + updateInputFilterLocked(); } catch (RemoteException e) { /* do nothing */ } @@ -648,7 +649,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub mComponentNameToServiceMap.remove(service.mComponentName); mHandler.removeMessages(service.mId); service.unlinkToOwnDeath(); - updateTouchExplorationEnabledLocked(); + updateInputFilterLocked(); return removed; } @@ -781,12 +782,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } /** - * Updates the state of {@link android.view.accessibility.AccessibilityManager} clients. + * Sends the state to the clients. */ - private void sendAccessibilityEnabledToClientsLocked() { + private void sendStateToClientsLocked() { + final int state = getState(); for (int i = 0, count = mClients.size(); i < count; i++) { try { - mClients.get(i).setEnabled(mIsAccessibilityEnabled); + mClients.get(i).setState(state); } catch (RemoteException re) { mClients.remove(i); count--; @@ -796,48 +798,39 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } /** - * Sends the touch exploration state to clients. + * Gets the current state as a set of flags. + * + * @return The state. */ - private void sendTouchExplorationEnabledToClientsLocked() { - for (int i = 0, count = mClients.size(); i < count; i++) { - try { - mClients.get(i).setTouchExplorationEnabled(mIsTouchExplorationEnabled); - } catch (RemoteException re) { - mClients.remove(i); - count--; - i--; - } + private int getState() { + int state = 0; + if (mIsAccessibilityEnabled) { + state |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED; } + // Touch exploration relies on enabled accessibility. + if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) { + state |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED; + } + return state; } /** - * Updates the touch exploration state. Touch exploration is enabled if it - * is requested, accessibility is on and there is at least one enabled - * accessibility service providing spoken feedback. + * Updates the touch exploration state. */ - private void updateTouchExplorationEnabledLocked() { - if (mIsAccessibilityEnabled && mIsTouchExplorationRequested) { - final boolean hasSpeakingServicesEnabled = !getEnabledAccessibilityServiceList( - AccessibilityServiceInfo.FEEDBACK_SPOKEN).isEmpty(); - if (!mIsTouchExplorationEnabled) { - if (!hasSpeakingServicesEnabled) { - return; - } + private void updateInputFilterLocked() { + if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) { + if (!mHasInputFilter) { + mHasInputFilter = true; if (mInputFilter == null) { mInputFilter = new AccessibilityInputFilter(mContext); } mWindowManagerService.setInputFilter(mInputFilter); - mIsTouchExplorationEnabled = true; - sendTouchExplorationEnabledToClientsLocked(); - return; - } else if (hasSpeakingServicesEnabled) { - return; } + return; } - if (mIsTouchExplorationEnabled) { + if (mHasInputFilter) { + mHasInputFilter = false; mWindowManagerService.setInputFilter(null); - mIsTouchExplorationEnabled = false; - sendTouchExplorationEnabledToClientsLocked(); } } diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java index 5a3a55d24730..0ad58d095660 100644 --- a/services/java/com/android/server/accessibility/TouchExplorer.java +++ b/services/java/com/android/server/accessibility/TouchExplorer.java @@ -19,21 +19,21 @@ package com.android.server.accessibility; import static android.view.accessibility.AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END; import static android.view.accessibility.AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START; -import com.android.server.accessibility.AccessibilityInputFilter.Explorer; -import com.android.server.wm.InputFilter; - import android.content.Context; import android.os.Handler; import android.os.SystemClock; import android.util.Slog; import android.view.MotionEvent; -import android.view.ViewConfiguration; -import android.view.WindowManagerPolicy; import android.view.MotionEvent.PointerCoords; import android.view.MotionEvent.PointerProperties; +import android.view.ViewConfiguration; +import android.view.WindowManagerPolicy; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; +import com.android.server.accessibility.AccessibilityInputFilter.Explorer; +import com.android.server.wm.InputFilter; + import java.util.Arrays; /** @@ -146,6 +146,9 @@ public class TouchExplorer implements Explorer { // Command for delayed sending of a hover event. private final SendHoverDelayed mSendHoverDelayed; + // Command for delayed sending of a long press. + private final PerformLongPressDelayed mPerformLongPressDelayed; + /** * Creates a new instance. * @@ -160,6 +163,7 @@ public class TouchExplorer implements Explorer { mPointerTracker = new PointerTracker(context); mHandler = new Handler(context.getMainLooper()); mSendHoverDelayed = new SendHoverDelayed(); + mPerformLongPressDelayed = new PerformLongPressDelayed(); mAccessibilityManager = AccessibilityManager.getInstance(context); } @@ -208,15 +212,7 @@ public class TouchExplorer implements Explorer { final int activePointerCount = pointerTracker.getActivePointerCount(); switch (event.getActionMasked()) { - case MotionEvent.ACTION_DOWN: { - // Send a hover for every finger down so the user gets feedback - // where she is currently touching. - mSendHoverDelayed.forceSendAndRemove(); - final int pointerIndex = event.getActionIndex(); - final int pointerIdBits = (1 << event.getPointerId(pointerIndex)); - mSendHoverDelayed.post(event, MotionEvent.ACTION_HOVER_ENTER, pointerIdBits, - policyFlags, DELAY_SEND_HOVER_MOVE); - } break; + case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_DOWN: { switch (activePointerCount) { case 0: { @@ -224,13 +220,13 @@ public class TouchExplorer implements Explorer { + "touch exploring state!"); } case 1: { - // Schedule a hover event which will lead to firing an - // accessibility event from the hovered view. - mSendHoverDelayed.remove(); + // Send hover if pending. + mSendHoverDelayed.forceSendAndRemove(); + // Send a hover for every finger down so the user gets feedback. final int pointerId = pointerTracker.getPrimaryActivePointerId(); final int pointerIdBits = (1 << pointerId); final int lastAction = pointerTracker.getLastInjectedHoverAction(); - // If a schedules hover enter for another pointer is delivered we send move. + // If a hover enter for another pointer is delivered we send move. final int action = (lastAction == MotionEvent.ACTION_HOVER_ENTER) ? MotionEvent.ACTION_HOVER_MOVE : MotionEvent.ACTION_HOVER_ENTER; @@ -244,7 +240,19 @@ public class TouchExplorer implements Explorer { // If more pointers down on the screen since the last touch // exploration we discard the last cached touch explore event. if (event.getPointerCount() != mLastTouchExploreEvent.getPointerCount()) { - mLastTouchExploreEvent = null; + mLastTouchExploreEvent = null; + break; + } + + // If the down is in the time slop => schedule a long press. + final long pointerDownTime = + pointerTracker.getReceivedPointerDownTime(pointerId); + final long lastExploreTime = mLastTouchExploreEvent.getEventTime(); + final long deltaTimeExplore = pointerDownTime - lastExploreTime; + if (deltaTimeExplore <= ACTIVATION_TIME_SLOP) { + mPerformLongPressDelayed.post(event, policyFlags, + ViewConfiguration.getLongPressTimeout()); + break; } } break; default: { @@ -275,6 +283,7 @@ public class TouchExplorer implements Explorer { sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_START); // Make sure the scheduled down/move event is sent. mSendHoverDelayed.forceSendAndRemove(); + mPerformLongPressDelayed.remove(); // If we have transitioned to exploring state from another one // we need to send a hover enter event here. final int lastAction = mPointerTracker.getLastInjectedHoverAction(); @@ -291,20 +300,11 @@ public class TouchExplorer implements Explorer { policyFlags); } - // Detect long press on the last touch explored position. - if (!mTouchExploreGestureInProgress && mLastTouchExploreEvent != null) { + // If the exploring pointer moved enough => cancel the long press. + if (!mTouchExploreGestureInProgress && mLastTouchExploreEvent != null + && mPerformLongPressDelayed.isPenidng()) { - // If the down was not in the time slop => nothing else to do. - final long pointerDownTime = - pointerTracker.getReceivedPointerDownTime(pointerId); - final long lastExploreTime = mLastTouchExploreEvent.getEventTime(); - final long deltaTimeExplore = pointerDownTime - lastExploreTime; - if (deltaTimeExplore > ACTIVATION_TIME_SLOP) { - mLastTouchExploreEvent = null; - break; - } - - // If the pointer moved more than the tap slop => nothing else to do. + // If the pointer moved more than the tap slop => cancel long press. final float deltaX = mLastTouchExploreEvent.getX(pointerIndex) - event.getX(pointerIndex); final float deltaY = mLastTouchExploreEvent.getY(pointerIndex) @@ -312,24 +312,14 @@ public class TouchExplorer implements Explorer { final float moveDelta = (float) Math.hypot(deltaX, deltaY); if (moveDelta > mTouchExplorationTapSlop) { mLastTouchExploreEvent = null; + mPerformLongPressDelayed.remove(); break; } - - // If down for long enough we get a long press. - final long deltaTimeMove = event.getEventTime() - pointerDownTime; - if (deltaTimeMove > ViewConfiguration.getLongPressTimeout()) { - mCurrentState = STATE_DELEGATING; - // Make sure the scheduled hover exit is delivered. - mSendHoverDelayed.forceSendAndRemove(); - sendDownForAllActiveNotInjectedPointers(event, policyFlags); - sendMotionEvent(event, policyFlags); - mTouchExploreGestureInProgress = false; - mLastTouchExploreEvent = null; - } } } break; case 2: { mSendHoverDelayed.forceSendAndRemove(); + mPerformLongPressDelayed.remove(); // We want to no longer hover over the location so subsequent // touch at the same spot will generate a hover enter. sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits, @@ -360,6 +350,7 @@ public class TouchExplorer implements Explorer { } break; default: { mSendHoverDelayed.forceSendAndRemove(); + mPerformLongPressDelayed.remove(); // We want to no longer hover over the location so subsequent // touch at the same spot will generate a hover enter. sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits, @@ -388,22 +379,26 @@ public class TouchExplorer implements Explorer { break; } + mSendHoverDelayed.forceSendAndRemove(); + mPerformLongPressDelayed.remove(); + // If touch exploring announce the end of the gesture. + // Also do not click on the last explored location. if (mTouchExploreGestureInProgress) { - sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_END); mTouchExploreGestureInProgress = false; + mLastTouchExploreEvent = MotionEvent.obtain(event); + sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_END); + break; } // Detect whether to activate i.e. click on the last explored location. if (mLastTouchExploreEvent != null) { - // If the down was not in the time slop => nothing else to do. final long eventTime = pointerTracker.getLastReceivedUpPointerDownTime(); final long exploreTime = mLastTouchExploreEvent.getEventTime(); final long deltaTime = eventTime - exploreTime; if (deltaTime > ACTIVATION_TIME_SLOP) { - mSendHoverDelayed.forceSendAndRemove(); final int lastAction = mPointerTracker.getLastInjectedHoverAction(); if (lastAction != MotionEvent.ACTION_HOVER_EXIT) { sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, @@ -413,15 +408,14 @@ public class TouchExplorer implements Explorer { break; } - // If the pointer moved more than the tap slop => nothing else to do. + // If a tap is farther than the tap slop => nothing to do. final int pointerIndex = event.findPointerIndex(pointerId); - final float deltaX = pointerTracker.getLastReceivedUpPointerDownX() + final float deltaX = mLastTouchExploreEvent.getX(pointerIndex) - event.getX(pointerIndex); - final float deltaY = pointerTracker.getLastReceivedUpPointerDownY() + final float deltaY = mLastTouchExploreEvent.getY(pointerIndex) - event.getY(pointerIndex); final float deltaMove = (float) Math.hypot(deltaX, deltaY); if (deltaMove > mTouchExplorationTapSlop) { - mSendHoverDelayed.forceSendAndRemove(); final int lastAction = mPointerTracker.getLastInjectedHoverAction(); if (lastAction != MotionEvent.ACTION_HOVER_EXIT) { sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, @@ -432,7 +426,6 @@ public class TouchExplorer implements Explorer { } // All preconditions are met, so click the last explored location. - mSendHoverDelayed.forceSendAndRemove(); sendActionDownAndUp(mLastTouchExploreEvent, policyFlags); mLastTouchExploreEvent = null; } else { @@ -448,6 +441,8 @@ public class TouchExplorer implements Explorer { } } break; case MotionEvent.ACTION_CANCEL: { + mSendHoverDelayed.remove(); + mPerformLongPressDelayed.remove(); final int lastAction = pointerTracker.getLastInjectedHoverAction(); if (lastAction != MotionEvent.ACTION_HOVER_EXIT) { final int pointerId = pointerTracker.getPrimaryActivePointerId(); @@ -934,8 +929,6 @@ public class TouchExplorer implements Explorer { private int mInjectedPointersDown; // Keep track of the last up pointer data. - private float mLastReceivedUpPointerDownX; - private float mLastReveivedUpPointerDownY; private long mLastReceivedUpPointerDownTime; private int mLastReceivedUpPointerId; private boolean mLastReceivedUpPointerActive; @@ -968,8 +961,6 @@ public class TouchExplorer implements Explorer { mPrimaryActivePointerId = 0; mHasMovingActivePointer = false; mInjectedPointersDown = 0; - mLastReceivedUpPointerDownX = 0; - mLastReveivedUpPointerDownY = 0; mLastReceivedUpPointerDownTime = 0; mLastReceivedUpPointerId = 0; mLastReceivedUpPointerActive = false; @@ -1126,20 +1117,6 @@ public class TouchExplorer implements Explorer { } /** - * @return The X coordinate where the last up received pointer went down. - */ - public float getLastReceivedUpPointerDownX() { - return mLastReceivedUpPointerDownX; - } - - /** - * @return The Y coordinate where the last up received pointer went down. - */ - public float getLastReceivedUpPointerDownY() { - return mLastReveivedUpPointerDownY; - } - - /** * @return The time when the last up received pointer went down. */ public long getLastReceivedUpPointerDownTime() { @@ -1220,8 +1197,6 @@ public class TouchExplorer implements Explorer { final int pointerFlag = (1 << pointerId); mLastReceivedUpPointerId = 0; - mLastReceivedUpPointerDownX = 0; - mLastReveivedUpPointerDownY = 0; mLastReceivedUpPointerDownTime = 0; mLastReceivedUpPointerActive = false; @@ -1262,8 +1237,6 @@ public class TouchExplorer implements Explorer { final int pointerFlag = (1 << pointerId); mLastReceivedUpPointerId = pointerId; - mLastReceivedUpPointerDownX = getReceivedPointerDownX(pointerId); - mLastReveivedUpPointerDownY = getReceivedPointerDownY(pointerId); mLastReceivedUpPointerDownTime = getReceivedPointerDownTime(pointerId); mLastReceivedUpPointerActive = isActivePointer(pointerId); @@ -1400,6 +1373,51 @@ public class TouchExplorer implements Explorer { } /** + * Class for delayed sending of long press. + */ + private final class PerformLongPressDelayed implements Runnable { + private MotionEvent mEvent; + private int mPolicyFlags; + + public void post(MotionEvent prototype, int policyFlags, long delay) { + mEvent = MotionEvent.obtain(prototype); + mPolicyFlags = policyFlags; + mHandler.postDelayed(this, delay); + } + + public void remove() { + if (isPenidng()) { + mHandler.removeCallbacks(this); + clear(); + } + } + + private boolean isPenidng() { + return (mEvent != null); + } + + @Override + public void run() { + mCurrentState = STATE_DELEGATING; + // Make sure the scheduled hover exit is delivered. + mSendHoverDelayed.forceSendAndRemove(); + sendDownForAllActiveNotInjectedPointers(mEvent, mPolicyFlags); + mTouchExploreGestureInProgress = false; + mLastTouchExploreEvent = null; + clear(); + } + + private void clear() { + if (!isPenidng()) { + return; + } + mEvent.recycle(); + mEvent = null; + mPolicyFlags = 0; + } + } + + /** * Class for delayed sending of hover events. */ private final class SendHoverDelayed implements Runnable { diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index d6a15e63fa90..9eb1179b8caf 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -2860,8 +2860,17 @@ public class PackageManagerService extends IPackageManager.Stub { } private File getDataPathForPackage(String packageName, int userId) { - return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId + /* + * Until we fully support multiple users, return the directory we + * previously would have. The PackageManagerTests will need to be + * revised when this is changed back.. + */ + if (userId == 0) { + return new File(mAppDataDir, packageName); + } else { + return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId + File.separator + packageName); + } } private PackageParser.Package scanPackageLI(PackageParser.Package pkg, diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp index 24d5f9ac9875..05b7527563fa 100644 --- a/services/surfaceflinger/Transform.cpp +++ b/services/surfaceflinger/Transform.cpp @@ -308,7 +308,7 @@ uint32_t Transform::getOrientation() const bool Transform::preserveRects() const { - return (type() & ROT_INVALID) ? false : true; + return (getOrientation() & ROT_INVALID) ? false : true; } void Transform::dump(const char* name) const diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java index 1234bfd8220e..46bcc4a259db 100644 --- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java @@ -29,12 +29,13 @@ import android.provider.Settings; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.LargeTest; import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IAccessibilityManager; import android.view.accessibility.IAccessibilityManagerClient; /** * This test exercises the - * {@link com.android.server.AccessibilityManagerService} by mocking the + * {@link com.android.server.accessibility.AccessibilityManagerService} by mocking the * {@link android.view.accessibility.AccessibilityManager} which talks to to the * service. The service itself is interacting with the platform. Note: Testing * the service in full isolation would require significant amount of work for @@ -97,7 +98,9 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase { MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient(); // invoke the method under test - boolean enabledAccessibilityDisabled = mManagerService.addClient(mockClient); + final int stateFlagsDisabled = mManagerService.addClient(mockClient); + boolean enabledAccessibilityDisabled = + (stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0; // check expected result assertFalse("The client must be disabled since accessibility is disabled.", @@ -107,7 +110,10 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase { ensureAccessibilityEnabled(mContext, true); // invoke the method under test - boolean enabledAccessibilityEnabled = mManagerService.addClient(mockClient); + final int stateFlagsEnabled = mManagerService.addClient(mockClient); + boolean enabledAccessibilityEnabled = + (stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0; + // check expected result assertTrue("The client must be enabled since accessibility is enabled.", @@ -123,7 +129,9 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase { MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient(); // invoke the method under test - boolean enabledAccessibilityEnabled = mManagerService.addClient(mockClient); + final int stateFlagsEnabled = mManagerService.addClient(mockClient); + boolean enabledAccessibilityEnabled = + (stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0; // check expected result assertTrue("The client must be enabled since accessibility is enabled.", @@ -133,7 +141,9 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase { ensureAccessibilityEnabled(mContext, false); // invoke the method under test - boolean enabledAccessibilityDisabled = mManagerService.addClient(mockClient); + final int stateFlagsDisabled = mManagerService.addClient(mockClient); + boolean enabledAccessibilityDisabled = + (stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0; // check expected result assertFalse("The client must be disabled since accessibility is disabled.", @@ -537,10 +547,10 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase { * This class is a mock {@link IAccessibilityManagerClient}. */ public class MyMockAccessibilityManagerClient extends IAccessibilityManagerClient.Stub { - boolean mIsEnabled; + int mState; - public void setEnabled(boolean enabled) { - mIsEnabled = enabled; + public void setState(int state) { + mState = state; } public void setTouchExplorationEnabled(boolean enabled) { diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java index 1463d3055fda..e08381532427 100644 --- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java @@ -70,7 +70,8 @@ public class AccessibilityManagerTest extends AndroidTestCase { // configure the mock service behavior IAccessibilityManager mockServiceInterface = mMockServiceInterface; - expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true); + expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn( + AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); expect(mockServiceInterface.getInstalledAccessibilityServiceList()).andReturn( expectedServices); replay(mockServiceInterface); @@ -91,7 +92,8 @@ public class AccessibilityManagerTest extends AndroidTestCase { public void testInterrupt() throws Exception { // configure the mock service behavior IAccessibilityManager mockServiceInterface = mMockServiceInterface; - expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true); + expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn( + AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); mockServiceInterface.interrupt(); replay(mockServiceInterface); @@ -107,7 +109,8 @@ public class AccessibilityManagerTest extends AndroidTestCase { public void testIsEnabled() throws Exception { // configure the mock service behavior IAccessibilityManager mockServiceInterface = mMockServiceInterface; - expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true); + expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn( + AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); replay(mockServiceInterface); // invoke the method under test @@ -118,7 +121,7 @@ public class AccessibilityManagerTest extends AndroidTestCase { assertTrue("Must be enabled since the mock service is enabled", isEnabledServiceEnabled); // disable accessibility - manager.getClient().setEnabled(false); + manager.getClient().setState(0); // wait for the asynchronous IBinder call to complete Thread.sleep(TIMEOUT_BINDER_CALL); @@ -141,7 +144,8 @@ public class AccessibilityManagerTest extends AndroidTestCase { // configure the mock service behavior IAccessibilityManager mockServiceInterface = mMockServiceInterface; - expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true); + expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn( + AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent))) .andReturn(true); expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent))) @@ -176,7 +180,7 @@ public class AccessibilityManagerTest extends AndroidTestCase { // configure the mock service behavior IAccessibilityManager mockServiceInterface = mMockServiceInterface; - expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(false); + expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(0); replay(mockServiceInterface); // invoke the method under test (accessibility disabled) diff --git a/tests/GridLayoutTest/res/layout/grid3.xml b/tests/GridLayoutTest/res/layout/grid3.xml index 3c2db545a6b3..2eca384be5ff 100644 --- a/tests/GridLayoutTest/res/layout/grid3.xml +++ b/tests/GridLayoutTest/res/layout/grid3.xml @@ -27,8 +27,8 @@ > <TextView - android:text="Email account" - android:textSize="48dip" + android:text="Email setup" + android:textSize="32dip" android:layout_columnSpan="4" android:layout_gravity="center_horizontal" @@ -36,7 +36,7 @@ <TextView android:text="You can configure email in just a few steps:" - android:textSize="20dip" + android:textSize="16dip" android:layout_columnSpan="4" android:layout_gravity="left" @@ -49,7 +49,7 @@ /> <EditText - android:layout_width="100dip" + android:layout_width="64dip" /> <TextView @@ -60,14 +60,14 @@ /> <EditText - android:layout_width="50dip" + android:layout_width="32dip" /> <Space android:layout_row="4" android:layout_column="2" - android:layout_rowFlexibility="canStretch" - android:layout_columnFlexibility="canStretch" + android:layout_margin="0dip" + android:layout_gravity="fill" /> <Button @@ -75,7 +75,6 @@ android:layout_row="5" android:layout_column="3" - android:layout_gravity="fill_horizontal" /> <Button diff --git a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java index 38a85a3a2c98..e1871ac809a0 100644 --- a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java +++ b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java @@ -38,30 +38,31 @@ public class Activity2 extends Activity { vg.setUseDefaultMargins(true); vg.setAlignmentMode(ALIGN_BOUNDS); - Spec row1 = spec(0, CENTER); - Spec row2 = spec(1, CENTER); + Spec row1 = spec(0); + Spec row2 = spec(1); Spec row3 = spec(2, BASELINE); Spec row4 = spec(3, BASELINE); - Spec row5 = spec(4, FILL, CAN_STRETCH); - Spec row6 = spec(5, CENTER); - Spec row7 = spec(6, CENTER); + Spec row5 = spec(4, FILL); + Spec row6 = spec(5); + Spec row7 = spec(6); Spec col1a = spec(0, 4, CENTER); Spec col1b = spec(0, 4, LEFT); Spec col1c = spec(0, RIGHT); Spec col2 = spec(1, LEFT); - Spec col3 = spec(2, FILL, CAN_STRETCH); - Spec col4 = spec(3, FILL); + Spec col3 = spec(2, FILL); + Spec col4a = spec(3); + Spec col4b = spec(3, FILL); { TextView v = new TextView(context); - v.setTextSize(48); + v.setTextSize(32); v.setText("Email setup"); vg.addView(v, new LayoutParams(row1, col1a)); } { TextView v = new TextView(context); - v.setTextSize(20); + v.setTextSize(16); v.setText("You can configure email in just a few steps:"); vg.addView(v, new LayoutParams(row2, col1b)); } @@ -75,7 +76,7 @@ public class Activity2 extends Activity { v.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_EMAIL_ADDRESS); { LayoutParams lp = new LayoutParams(row3, col2); - lp.width = (int) v.getPaint().measureText("Frederick.W.Flintstone@bedrock.com "); + lp.width = (int) v.getPaint().measureText("Frederick.W.Flintstone"); vg.addView(v, lp); } } @@ -95,17 +96,19 @@ public class Activity2 extends Activity { } { Space v = new Space(context); - vg.addView(v, new LayoutParams(row5, col3)); + LayoutParams lp = new LayoutParams(row5, col3); + lp.setMargins(0, 0, 0, 0); + vg.addView(v, lp); } { Button v = new Button(context); v.setText("Manual setup"); - vg.addView(v, new LayoutParams(row6, col4)); + vg.addView(v, new LayoutParams(row6, col4a)); } { Button v = new Button(context); v.setText("Next"); - vg.addView(v, new LayoutParams(row7, col4)); + vg.addView(v, new LayoutParams(row7, col4b)); } return vg; diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs index 16ebe08a11c7..d93238c2580c 100644 --- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs @@ -84,10 +84,10 @@ void filter() { fs.radius = radius; fs.ain = rsGetAllocation(ScratchPixel1); - rsForEach(hBlurScript, fs.ain, rsGetAllocation(ScratchPixel2), &fs); + rsForEach(hBlurScript, fs.ain, rsGetAllocation(ScratchPixel2), &fs, sizeof(fs)); fs.ain = rsGetAllocation(ScratchPixel2); - rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs); + rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs, sizeof(fs)); rsSendToClientBlocking(CMD_FINISHED); } diff --git a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs index f04695260f41..0e619ea1aff8 100644 --- a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs +++ b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs @@ -60,7 +60,7 @@ int root(void) { robot2Ptr->transforms[1].w += 2.5f; robot2Ptr->isDirty = 1; - rsForEach(gTransformRS, gRootNode->children, gRootNode->children, 0); + rsForEach(gTransformRS, gRootNode->children, gRootNode->children, NULL, 0); rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f); rsgClearDepth(1.0f); diff --git a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/transform.rs b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/transform.rs index f328025ecf96..85c06306071d 100644 --- a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/transform.rs +++ b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/transform.rs @@ -91,6 +91,6 @@ void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32 //rsDebug("Transform calling self with child ", (int)data->children.p); if (data->children.p) { - rsForEach(transformScript, data->children, data->children, (void*)&toChild); + rsForEach(transformScript, data->children, data->children, (void*)&toChild, sizeof(toChild)); } } diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs index eaafe1db3d40..db9783530971 100644 --- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs +++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs @@ -280,7 +280,7 @@ static void displayFontSamples(int fillNum) { testData.renderSurfaceW = gRenderSurfaceW; testData.renderSurfaceH = gRenderSurfaceH; testData.user = fillNum; - rsForEach(gFontScript, gDummyAlloc, gDummyAlloc, &testData); + rsForEach(gFontScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData)); } static void bindProgramVertexOrtho() { @@ -520,7 +520,7 @@ static void displaySimpleGeoSamples(bool useTexture, int numMeshes) { testData.user = 0; testData.user1 = useTexture ? 1 : 0; testData.user2 = numMeshes; - rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData); + rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData)); } static void displayCustomShaderSamples(int numMeshes) { @@ -530,7 +530,7 @@ static void displayCustomShaderSamples(int numMeshes) { testData.dt = gDt; testData.user = 1; testData.user1 = numMeshes; - rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData); + rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData)); } static void displayPixelLightSamples(int numMeshes, bool heavyVertex) { @@ -541,7 +541,7 @@ static void displayPixelLightSamples(int numMeshes, bool heavyVertex) { testData.user = 2; testData.user1 = numMeshes; testData.user2 = heavyVertex ? 1 : 0; - rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData); + rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData)); } static void displayMultitextureSample(bool blend, int quadCount) { diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java index 49ddf1d2fcb2..0e24cc011203 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java @@ -117,8 +117,10 @@ public class DelegateClassAdapter extends ClassAdapter { int accessDelegate = access; // change access to public for the original one - access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE); - access |= Opcodes.ACC_PUBLIC; + if (Main.sOptions.generatePublicAccess) { + access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE); + access |= Opcodes.ACC_PUBLIC; + } MethodVisitor mwOriginal = super.visitMethod(access, name + ORIGINAL_SUFFIX, desc, signature, exceptions); diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java index ce480697c094..9bf52c7826bb 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java @@ -37,7 +37,7 @@ import java.util.Set; * which does: * <pre> * $ make layoutlib_create <bunch of framework jars> - * $ out/host/linux-x86/framework/bin/layoutlib_create \ + * $ java -jar out/host/linux-x86/framework/layoutlib_create.jar \ * out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar \ * out/target/common/obj/JAVA_LIBRARIES/core_intermediates/classes.jar \ * out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar @@ -45,6 +45,12 @@ import java.util.Set; */ public class Main { + public static class Options { + public boolean generatePublicAccess = true; + } + + public static final Options sOptions = new Options(); + public static void main(String[] args) { Log log = new Log(); @@ -53,7 +59,7 @@ public class Main { String[] osDestJar = { null }; if (!processArgs(log, args, osJarPath, osDestJar)) { - log.error("Usage: layoutlib_create [-v] output.jar input.jar ..."); + log.error("Usage: layoutlib_create [-v] [-p] output.jar input.jar ..."); System.exit(1); } @@ -136,6 +142,8 @@ public class Main { String s = args[i]; if (s.equals("-v")) { log.setVerbose(true); + } else if (s.equals("-p")) { + sOptions.generatePublicAccess = false; } else if (!s.startsWith("-")) { if (osDestJar[0] == null) { osDestJar[0] = s; diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java index f2d97557f264..5a0a44a40e34 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java @@ -72,8 +72,10 @@ class TransformClassAdapter extends ClassAdapter { name = mClassName; // remove protected or private and set as public - access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED); - access |= Opcodes.ACC_PUBLIC; + if (Main.sOptions.generatePublicAccess) { + access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED); + access |= Opcodes.ACC_PUBLIC; + } // remove final access = access & ~Opcodes.ACC_FINAL; // note: leave abstract classes as such @@ -87,8 +89,10 @@ class TransformClassAdapter extends ClassAdapter { @Override public void visitInnerClass(String name, String outerName, String innerName, int access) { // remove protected or private and set as public - access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED); - access |= Opcodes.ACC_PUBLIC; + if (Main.sOptions.generatePublicAccess) { + access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED); + access |= Opcodes.ACC_PUBLIC; + } // remove final access = access & ~Opcodes.ACC_FINAL; // note: leave abstract classes as such @@ -117,8 +121,10 @@ class TransformClassAdapter extends ClassAdapter { String methodSignature = mClassName.replace('/', '.') + "#" + name; // change access to public - access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE); - access |= Opcodes.ACC_PUBLIC; + if (Main.sOptions.generatePublicAccess) { + access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE); + access |= Opcodes.ACC_PUBLIC; + } // remove final access = access & ~Opcodes.ACC_FINAL; @@ -155,9 +161,10 @@ class TransformClassAdapter extends ClassAdapter { public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { // change access to public - access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE); - access |= Opcodes.ACC_PUBLIC; - + if (Main.sOptions.generatePublicAccess) { + access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE); + access |= Opcodes.ACC_PUBLIC; + } return super.visitField(access, name, desc, signature, value); } |