diff options
63 files changed, 815 insertions, 444 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index cb53422..54b5836 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -1301,7 +1301,6 @@ public class Am { " am display-size [reset|MxN]\n" + " am to-uri [INTENT]\n" + " am to-intent-uri [INTENT]\n" + - " am switch-user <USER_ID>\n" + "\n" + "am start: start an Activity. Options are:\n" + " -D: enable debugging\n" + diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index f9ff861..88a025e 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -1360,22 +1360,19 @@ public final class Pm { System.err.println(" pm list instrumentation [-f] [TARGET-PACKAGE]"); System.err.println(" pm list features"); System.err.println(" pm list libraries"); - System.err.println(" pm list users"); System.err.println(" pm path PACKAGE"); System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]"); System.err.println(" [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>] PATH"); System.err.println(" pm uninstall [-k] PACKAGE"); System.err.println(" pm clear PACKAGE"); - System.err.println(" pm enable [--user USER_ID] PACKAGE_OR_COMPONENT"); - System.err.println(" pm disable [--user USER_ID] PACKAGE_OR_COMPONENT"); - System.err.println(" pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT"); + System.err.println(" pm enable PACKAGE_OR_COMPONENT"); + System.err.println(" pm disable PACKAGE_OR_COMPONENT"); + System.err.println(" pm disable-user PACKAGE_OR_COMPONENT"); System.err.println(" pm grant PACKAGE PERMISSION"); System.err.println(" pm revoke PACKAGE PERMISSION"); System.err.println(" pm set-install-location [0/auto] [1/internal] [2/external]"); System.err.println(" pm get-install-location"); System.err.println(" pm set-permission-enforced PERMISSION [true|false]"); - System.err.println(" pm create-user USER_NAME"); - System.err.println(" pm remove-user USER_ID"); System.err.println(""); System.err.println("pm list packages: prints all packages, optionally only"); System.err.println(" those whose package name contains the text in FILTER. Options:"); diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java index ad4b58f..079b9bd 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -163,7 +163,8 @@ public class AccountManagerService new HashMap<Account, Integer>(); private final Object cacheLock = new Object(); /** protected by the {@link #cacheLock} */ - private final HashMap<String, Account[]> accountCache = new HashMap<String, Account[]>(); + private final HashMap<String, Account[]> accountCache = + new LinkedHashMap<String, Account[]>(); /** protected by the {@link #cacheLock} */ private HashMap<Account, HashMap<String, String>> userDataCache = new HashMap<Account, HashMap<String, String>>(); @@ -296,7 +297,7 @@ public class AccountManagerService try { accounts.accountCache.clear(); final HashMap<String, ArrayList<String>> accountNamesByType = - new HashMap<String, ArrayList<String>>(); + new LinkedHashMap<String, ArrayList<String>>(); while (cursor.moveToNext()) { final long accountId = cursor.getLong(0); final String accountType = cursor.getString(1); diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 6058bdc..03ee419 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -1568,8 +1568,17 @@ final class FragmentManagerImpl extends FragmentManager { for (int i=0; i<N; i++) { Fragment f = mActive.get(i); if (f != null) { + if (f.mIndex < 0) { + String msg = "Failure saving state: active " + f + + " has cleared index: " + f.mIndex; + Slog.e(TAG, msg); + dump(" ", null, new PrintWriter(new LogWriter( + Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { }); + throw new IllegalStateException(msg); + } + haveFragments = true; - + FragmentState fs = new FragmentState(f); active[i] = fs; @@ -1621,6 +1630,14 @@ final class FragmentManagerImpl extends FragmentManager { added = new int[N]; for (int i=0; i<N; i++) { added[i] = mAdded.get(i).mIndex; + if (added[i] < 0) { + String msg = "Failure saving state: active " + mAdded.get(i) + + " has cleared index: " + added[i]; + Slog.e(TAG, msg); + dump(" ", null, new PrintWriter(new LogWriter( + Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { }); + throw new IllegalStateException(msg); + } if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i + ": " + mAdded.get(i)); } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 3ced82b..036008b 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -1379,7 +1379,7 @@ public class Notification implements Parcelable } } - private RemoteViews applyStandardTemplate(int resId) { + private RemoteViews applyStandardTemplate(int resId, boolean fitIn1U) { RemoteViews contentView = new RemoteViews(mContext.getPackageName(), resId); boolean showLine3 = false; boolean showLine2 = false; @@ -1432,7 +1432,6 @@ public class Notification implements Parcelable contentView.setTextViewText(R.id.text, mSubText); if (mContentText != null) { contentView.setTextViewText(R.id.text2, mContentText); - // need to shrink all the type to make sure everything fits contentView.setViewVisibility(R.id.text2, View.VISIBLE); showLine2 = true; } else { @@ -1450,10 +1449,13 @@ public class Notification implements Parcelable } } if (showLine2) { - final Resources res = mContext.getResources(); - final float subTextSize = res.getDimensionPixelSize( - R.dimen.notification_subtext_size); - contentView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_PX, subTextSize); + if (fitIn1U) { + // need to shrink all the type to make sure everything fits + final Resources res = mContext.getResources(); + final float subTextSize = res.getDimensionPixelSize( + R.dimen.notification_subtext_size); + contentView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_PX, subTextSize); + } // vertical centering contentView.setViewPadding(R.id.line1, 0, 0, 0, 0); } @@ -1470,16 +1472,18 @@ public class Notification implements Parcelable } } contentView.setViewVisibility(R.id.line3, showLine3 ? View.VISIBLE : View.GONE); + contentView.setViewVisibility(R.id.overflow_divider, showLine3 ? View.VISIBLE : View.GONE); return contentView; } private RemoteViews applyStandardTemplateWithActions(int layoutId) { - RemoteViews big = applyStandardTemplate(layoutId); + RemoteViews big = applyStandardTemplate(layoutId, false); int N = mActions.size(); if (N > 0) { // Log.d("Notification", "has actions: " + mContentText); big.setViewVisibility(R.id.actions, View.VISIBLE); + big.setViewVisibility(R.id.action_divider, View.VISIBLE); if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS; big.removeAllViews(R.id.actions); for (int i=0; i<N; i++) { @@ -1495,7 +1499,7 @@ public class Notification implements Parcelable if (mContentView != null) { return mContentView; } else { - return applyStandardTemplate(R.layout.notification_template_base); // no more special large_icon flavor + return applyStandardTemplate(R.layout.notification_template_base, true); // no more special large_icon flavor } } @@ -1506,7 +1510,7 @@ public class Notification implements Parcelable if (mContentView == null) { return applyStandardTemplate(mLargeIcon == null ? R.layout.status_bar_latest_event_ticker - : R.layout.status_bar_latest_event_ticker_large_icon); + : R.layout.status_bar_latest_event_ticker_large_icon, true); } else { return null; } @@ -1655,12 +1659,9 @@ public class Notification implements Parcelable contentView.setViewVisibility(R.id.line1, View.VISIBLE); } + // The last line defaults to the content text or subtext, but can be replaced by mSummaryText if (mSummaryText != null && !mSummaryText.equals("")) { - contentView.setViewVisibility(R.id.overflow_title, View.VISIBLE); - contentView.setTextViewText(R.id.overflow_title, mSummaryText); - contentView.setViewVisibility(R.id.line3, View.GONE); - } else { - contentView.setViewVisibility(R.id.overflow_title, View.GONE); + contentView.setTextViewText(R.id.text, mSummaryText); contentView.setViewVisibility(R.id.line3, View.VISIBLE); } @@ -1801,6 +1802,8 @@ public class Notification implements Parcelable } private RemoteViews makeBigContentView() { + // Remove the content text so line3 disappears entirely + mBuilder.mContentText = null; RemoteViews contentView = getStandardView(R.layout.notification_template_big_text); contentView.setTextViewText(R.id.big_text, mBigText); contentView.setViewVisibility(R.id.big_text, View.VISIBLE); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index ad52e13..e180df4 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -935,7 +935,17 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifest_installLocation, PARSE_DEFAULT_INSTALL_LOCATION); pkg.applicationInfo.installLocation = pkg.installLocation; - + + /* Set the global "forward lock" flag */ + if ((flags & PARSE_FORWARD_LOCK) != 0) { + pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FORWARD_LOCK; + } + + /* Set the global "on SD card" flag */ + if ((flags & PARSE_ON_SDCARD) != 0) { + pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE; + } + // Resource boolean are -1, so 1 means we don't know the value. int supportsSmallScreens = 1; int supportsNormalScreens = 1; @@ -1726,14 +1736,6 @@ public class PackageParser { } } - if ((flags & PARSE_FORWARD_LOCK) != 0) { - ai.flags |= ApplicationInfo.FLAG_FORWARD_LOCK; - } - - if ((flags & PARSE_ON_SDCARD) != 0) { - ai.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE; - } - if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_debuggable, false)) { diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 035a7c6..4d9077f 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -736,8 +736,8 @@ public class Camera { return; case CAMERA_MSG_PREVIEW_FRAME: - if (mPreviewCallback != null) { - PreviewCallback cb = mPreviewCallback; + PreviewCallback pCb = mPreviewCallback; + if (pCb != null) { if (mOneShot) { // Clear the callback variable before the callback // in case the app calls setPreviewCallback from @@ -749,7 +749,7 @@ public class Camera { // Set to oneshot mode again. setHasPreviewCallback(true, false); } - cb.onPreviewFrame((byte[])msg.obj, mCamera); + pCb.onPreviewFrame((byte[])msg.obj, mCamera); } return; diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 2782dca..e8f87bb 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -24,6 +24,7 @@ import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; +import android.content.ContextWrapper; import android.content.CursorEntityIterator; import android.content.Entity; import android.content.EntityIterator; @@ -7711,9 +7712,19 @@ public final class ContactsContract { */ public static void showQuickContact(Context context, Rect target, Uri lookupUri, int mode, String[] excludeMimes) { + // When launching from an Activiy, we don't want to start a new task, but otherwise + // we *must* start a new task. (Otherwise startActivity() would crash.) + Context actualContext = context; + while ((actualContext instanceof ContextWrapper) + && !(actualContext instanceof Activity)) { + actualContext = ((ContextWrapper) actualContext).getBaseContext(); + } + final int intentFlags = (actualContext instanceof Activity) + ? Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET + : Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK; + // Launch pivot dialog through intent for now - final Intent intent = new Intent(ACTION_QUICK_CONTACT) - .addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); + final Intent intent = new Intent(ACTION_QUICK_CONTACT).addFlags(intentFlags); intent.setData(lookupUri); intent.setSourceBounds(target); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 8b7ee0e..8630204 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2886,6 +2886,15 @@ public final class Settings { "enabled_accessibility_services"; /** + * List of the accessibility services to which the user has graned + * permission to put the device into touch exploration mode. + * + * @hide + */ + public static final String TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES = + "touch_exploration_granted_accessibility_services"; + + /** * Whether to speak passwords while in accessibility mode. */ public static final String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password"; @@ -4292,6 +4301,7 @@ public final class Settings { ACCESSIBILITY_SCRIPT_INJECTION, BACKUP_AUTO_RESTORE, ENABLED_ACCESSIBILITY_SERVICES, + TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, TOUCH_EXPLORATION_ENABLED, ACCESSIBILITY_ENABLED, ACCESSIBILITY_SPEAK_PASSWORD, diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java index 300bc68..08a99d2 100644 --- a/core/java/android/server/BluetoothA2dpService.java +++ b/core/java/android/server/BluetoothA2dpService.java @@ -33,7 +33,11 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; +import android.os.Handler; +import android.os.Message; import android.os.ParcelUuid; +import android.os.PowerManager; +import android.os.PowerManager.WakeLock; import android.provider.Settings; import android.util.Log; @@ -65,6 +69,10 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { private final BluetoothAdapter mAdapter; private int mTargetA2dpState; private BluetoothDevice mPlayingA2dpDevice; + private IntentBroadcastHandler mIntentBroadcastHandler; + private final WakeLock mWakeLock; + + private static final int MSG_CONNECTION_STATE_CHANGED = 0; private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override @@ -131,6 +139,11 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { public BluetoothA2dpService(Context context, BluetoothService bluetoothService) { mContext = context; + PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); + mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "BluetoothA2dpService"); + + mIntentBroadcastHandler = new IntentBroadcastHandler(); + mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); mBluetoothService = bluetoothService; @@ -514,17 +527,15 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { adjustOtherSinkPriorities(device); } - Intent intent = new Intent(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); - intent.putExtra(BluetoothProfile.EXTRA_STATE, state); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcast(intent, BLUETOOTH_PERM); + int delay = mAudioManager.setBluetoothA2dpDeviceConnectionState(device, state); - if (DBG) log("A2DP state : device: " + device + " State:" + prevState + "->" + state); - - mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.A2DP, state, - prevState); + mWakeLock.acquire(); + mIntentBroadcastHandler.sendMessageDelayed(mIntentBroadcastHandler.obtainMessage( + MSG_CONNECTION_STATE_CHANGED, + prevState, + state, + device), + delay); } } @@ -586,6 +597,34 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { } } + /** Handles A2DP connection state change intent broadcasts. */ + private class IntentBroadcastHandler extends Handler { + + private void onConnectionStateChanged(BluetoothDevice device, int prevState, int state) { + Intent intent = new Intent(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); + intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); + intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); + intent.putExtra(BluetoothProfile.EXTRA_STATE, state); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + mContext.sendBroadcast(intent, BLUETOOTH_PERM); + + if (DBG) log("A2DP state : device: " + device + " State:" + prevState + "->" + state); + + mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.A2DP, state, + prevState); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_CONNECTION_STATE_CHANGED: + onConnectionStateChanged((BluetoothDevice) msg.obj, msg.arg1, msg.arg2); + mWakeLock.release(); + break; + } + } + } + @Override protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index 2ea0360..3bb9c01 100755 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -459,6 +459,18 @@ public final class InputDevice implements Parcelable { } /** + * Returns true if the device is a full keyboard. + * + * @return True if the device is a full keyboard. + * + * @hide + */ + public boolean isFullKeyboard() { + return (mSources & SOURCE_KEYBOARD) == SOURCE_KEYBOARD + && mKeyboardType == KEYBOARD_TYPE_ALPHABETIC; + } + + /** * Gets the name of this input device. * @return The input device name. */ diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java index 78984e0..5ffc2c3 100644 --- a/core/java/android/view/VolumePanel.java +++ b/core/java/android/view/VolumePanel.java @@ -437,8 +437,10 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie public void postVolumeChanged(int streamType, int flags) { if (hasMessages(MSG_VOLUME_CHANGED)) return; - if (mStreamControls == null) { - createSliders(); + synchronized (this) { + if (mStreamControls == null) { + createSliders(); + } } removeMessages(MSG_FREE_RESOURCES); obtainMessage(MSG_VOLUME_CHANGED, streamType, flags).sendToTarget(); @@ -450,8 +452,10 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie public void postMuteChanged(int streamType, int flags) { if (hasMessages(MSG_VOLUME_CHANGED)) return; - if (mStreamControls == null) { - createSliders(); + synchronized (this) { + if (mStreamControls == null) { + createSliders(); + } } removeMessages(MSG_FREE_RESOURCES); obtainMessage(MSG_MUTE_CHANGED, streamType, flags).sendToTarget(); @@ -471,10 +475,12 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie if (LOGD) Log.d(TAG, "onVolumeChanged(streamType: " + streamType + ", flags: " + flags + ")"); if ((flags & AudioManager.FLAG_SHOW_UI) != 0) { - if (mActiveStreamType != streamType) { - reorderSliders(streamType); + synchronized (this) { + if (mActiveStreamType != streamType) { + reorderSliders(streamType); + } + onShowVolumeChanged(streamType, flags); } - onShowVolumeChanged(streamType, flags); } if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 && ! mRingIsSilent) { diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 9abe72b..dae9c6a 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -2283,14 +2283,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final ListAdapter adapter = getAdapter(); if ((position == INVALID_POSITION) || (adapter == null)) { - // Cannot perform actions on invalid items. - info.setEnabled(false); return; } if (!isEnabled() || !adapter.isEnabled(position)) { - // Cannot perform actions on invalid items. - info.setEnabled(false); return; } diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 16490e8..c29dd58 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -1416,6 +1416,7 @@ public class Editor { } Layout layout = mTextView.getLayout(); + Layout hintLayout = mTextView.getHintLayout(); final int offset = mTextView.getSelectionStart(); final int line = layout.getLineForOffset(offset); final int top = layout.getLineTop(line); @@ -1429,13 +1430,23 @@ public class Editor { middle = (top + bottom) >> 1; } - updateCursorPosition(0, top, middle, layout.getPrimaryHorizontal(offset)); + updateCursorPosition(0, top, middle, getPrimaryHorizontal(layout, hintLayout, offset)); if (mCursorCount == 2) { updateCursorPosition(1, middle, bottom, layout.getSecondaryHorizontal(offset)); } } + private float getPrimaryHorizontal(Layout layout, Layout hintLayout, int offset) { + if (TextUtils.isEmpty(layout.getText()) && + hintLayout != null && + !TextUtils.isEmpty(hintLayout.getText())) { + return hintLayout.getPrimaryHorizontal(offset); + } else { + return layout.getPrimaryHorizontal(offset); + } + } + /** * @return true if the selection mode was actually started. */ diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 3e2d43a..131b075 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -1312,6 +1312,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** + * @return the Layout that is currently being used to display the hint text. + * This can be null. + */ + final Layout getHintLayout() { + return mHintLayout; + } + + /** * @return the current key listener for this TextView. * This will frequently be null for non-EditText TextViews. * diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java index 234cb71..46478ca 100644 --- a/core/java/com/android/internal/app/ActionBarImpl.java +++ b/core/java/com/android/internal/app/ActionBarImpl.java @@ -673,26 +673,29 @@ public class ActionBarImpl extends ActionBar { if (mCurWindowVisibility == View.VISIBLE && (mShowHideAnimationEnabled || fromSystem)) { - mTopVisibilityView.setAlpha(0); - mTopVisibilityView.setTranslationY(-mTopVisibilityView.getHeight()); + mTopVisibilityView.setTranslationY(0); // because we're about to ask its window loc + float startingY = -mTopVisibilityView.getHeight(); + if (fromSystem) { + int topLeft[] = {0, 0}; + mTopVisibilityView.getLocationInWindow(topLeft); + startingY -= topLeft[1]; + } + mTopVisibilityView.setTranslationY(startingY); AnimatorSet anim = new AnimatorSet(); - AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mTopVisibilityView, "alpha", 1)); - b.with(ObjectAnimator.ofFloat(mTopVisibilityView, "translationY", 0)); + AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mTopVisibilityView, + "translationY", 0)); if (mContentView != null) { b.with(ObjectAnimator.ofFloat(mContentView, "translationY", - -mTopVisibilityView.getHeight(), 0)); + startingY, 0)); } if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) { - mSplitView.setAlpha(0); mSplitView.setTranslationY(mSplitView.getHeight()); mSplitView.setVisibility(View.VISIBLE); - b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 1)); b.with(ObjectAnimator.ofFloat(mSplitView, "translationY", 0)); } anim.setInterpolator(AnimationUtils.loadInterpolator(mContext, - com.android.internal.R.interpolator.decelerate_quad)); - anim.setDuration(mContext.getResources().getInteger( - com.android.internal.R.integer.config_mediumAnimTime)); + com.android.internal.R.interpolator.decelerate_cubic)); + anim.setDuration(250); // If this is being shown from the system, add a small delay. // This is because we will also be animating in the status bar, // and these two elements can't be done in lock-step. So we give @@ -700,9 +703,6 @@ public class ActionBarImpl extends ActionBar { // the action bar animates. (This corresponds to the corresponding // case when hiding, where the status bar has a small delay before // starting.) - if (fromSystem) { - anim.setStartDelay(100); - } anim.addListener(mShowListener); mCurrentShowAnim = anim; anim.start(); @@ -734,23 +734,26 @@ public class ActionBarImpl extends ActionBar { mTopVisibilityView.setAlpha(1); mContainerView.setTransitioning(true); AnimatorSet anim = new AnimatorSet(); - AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mTopVisibilityView, "alpha", 0)); - b.with(ObjectAnimator.ofFloat(mTopVisibilityView, "translationY", - -mTopVisibilityView.getHeight())); + float endingY = -mTopVisibilityView.getHeight(); + if (fromSystem) { + int topLeft[] = {0, 0}; + mTopVisibilityView.getLocationInWindow(topLeft); + endingY -= topLeft[1]; + } + AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mTopVisibilityView, + "translationY", endingY)); if (mContentView != null) { b.with(ObjectAnimator.ofFloat(mContentView, "translationY", - 0, -mTopVisibilityView.getHeight())); + 0, endingY)); } if (mSplitView != null && mSplitView.getVisibility() == View.VISIBLE) { mSplitView.setAlpha(1); - b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 0)); b.with(ObjectAnimator.ofFloat(mSplitView, "translationY", mSplitView.getHeight())); } anim.setInterpolator(AnimationUtils.loadInterpolator(mContext, - com.android.internal.R.interpolator.accelerate_quad)); - anim.setDuration(mContext.getResources().getInteger( - com.android.internal.R.integer.config_mediumAnimTime)); + com.android.internal.R.interpolator.accelerate_cubic)); + anim.setDuration(250); anim.addListener(mHideListener); mCurrentShowAnim = anim; anim.start(); diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java index a22395b..b2c3091 100644 --- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java +++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java @@ -419,6 +419,7 @@ public class MultiWaveView extends View { "y", 0, "onUpdate", mUpdateListener, "onComplete", finishListener)); + mHandleAnimations.start(); } /** @@ -528,7 +529,6 @@ public class MultiWaveView extends View { deactivateHandle(HIDE_ANIMATION_DURATION, HIDE_ANIMATION_DELAY, 1.0f, mResetListenerWithPing); hideTargets(true, false); - mHandleAnimations.start(); } setGrabbedState(OnTriggerListener.NO_HANDLE); diff --git a/core/jni/android_database_SQLiteConnection.cpp b/core/jni/android_database_SQLiteConnection.cpp index 0777ea2..3bbb8bf 100644 --- a/core/jni/android_database_SQLiteConnection.cpp +++ b/core/jni/android_database_SQLiteConnection.cpp @@ -41,6 +41,20 @@ namespace android { +/* Busy timeout in milliseconds. + * If another connection (possibly in another process) has the database locked for + * longer than this amount of time then SQLite will generate a SQLITE_BUSY error. + * The SQLITE_BUSY error is then raised as a SQLiteDatabaseLockedException. + * + * In ordinary usage, busy timeouts are quite rare. Most databases only ever + * have a single open connection at a time unless they are using WAL. When using + * WAL, a timeout could occur if one connection is busy performing an auto-checkpoint + * operation. The busy timeout needs to be long enough to tolerate slow I/O write + * operations but not so long as to cause the application to hang indefinitely if + * there is a problem acquiring a database lock. + */ +static const int BUSY_TIMEOUT_MS = 2500; + static struct { jfieldID name; jfieldID numArgs; @@ -127,8 +141,8 @@ static jint nativeOpen(JNIEnv* env, jclass clazz, jstring pathStr, jint openFlag return 0; } - // Set the default busy handler to retry for 1000ms and then return SQLITE_BUSY - err = sqlite3_busy_timeout(db, 1000 /* ms */); + // Set the default busy handler to retry automatically before returning SQLITE_BUSY. + err = sqlite3_busy_timeout(db, BUSY_TIMEOUT_MS); if (err != SQLITE_OK) { throw_sqlite3_exception(env, db, "Could not set busy timeout"); sqlite3_close(db); diff --git a/core/res/res/anim/dock_bottom_enter.xml b/core/res/res/anim/dock_bottom_enter.xml index 74a021b..4f2f753 100644 --- a/core/res/res/anim/dock_bottom_enter.xml +++ b/core/res/res/anim/dock_bottom_enter.xml @@ -18,7 +18,7 @@ <!-- Animation for when a dock window at the bottom of the screen is entering. --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:interpolator="@android:interpolator/decelerate_quad"> + android:interpolator="@android:interpolator/decelerate_cubic"> <translate android:fromYDelta="100%" android:toYDelta="0" - android:duration="@android:integer/config_mediumAnimTime"/> + android:duration="250"/> </set> diff --git a/core/res/res/anim/dock_bottom_exit.xml b/core/res/res/anim/dock_bottom_exit.xml index 213b3d9..afbe24b 100644 --- a/core/res/res/anim/dock_bottom_exit.xml +++ b/core/res/res/anim/dock_bottom_exit.xml @@ -18,7 +18,7 @@ <!-- Animation for when a dock window at the bottom of the screen is exiting. --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:interpolator="@android:interpolator/accelerate_quad"> + android:interpolator="@android:interpolator/accelerate_cubic"> <translate android:fromYDelta="0" android:toYDelta="100%" - android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/> + android:startOffset="100" android:duration="250"/> </set> diff --git a/core/res/res/anim/dock_left_enter.xml b/core/res/res/anim/dock_left_enter.xml index 4fce35a..7f5dfd5 100644 --- a/core/res/res/anim/dock_left_enter.xml +++ b/core/res/res/anim/dock_left_enter.xml @@ -18,7 +18,7 @@ <!-- Animation for when a dock window at the left of the screen is entering. --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:interpolator="@android:interpolator/decelerate_quad"> + android:interpolator="@android:interpolator/decelerate_cubic"> <translate android:fromXDelta="-100%" android:toXDelta="0" - android:duration="@android:integer/config_mediumAnimTime"/> + android:duration="250"/> </set> diff --git a/core/res/res/anim/dock_left_exit.xml b/core/res/res/anim/dock_left_exit.xml index bce203d..11cbc0b 100644 --- a/core/res/res/anim/dock_left_exit.xml +++ b/core/res/res/anim/dock_left_exit.xml @@ -18,7 +18,7 @@ <!-- Animation for when a dock window at the right of the screen is exiting. --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:interpolator="@android:interpolator/accelerate_quad"> + android:interpolator="@android:interpolator/accelerate_cubic"> <translate android:fromXDelta="0" android:toXDelta="-100%" - android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/> + android:startOffset="100" android:duration="250"/> </set> diff --git a/core/res/res/anim/dock_right_enter.xml b/core/res/res/anim/dock_right_enter.xml index 26b8ad6..a92c7d2 100644 --- a/core/res/res/anim/dock_right_enter.xml +++ b/core/res/res/anim/dock_right_enter.xml @@ -18,7 +18,7 @@ <!-- Animation for when a dock window at the right of the screen is entering. --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:interpolator="@android:interpolator/decelerate_quad"> + android:interpolator="@android:interpolator/decelerate_cubic"> <translate android:fromXDelta="100%" android:toXDelta="0" - android:duration="@android:integer/config_mediumAnimTime"/> + android:duration="250"/> </set> diff --git a/core/res/res/anim/dock_right_exit.xml b/core/res/res/anim/dock_right_exit.xml index 6beda59..80e4dc3 100644 --- a/core/res/res/anim/dock_right_exit.xml +++ b/core/res/res/anim/dock_right_exit.xml @@ -18,7 +18,7 @@ <!-- Animation for when a dock window at the right of the screen is exiting. --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:interpolator="@android:interpolator/accelerate_quad"> + android:interpolator="@android:interpolator/accelerate_cubic"> <translate android:fromXDelta="0" android:toXDelta="100%" - android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/> + android:startOffset="100" android:duration="250"/> </set> diff --git a/core/res/res/anim/dock_top_enter.xml b/core/res/res/anim/dock_top_enter.xml index 594b479..1f74e48 100644 --- a/core/res/res/anim/dock_top_enter.xml +++ b/core/res/res/anim/dock_top_enter.xml @@ -18,7 +18,7 @@ <!-- Animation for when a dock window at the top of the screen is entering. --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:interpolator="@android:interpolator/decelerate_quad"> + android:interpolator="@android:interpolator/decelerate_cubic"> <translate android:fromYDelta="-100%" android:toYDelta="0" - android:duration="@android:integer/config_mediumAnimTime"/> + android:duration="250"/> </set> diff --git a/core/res/res/anim/dock_top_exit.xml b/core/res/res/anim/dock_top_exit.xml index b9691f6..4d2fea9 100644 --- a/core/res/res/anim/dock_top_exit.xml +++ b/core/res/res/anim/dock_top_exit.xml @@ -18,7 +18,7 @@ <!-- Animation for when a dock window at the top of the screen is exiting. --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:interpolator="@android:interpolator/accelerate_quad"> + android:interpolator="@android:interpolator/accelerate_cubic"> <translate android:fromYDelta="0" android:toYDelta="-100%" - android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/> + android:startOffset="100" android:duration="250"/> </set> diff --git a/core/res/res/layout/notification_action_list.xml b/core/res/res/layout/notification_action_list.xml index fa0a8c8..591c9ea 100644 --- a/core/res/res/layout/notification_action_list.xml +++ b/core/res/res/layout/notification_action_list.xml @@ -23,6 +23,7 @@ android:visibility="gone" android:showDividers="middle" android:divider="?android:attr/listDivider" + android:dividerPadding="12dp" > <!-- actions will be added here --> </LinearLayout> diff --git a/core/res/res/layout/notification_template_base.xml b/core/res/res/layout/notification_template_base.xml index ed680a9..47bbbde 100644 --- a/core/res/res/layout/notification_template_base.xml +++ b/core/res/res/layout/notification_template_base.xml @@ -36,8 +36,7 @@ android:layout_marginLeft="@dimen/notification_large_icon_width" android:minHeight="@dimen/notification_large_icon_height" android:orientation="vertical" - android:paddingLeft="12dp" - android:paddingRight="12dp" + android:paddingRight="8dp" android:paddingTop="2dp" android:paddingBottom="2dp" android:gravity="top" @@ -47,6 +46,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="6dp" + android:layout_marginLeft="8dp" android:orientation="horizontal" > <TextView android:id="@+id/title" @@ -81,6 +81,7 @@ android:layout_height="wrap_content" android:layout_marginTop="-2dp" android:layout_marginBottom="-2dp" + android:layout_marginLeft="8dp" android:singleLine="true" android:fadingEdge="horizontal" android:ellipsize="marquee" @@ -90,24 +91,17 @@ android:id="@android:id/progress" android:layout_width="match_parent" android:layout_height="12dp" + android:layout_marginLeft="8dp" android:visibility="gone" style="?android:attr/progressBarStyleHorizontal" /> - <TextView android:id="@+id/overflow_title" - android:textAppearance="@style/TextAppearance.StatusBar.EventContent" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:singleLine="true" - android:ellipsize="marquee" - android:fadingEdge="horizontal" - android:visibility="gone" - android:layout_weight="1" - /> <LinearLayout android:id="@+id/line3" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" + android:gravity="center_vertical" + android:layout_marginLeft="8dp" > <TextView android:id="@+id/text" android:textAppearance="@style/TextAppearance.StatusBar.EventContent" @@ -130,14 +124,14 @@ android:paddingLeft="8dp" /> <ImageView android:id="@+id/right_icon" - android:layout_width="wrap_content" - android:layout_height="match_parent" + android:layout_width="16dp" + android:layout_height="16dp" android:layout_gravity="center" android:layout_weight="0" + android:layout_marginLeft="8dp" android:scaleType="centerInside" - android:paddingLeft="8dp" android:visibility="gone" - android:drawableAlpha="180" + android:drawableAlpha="153" /> </LinearLayout> </LinearLayout> diff --git a/core/res/res/layout/notification_template_big_base.xml b/core/res/res/layout/notification_template_big_base.xml index f2c204f..69f0a24 100644 --- a/core/res/res/layout/notification_template_big_base.xml +++ b/core/res/res/layout/notification_template_big_base.xml @@ -33,19 +33,16 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="fill_vertical" - android:layout_marginLeft="@dimen/notification_large_icon_width" android:minHeight="@dimen/notification_large_icon_height" android:orientation="vertical" - android:paddingLeft="12dp" - android:paddingRight="12dp" - android:paddingTop="2dp" - android:paddingBottom="2dp" android:gravity="top" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginLeft="@dimen/notification_large_icon_width" android:minHeight="@dimen/notification_large_icon_height" + android:paddingTop="2dp" android:orientation="vertical" > <LinearLayout @@ -53,6 +50,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="6dp" + android:layout_marginRight="8dp" + android:layout_marginLeft="8dp" android:orientation="horizontal" > <TextView android:id="@+id/title" @@ -87,6 +86,8 @@ android:layout_height="wrap_content" android:layout_marginTop="-2dp" android:layout_marginBottom="-2dp" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" android:singleLine="true" android:fadingEdge="horizontal" android:ellipsize="marquee" @@ -96,6 +97,8 @@ android:textAppearance="@style/TextAppearance.StatusBar.EventContent" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" android:singleLine="false" android:visibility="gone" /> @@ -103,7 +106,10 @@ android:id="@+id/line3" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" android:orientation="horizontal" + android:gravity="center_vertical" > <TextView android:id="@+id/text" android:textAppearance="@style/TextAppearance.StatusBar.EventContent" @@ -126,29 +132,38 @@ android:paddingLeft="8dp" /> <ImageView android:id="@+id/right_icon" - android:layout_width="wrap_content" - android:layout_height="match_parent" + android:layout_width="16dp" + android:layout_height="16dp" android:layout_gravity="center" android:layout_weight="0" + android:layout_marginLeft="8dp" android:scaleType="centerInside" - android:paddingLeft="8dp" android:visibility="gone" - android:drawableAlpha="180" + android:drawableAlpha="153" /> </LinearLayout> <ProgressBar android:id="@android:id/progress" android:layout_width="match_parent" android:layout_height="12dp" + android:layout_marginBottom="8dp" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" android:visibility="gone" style="?android:attr/progressBarStyleHorizontal" /> </LinearLayout> + <ImageView + android:layout_width="match_parent" + android:layout_height="1px" + android:id="@+id/action_divider" + android:visibility="gone" + android:background="?android:attr/dividerHorizontal" /> <include layout="@layout/notification_action_list" - android:id="@+id/actions" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginLeft="@dimen/notification_large_icon_width" /> </LinearLayout> </FrameLayout> diff --git a/core/res/res/layout/notification_template_big_picture.xml b/core/res/res/layout/notification_template_big_picture.xml index 077616e..ecb3616 100644 --- a/core/res/res/layout/notification_template_big_picture.xml +++ b/core/res/res/layout/notification_template_big_picture.xml @@ -53,7 +53,6 @@ <include layout="@layout/notification_action_list" android:id="@+id/actions" - android:layout_marginLeft="8dp" android:layout_gravity="bottom" android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/core/res/res/layout/notification_template_big_text.xml b/core/res/res/layout/notification_template_big_text.xml index 304f2b5..b86177e 100644 --- a/core/res/res/layout/notification_template_big_text.xml +++ b/core/res/res/layout/notification_template_big_text.xml @@ -34,8 +34,6 @@ android:layout_gravity="fill_vertical" android:layout_marginLeft="@dimen/notification_large_icon_width" android:orientation="vertical" - android:paddingLeft="12dp" - android:paddingRight="12dp" android:paddingTop="2dp" android:paddingBottom="2dp" android:gravity="top" @@ -44,6 +42,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" android:layout_weight="1" > <LinearLayout @@ -87,6 +87,7 @@ android:layout_height="wrap_content" android:layout_marginTop="-2dp" android:layout_marginBottom="-2dp" + android:layout_marginRight="8dp" android:singleLine="true" android:fadingEdge="horizontal" android:ellipsize="marquee" @@ -97,6 +98,8 @@ android:id="@android:id/progress" android:layout_width="match_parent" android:layout_height="12dp" + android:layout_marginBottom="8dp" + android:layout_marginRight="8dp" android:visibility="gone" android:layout_weight="0" style="?android:attr/progressBarStyleHorizontal" @@ -105,7 +108,8 @@ android:textAppearance="@style/TextAppearance.StatusBar.EventContent" android:layout_width="match_parent" android:layout_height="0dp" - android:layout_marginBottom="2dp" + android:layout_marginBottom="8dp" + android:layout_marginRight="8dp" android:singleLine="false" android:visibility="gone" android:maxLines="8" @@ -113,6 +117,13 @@ android:layout_weight="1" /> </LinearLayout> + <ImageView + android:layout_width="match_parent" + android:layout_height="1dip" + android:layout_marginTop="-1px" + android:id="@+id/action_divider" + android:visibility="gone" + android:background="?android:attr/dividerHorizontal" /> <include layout="@layout/notification_action_list" android:layout_width="match_parent" @@ -120,22 +131,23 @@ android:visibility="gone" android:layout_weight="1" /> - <TextView android:id="@+id/overflow_title" - android:textAppearance="@style/TextAppearance.StatusBar.EventContent" + <ImageView android:layout_width="match_parent" - android:layout_height="wrap_content" - android:singleLine="true" - android:ellipsize="marquee" - android:fadingEdge="horizontal" - android:visibility="gone" - android:layout_weight="0" - /> + android:layout_height="1px" + android:id="@+id/overflow_divider" + android:layout_marginBottom="8dp" + android:visibility="visible" + android:background="?android:attr/dividerHorizontal" /> <LinearLayout android:id="@+id/line3" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginLeft="8dp" + android:layout_marginBottom="8dp" + android:layout_marginRight="8dp" android:orientation="horizontal" android:layout_weight="0" + android:gravity="center_vertical" > <TextView android:id="@+id/text" android:textAppearance="@style/TextAppearance.StatusBar.EventContent" @@ -158,14 +170,14 @@ android:paddingLeft="8dp" /> <ImageView android:id="@+id/right_icon" - android:layout_width="wrap_content" - android:layout_height="match_parent" + android:layout_width="16dp" + android:layout_height="16dp" android:layout_gravity="center" android:layout_weight="0" + android:layout_marginLeft="8dp" android:scaleType="centerInside" - android:paddingLeft="8dp" android:visibility="gone" - android:drawableAlpha="180" + android:drawableAlpha="153" /> </LinearLayout> </LinearLayout> diff --git a/core/res/res/layout/notification_template_inbox.xml b/core/res/res/layout/notification_template_inbox.xml index 121a81c..e9a3686 100644 --- a/core/res/res/layout/notification_template_inbox.xml +++ b/core/res/res/layout/notification_template_inbox.xml @@ -36,8 +36,6 @@ android:layout_marginLeft="@dimen/notification_large_icon_width" android:minHeight="@dimen/notification_large_icon_height" android:orientation="vertical" - android:paddingLeft="12dp" - android:paddingRight="12dp" android:paddingTop="2dp" android:paddingBottom="2dp" android:gravity="top" @@ -46,6 +44,8 @@ android:id="@+id/line1" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" android:paddingTop="6dp" android:orientation="horizontal" android:layout_weight="0" @@ -82,6 +82,8 @@ android:layout_height="wrap_content" android:layout_marginTop="-2dp" android:layout_marginBottom="-2dp" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" android:singleLine="true" android:fadingEdge="horizontal" android:ellipsize="marquee" @@ -92,6 +94,8 @@ android:id="@android:id/progress" android:layout_width="match_parent" android:layout_height="12dp" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" android:visibility="gone" android:layout_weight="0" style="?android:attr/progressBarStyleHorizontal" @@ -100,6 +104,8 @@ android:textAppearance="@style/TextAppearance.StatusBar.EventContent" android:layout_width="match_parent" android:layout_height="0dp" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" android:singleLine="true" android:ellipsize="end" android:visibility="gone" @@ -109,6 +115,8 @@ android:textAppearance="@style/TextAppearance.StatusBar.EventContent" android:layout_width="match_parent" android:layout_height="0dp" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" android:singleLine="true" android:ellipsize="end" android:visibility="gone" @@ -118,6 +126,8 @@ android:textAppearance="@style/TextAppearance.StatusBar.EventContent" android:layout_width="match_parent" android:layout_height="0dp" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" android:singleLine="true" android:ellipsize="end" android:visibility="gone" @@ -127,6 +137,8 @@ android:textAppearance="@style/TextAppearance.StatusBar.EventContent" android:layout_width="match_parent" android:layout_height="0dp" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" android:singleLine="true" android:ellipsize="end" android:visibility="gone" @@ -136,6 +148,7 @@ android:textAppearance="@style/TextAppearance.StatusBar.EventContent" android:layout_width="match_parent" android:layout_height="0dp" + android:layout_marginLeft="8dp" android:singleLine="true" android:ellipsize="end" android:visibility="gone" @@ -145,6 +158,8 @@ android:textAppearance="@style/TextAppearance.StatusBar.EventContent" android:layout_width="match_parent" android:layout_height="0dp" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" android:singleLine="true" android:ellipsize="end" android:visibility="gone" @@ -154,6 +169,8 @@ android:textAppearance="@style/TextAppearance.StatusBar.EventContent" android:layout_width="match_parent" android:layout_height="0dp" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" android:singleLine="true" android:ellipsize="end" android:visibility="gone" @@ -163,35 +180,44 @@ android:textAppearance="@style/TextAppearance.StatusBar.EventContent" android:layout_width="match_parent" android:layout_height="0dp" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" android:singleLine="true" android:ellipsize="end" android:visibility="gone" android:layout_weight="1" android:text="@android:string/ellipsis" /> + <ImageView + android:layout_width="match_parent" + android:layout_height="1px" + android:id="@+id/overflow_divider" + android:layout_marginTop="8dp" + android:visibility="visible" + android:background="?android:attr/dividerHorizontal" /> <include layout="@layout/notification_action_list" - android:id="@+id/actions" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0" /> - <TextView android:id="@+id/overflow_title" - android:textAppearance="@style/TextAppearance.StatusBar.EventContent" + <ImageView android:layout_width="match_parent" - android:layout_height="wrap_content" - android:singleLine="true" - android:ellipsize="marquee" - android:fadingEdge="horizontal" + android:layout_height="1px" + android:id="@+id/action_divider" android:visibility="gone" - android:layout_weight="0" - /> + android:background="?android:attr/dividerHorizontal" /><!-- note: divider below actions --> <LinearLayout android:id="@+id/line3" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:layout_marginLeft="8dp" + android:layout_marginBottom="8dp" + android:layout_marginRight="8dp" android:orientation="horizontal" android:layout_weight="0" + android:gravity="center_vertical" > <TextView android:id="@+id/text" android:textAppearance="@style/TextAppearance.StatusBar.EventContent" @@ -214,14 +240,14 @@ android:paddingLeft="8dp" /> <ImageView android:id="@+id/right_icon" - android:layout_width="wrap_content" - android:layout_height="match_parent" + android:layout_width="16dp" + android:layout_height="16dp" android:layout_gravity="center" android:layout_weight="0" + android:layout_marginLeft="8dp" android:scaleType="centerInside" - android:paddingLeft="8dp" android:visibility="gone" - android:drawableAlpha="180" + android:drawableAlpha="153" /> </LinearLayout> </LinearLayout> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index a70394f..bf9fe42 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -120,7 +120,6 @@ <java-symbol type="id" name="old_app_action" /> <java-symbol type="id" name="old_app_description" /> <java-symbol type="id" name="old_app_icon" /> - <java-symbol type="id" name="overflow_title" /> <java-symbol type="id" name="package_label" /> <java-symbol type="id" name="packages_list" /> <java-symbol type="id" name="pause" /> @@ -210,6 +209,8 @@ <java-symbol type="id" name="inbox_text6" /> <java-symbol type="id" name="inbox_more" /> <java-symbol type="id" name="status_bar_latest_event_content" /> + <java-symbol type="id" name="action_divider" /> + <java-symbol type="id" name="overflow_divider" /> <java-symbol type="attr" name="actionModeShareDrawable" /> <java-symbol type="attr" name="alertDialogCenterButtons" /> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index a54cdf1..223d17a 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -239,7 +239,7 @@ please see styles_device_defaults.xml. </style> <!-- Notification content styles --> <style name="TextAppearance.StatusBar.EventContent"> - <item name="android:textColor">#808080</item> + <item name="android:textColor">#999999</item> <item name="android:textSize">@dimen/notification_text_size</item> </style> <style name="TextAppearance.StatusBar.EventContent.Title"> @@ -253,11 +253,14 @@ please see styles_device_defaults.xml. </style> <style name="TextAppearance.StatusBar.EventContent.Info"> <item name="android:textSize">@dimen/notification_subtext_size</item> - <item name="android:textColor">#666666</item> + <item name="android:textColor">#999999</item> </style> <style name="TextAppearance.StatusBar.EventContent.Time"> <item name="android:textSize">@dimen/notification_subtext_size</item> - <item name="android:textColor">#666666</item> + <item name="android:textColor">#999999</item> + </style> + <style name="TextAppearance.StatusBar.EventContent.Emphasis"> + <item name="android:textColor">#CCCCCC</item> </style> <style name="TextAppearance.Small.CalendarViewWeekDayView"> diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 6c7c160..6b9522b 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -19,6 +19,7 @@ package android.media; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.PendingIntent; +import android.bluetooth.BluetoothDevice; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -2376,6 +2377,42 @@ public class AudioManager { } } + /** + * Indicate wired accessory connection state change. + * @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx) + * @param state new connection state: 1 connected, 0 disconnected + * @param name device name + * {@hide} + */ + public void setWiredDeviceConnectionState(int device, int state, String name) { + IAudioService service = getService(); + try { + service.setWiredDeviceConnectionState(device, state, name); + } catch (RemoteException e) { + Log.e(TAG, "Dead object in setWiredDeviceConnectionState "+e); + } + } + + /** + * Indicate A2DP sink connection state change. + * @param device Bluetooth device connected/disconnected + * @param state new connection state (BluetoothProfile.STATE_xxx) + * @return a delay in ms that the caller should wait before broadcasting + * BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent. + * {@hide} + */ + public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state) { + IAudioService service = getService(); + int delay = 0; + try { + delay = service.setBluetoothA2dpDeviceConnectionState(device, state); + } catch (RemoteException e) { + Log.e(TAG, "Dead object in setBluetoothA2dpDeviceConnectionState "+e); + } finally { + return delay; + } + } + /** {@hide} */ public IRingtonePlayer getRingtonePlayer() { try { diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 5e338ab..84856bf 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -135,6 +135,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished { private static final int MSG_RCDISPLAY_UPDATE = 13; private static final int MSG_SET_ALL_VOLUMES = 14; private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 15; + private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 16; + private static final int MSG_SET_A2DP_CONNECTION_STATE = 17; // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be @@ -442,15 +444,9 @@ public class AudioService extends IAudioService.Stub implements OnFinished { // Register for device connection intent broadcasts. IntentFilter intentFilter = - new IntentFilter(Intent.ACTION_HEADSET_PLUG); - - intentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); - intentFilter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); + new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); intentFilter.addAction(Intent.ACTION_DOCK_EVENT); - intentFilter.addAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG); - intentFilter.addAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG); - intentFilter.addAction(Intent.ACTION_HDMI_AUDIO_PLUG); intentFilter.addAction(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG); intentFilter.addAction(Intent.ACTION_USB_AUDIO_DEVICE_PLUG); intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED); @@ -1961,7 +1957,19 @@ public class AudioService extends IAudioService.Stub implements OnFinished { deviceList = a2dp.getConnectedDevices(); if (deviceList.size() > 0) { btDevice = deviceList.get(0); - handleA2dpConnectionStateChange(btDevice, a2dp.getConnectionState(btDevice)); + synchronized (mConnectedDevices) { + int state = a2dp.getConnectionState(btDevice); + int delay = checkSendBecomingNoisyIntent( + AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, + (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); + sendMsg(mAudioHandler, + MSG_SET_A2DP_CONNECTION_STATE, + SENDMSG_QUEUE, + state, + 0, + btDevice, + delay); + } } break; @@ -2262,6 +2270,36 @@ public class AudioService extends IAudioService.Stub implements OnFinished { return device; } + public void setWiredDeviceConnectionState(int device, int state, String name) { + synchronized (mConnectedDevices) { + int delay = checkSendBecomingNoisyIntent(device, state); + sendMsg(mAudioHandler, + MSG_SET_WIRED_DEVICE_CONNECTION_STATE, + SENDMSG_QUEUE, + device, + state, + name, + delay); + } + } + + public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state) + { + int delay; + synchronized (mConnectedDevices) { + delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, + (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); + sendMsg(mAudioHandler, + MSG_SET_A2DP_CONNECTION_STATE, + SENDMSG_QUEUE, + state, + 0, + device, + delay); + } + return delay; + } + /////////////////////////////////////////////////////////////////////////// // Inner classes /////////////////////////////////////////////////////////////////////////// @@ -2959,6 +2997,14 @@ public class AudioService extends IAudioService.Stub implements OnFinished { case MSG_BT_HEADSET_CNCT_FAILED: resetBluetoothSco(); break; + + case MSG_SET_WIRED_DEVICE_CONNECTION_STATE: + onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj); + break; + + case MSG_SET_A2DP_CONNECTION_STATE: + onSetA2dpConnectionState((BluetoothDevice)msg.obj, msg.arg1); + break; } } } @@ -3020,7 +3066,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished { // must be called synchronized on mConnectedDevices private void makeA2dpDeviceUnavailableNow(String address) { - sendBecomingNoisyIntent(); AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, AudioSystem.DEVICE_STATE_UNAVAILABLE, address); @@ -3050,7 +3095,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished { return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT); } - private void handleA2dpConnectionStateChange(BluetoothDevice btDevice, int state) + private void onSetA2dpConnectionState(BluetoothDevice btDevice, int state) { if (btDevice == null) { return; @@ -3116,6 +3161,76 @@ public class AudioService extends IAudioService.Stub implements OnFinished { return false; } + // Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only + // sent if none of these devices is connected. + int mBecomingNoisyIntentDevices = + AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE | + AudioSystem.DEVICE_OUT_ALL_A2DP; + + // must be called before removing the device from mConnectedDevices + private int checkSendBecomingNoisyIntent(int device, int state) { + int delay = 0; + if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) { + int devices = 0; + for (int dev : mConnectedDevices.keySet()) { + if ((dev & mBecomingNoisyIntentDevices) != 0) { + devices |= dev; + } + } + if (devices == device) { + delay = 1000; + sendBecomingNoisyIntent(); + } + } + + if (mAudioHandler.hasMessages(MSG_SET_A2DP_CONNECTION_STATE) || + mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) { + delay = 1000; + } + return delay; + } + + private void sendDeviceConnectionIntent(int device, int state, String name) + { + Intent intent = new Intent(); + + intent.putExtra("state", state); + intent.putExtra("name", name); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + + if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) { + intent.setAction(Intent.ACTION_HEADSET_PLUG); + intent.putExtra("microphone", 1); + } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) { + intent.setAction(Intent.ACTION_HEADSET_PLUG); + intent.putExtra("microphone", 0); + } else if (device == AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET) { + intent.setAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG); + } else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) { + intent.setAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG); + } else if (device == AudioSystem.DEVICE_OUT_AUX_DIGITAL) { + intent.setAction(Intent.ACTION_HDMI_AUDIO_PLUG); + } + + ActivityManagerNative.broadcastStickyIntent(intent, null); + } + + private void onSetWiredDeviceConnectionState(int device, int state, String name) + { + synchronized (mConnectedDevices) { + if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || + (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) { + setBluetoothA2dpOnInt(true); + } + handleDeviceConnection((state == 1), device, ""); + if ((state != 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || + (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) { + setBluetoothA2dpOnInt(false); + } + sendDeviceConnectionIntent(device, state, name); + } + } + /* cache of the address of the last dock the device was connected to */ private String mDockAddress; @@ -3151,12 +3266,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished { config = AudioSystem.FORCE_NONE; } AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config); - } else if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) { - state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, - BluetoothProfile.STATE_DISCONNECTED); - BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - - handleA2dpConnectionStateChange(btDevice, state); } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) { state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED); @@ -3197,43 +3306,9 @@ public class AudioService extends IAudioService.Stub implements OnFinished { } } } - } else if (action.equals(Intent.ACTION_HEADSET_PLUG)) { - state = intent.getIntExtra("state", 0); - int microphone = intent.getIntExtra("microphone", 0); - - if (microphone != 0) { - device = AudioSystem.DEVICE_OUT_WIRED_HEADSET; - } else { - device = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE; - } - // enable A2DP before notifying headset disconnection to avoid glitches - if (state == 0) { - setBluetoothA2dpOnInt(true); - } - handleDeviceConnection((state == 1), device, ""); - // disable A2DP after notifying headset connection to avoid glitches - if (state != 0) { - setBluetoothA2dpOnInt(false); - } - } else if (action.equals(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG)) { - state = intent.getIntExtra("state", 0); - Log.v(TAG, "Broadcast Receiver: Got ACTION_ANALOG_AUDIO_DOCK_PLUG, state = "+state); - handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET, ""); - } else if (action.equals(Intent.ACTION_HDMI_AUDIO_PLUG)) { - state = intent.getIntExtra("state", 0); - Log.v(TAG, "Broadcast Receiver: Got ACTION_HDMI_AUDIO_PLUG, state = "+state); - handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_AUX_DIGITAL, ""); - } else if (action.equals(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG)) { - state = intent.getIntExtra("state", 0); - Log.v(TAG, - "Broadcast Receiver Got ACTION_DIGITAL_AUDIO_DOCK_PLUG, state = " + state); - handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET, ""); } else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) || action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) { state = intent.getIntExtra("state", 0); - if (state == 0) { - sendBecomingNoisyIntent(); - } int alsaCard = intent.getIntExtra("card", -1); int alsaDevice = intent.getIntExtra("device", -1); String params = (alsaCard == -1 && alsaDevice == -1 ? "" diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 7fbe28c..133f30b 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -17,6 +17,7 @@ package android.media; import android.app.PendingIntent; +import android.bluetooth.BluetoothDevice; import android.content.ComponentName; import android.media.IAudioFocusDispatcher; import android.media.IRemoteControlClient; @@ -133,4 +134,7 @@ interface IAudioService { void setRingtonePlayer(IRingtonePlayer player); IRingtonePlayer getRingtonePlayer(); int getMasterStreamType(); + + void setWiredDeviceConnectionState(int device, int state, String name); + int setBluetoothA2dpDeviceConnectionState(in BluetoothDevice device, int state); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java index 62462bd..6995c60 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java @@ -415,59 +415,61 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me output.write("Total number of loops: " + NUMBER_OF_TIME_LAPSE_LOOPS + "\n"); try { - output.write("No of loop: "); - for (int i = 0; i < NUMBER_OF_TIME_LAPSE_LOOPS; i++) { - filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT; - Log.v(TAG, filename); - runOnLooper(new Runnable() { - @Override - public void run() { - mRecorder = new MediaRecorder(); + for (int j = 0, n = Camera.getNumberOfCameras(); j < n; j++) { + output.write("No of loop: camera " + j); + for (int i = 0; i < NUMBER_OF_TIME_LAPSE_LOOPS; i++) { + filename = OUTPUT_FILE + j + "_" + i + OUTPUT_FILE_EXT; + Log.v(TAG, filename); + runOnLooper(new Runnable() { + @Override + public void run() { + mRecorder = new MediaRecorder(); + } + }); + + // Set callback + mRecorder.setOnErrorListener(mRecorderErrorCallback); + + // Set video source + mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); + + // Set camcorder profile for time lapse + CamcorderProfile profile = + CamcorderProfile.get(j, CamcorderProfile.QUALITY_TIME_LAPSE_HIGH); + mRecorder.setProfile(profile); + + // Set the timelapse setting; 0.1 = 10 sec timelapse, 0.5 = 2 sec timelapse, etc. + // http://developer.android.com/guide/topics/media/camera.html#time-lapse-video + mRecorder.setCaptureRate(captureRate); + + // Set output file + mRecorder.setOutputFile(filename); + + // Set the preview display + Log.v(TAG, "mediaRecorder setPreviewDisplay"); + mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); + + mRecorder.prepare(); + mRecorder.start(); + Thread.sleep(record_duration); + Log.v(TAG, "Before stop"); + mRecorder.stop(); + mRecorder.release(); + + // Start the playback + MediaPlayer mp = new MediaPlayer(); + mp.setDataSource(filename); + mp.setDisplay(mSurfaceHolder); + mp.prepare(); + mp.start(); + Thread.sleep(TIME_LAPSE_PLAYBACK_WAIT_TIME); + mp.release(); + validateRecordedVideo(filename); + if (remove_video) { + removeRecordedVideo(filename); } - }); - - // Set callback - mRecorder.setOnErrorListener(mRecorderErrorCallback); - - // Set video source - mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); - - // Set camcorder profile for time lapse - CamcorderProfile profile = - CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH); - mRecorder.setProfile(profile); - - // Set the timelapse setting; 0.1 = 10 sec timelapse, 0.5 = 2 sec timelapse, etc. - // http://developer.android.com/guide/topics/media/camera.html#time-lapse-video - mRecorder.setCaptureRate(captureRate); - - // Set output file - mRecorder.setOutputFile(filename); - - // Set the preview display - Log.v(TAG, "mediaRecorder setPreviewDisplay"); - mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); - - mRecorder.prepare(); - mRecorder.start(); - Thread.sleep(record_duration); - Log.v(TAG, "Before stop"); - mRecorder.stop(); - mRecorder.release(); - - // Start the playback - MediaPlayer mp = new MediaPlayer(); - mp.setDataSource(filename); - mp.setDisplay(mSurfaceHolder); - mp.prepare(); - mp.start(); - Thread.sleep(TIME_LAPSE_PLAYBACK_WAIT_TIME); - mp.release(); - validateRecordedVideo(filename); - if(remove_video) { - removeRecordedVideo(filename); + output.write(", " + i); } - output.write(", " + i); } } catch (IllegalStateException e) { diff --git a/packages/SystemUI/res/drawable-hdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-hdpi/notification_panel_bg.9.png Binary files differindex 8a0a30f..ff0bd4c 100644 --- a/packages/SystemUI/res/drawable-hdpi/notification_panel_bg.9.png +++ b/packages/SystemUI/res/drawable-hdpi/notification_panel_bg.9.png diff --git a/packages/SystemUI/res/drawable-mdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-mdpi/notification_panel_bg.9.png Binary files differindex 25f15e6..2bbb2c6 100644 --- a/packages/SystemUI/res/drawable-mdpi/notification_panel_bg.9.png +++ b/packages/SystemUI/res/drawable-mdpi/notification_panel_bg.9.png diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/notification_panel_bg.9.png Binary files differindex 2ff93d3..e7caeda 100644 --- a/packages/SystemUI/res/drawable-sw600dp-hdpi/notification_panel_bg.9.png +++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/notification_panel_bg.9.png diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/notification_panel_bg.9.png Binary files differindex 430f913..ae07083 100644 --- a/packages/SystemUI/res/drawable-sw600dp-mdpi/notification_panel_bg.9.png +++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/notification_panel_bg.9.png diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/notification_panel_bg.9.png Binary files differindex 807241a..8423ef9 100644 --- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/notification_panel_bg.9.png +++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/notification_panel_bg.9.png diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/notification_panel_bg.9.png Binary files differindex 2ff93d3..0c20ba2 100644 --- a/packages/SystemUI/res/drawable-sw720dp-hdpi/notification_panel_bg.9.png +++ b/packages/SystemUI/res/drawable-sw720dp-hdpi/notification_panel_bg.9.png diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/notification_panel_bg.9.png Binary files differindex 430f913..56cd238 100644 --- a/packages/SystemUI/res/drawable-sw720dp-mdpi/notification_panel_bg.9.png +++ b/packages/SystemUI/res/drawable-sw720dp-mdpi/notification_panel_bg.9.png diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/notification_panel_bg.9.png Binary files differindex 807241a..3f05767 100644 --- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/notification_panel_bg.9.png +++ b/packages/SystemUI/res/drawable-sw720dp-xhdpi/notification_panel_bg.9.png diff --git a/packages/SystemUI/res/drawable-xhdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-xhdpi/notification_panel_bg.9.png Binary files differindex 60e7418..932e0ef 100644 --- a/packages/SystemUI/res/drawable-xhdpi/notification_panel_bg.9.png +++ b/packages/SystemUI/res/drawable-xhdpi/notification_panel_bg.9.png diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 6433cd3..ca29738 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -145,6 +145,6 @@ <string name="notifications_off_title" msgid="8936620513608443224">"通知功能已停用"</string> <string name="notifications_off_text" msgid="2529001315769385273">"点按此处可重新启用通知功能。"</string> <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"屏幕会自动旋转。"</string> - <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"屏幕锁定为横向浏览模式。"</string> - <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"屏幕已锁定为纵向浏览模式。"</string> + <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"屏幕锁定为横向模式。"</string> + <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"屏幕锁定为纵向模式。"</string> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java b/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java index 1db2a7f..73249b4 100644 --- a/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java +++ b/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java @@ -58,8 +58,8 @@ public class DreamsDockLauncher extends Activity { @Override public void onReceive(Context context, Intent intent) { final boolean activateOnDock = 0 != Settings.Secure.getInt( - context.getContentResolver(), - Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, 1); + context.getContentResolver(), + Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, 0); if (!activateOnDock) return; diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index 89bf3b6..587bfe8 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -309,7 +309,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener // if there are no apps, either bring up a "No recent apps" message, or just // quit early - boolean noApps = (mRecentTaskDescriptions.size() == 0); + boolean noApps = !mFirstScreenful && (mRecentTaskDescriptions.size() == 0); if (mRecentsNoApps != null) { mRecentsNoApps.setVisibility(noApps ? View.VISIBLE : View.INVISIBLE); } else { diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java index 3c71784..f682203 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java @@ -101,6 +101,9 @@ public class RecentsVerticalScrollView extends ScrollView } final View view = mAdapter.getView(i, old, mLinearLayout); + if (view.getParent() != null) { + throw new RuntimeException("Recycled child has parent"); + } if (mPerformanceHelper != null) { mPerformanceHelper.addViewCallback(view); @@ -139,6 +142,9 @@ public class RecentsVerticalScrollView extends ScrollView thumbnailView.setClickable(true); thumbnailView.setOnClickListener(launchAppListener); thumbnailView.setOnLongClickListener(longClickListener); + if (view.getParent() != null) { + throw new RuntimeException("Recycled child has parent"); + } // We don't want to dismiss recents if a user clicks on the app title // (we also don't want to launch the app either, though, because the @@ -148,6 +154,9 @@ public class RecentsVerticalScrollView extends ScrollView appTitle.setOnTouchListener(noOpListener); final View calloutLine = view.findViewById(R.id.recents_callout_line); calloutLine.setOnTouchListener(noOpListener); + if (view.getParent() != null) { + throw new RuntimeException("Recycled child has parent"); + } mLinearLayout.addView(view); } diff --git a/policy/src/com/android/internal/policy/impl/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/FaceUnlock.java index 737ea47..22b854e 100644 --- a/policy/src/com/android/internal/policy/impl/FaceUnlock.java +++ b/policy/src/com/android/internal/policy/impl/FaceUnlock.java @@ -468,7 +468,8 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { if (!mServiceRunning) { Log.d(TAG, "Starting Face Unlock"); try { - mService.startUi(windowToken, x, y, w, h, false); + mService.startUi(windowToken, x, y, w, h, + mLockPatternUtils.isBiometricWeakLivelinessEnabled()); } catch (RemoteException e) { Log.e(TAG, "Caught exception starting Face Unlock: " + e.toString()); return; diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index cce55d5..1033296 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -2278,7 +2278,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { // It's a system nav bar or a portrait screen; nav bar goes on bottom. int top = displayHeight - mNavigationBarHeightForRotation[displayRotation]; if (mHdmiPlugged) { - if (top > mExternalDisplayHeight) { + // Move the nav bar up if the external display is the same aspect ratio + // but shorter. This avoids clipping on the external display. + boolean sameAspect = mExternalDisplayHeight > 0 && displayHeight > 0 + && ((float) mExternalDisplayWidth / mExternalDisplayHeight > 1) + == ((float) displayWidth / displayHeight > 1); + if (sameAspect && top > mExternalDisplayHeight) { top = mExternalDisplayHeight; } } diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index 38e08ae..469b4f1 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -2242,7 +2242,9 @@ public class PowerManagerService extends IPowerManager.Stub } else { newValue = endValue; mHighestLightSensorValue = endSensorValue; - mInitialAnimation = false; + if (endValue > 0) { + mInitialAnimation = false; + } } if (mDebugLightAnimation) { @@ -2290,7 +2292,7 @@ public class PowerManagerService extends IPowerManager.Stub currentMask = mask; duration = (int) (mWindowScaleAnimation * animationDuration); startTimeMillis = SystemClock.elapsedRealtime(); - mInitialAnimation = currentValue == 0 && target > 0; + mInitialAnimation = mInitialAnimation && target > 0; if (mDebugLightAnimation) { Slog.v(TAG, "animateTo(target=" + target @@ -2608,7 +2610,8 @@ public class PowerManagerService extends IPowerManager.Stub } }; - private boolean mInitialAnimation; // used to prevent lightsensor changes while turning on + /** used to prevent lightsensor changes while turning on. */ + private boolean mInitialAnimation = true; private void dockStateChanged(int state) { synchronized (mLocks) { diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java index c936ef9..d1f92a7 100644 --- a/services/java/com/android/server/UiModeManagerService.java +++ b/services/java/com/android/server/UiModeManagerService.java @@ -65,7 +65,7 @@ class UiModeManagerService extends IUiModeManager.Stub { // Enable launching of applications when entering the dock. private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true; - private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = false; + private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true; private static final int MSG_UPDATE_TWILIGHT = 0; private static final int MSG_ENABLE_LOCATION_UPDATES = 1; @@ -120,7 +120,7 @@ class UiModeManagerService extends IUiModeManager.Stub { | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); return intent; } - + // The broadcast receiver which receives the result of the ordered broadcast sent when // the dock state changes. The original ordered broadcast is sent with an initial result // code of RESULT_OK. If any of the registered broadcast receivers changes this value, e.g., @@ -130,7 +130,7 @@ class UiModeManagerService extends IUiModeManager.Stub { public void onReceive(Context context, Intent intent) { if (getResultCode() != Activity.RESULT_OK) { if (LOG) { - Slog.v(TAG, "Handling broadcast result for action " + intent.getAction() + Slog.v(TAG, "Handling broadcast result for action " + intent.getAction() + ": canceled: " + getResultCode()); } return; @@ -138,7 +138,7 @@ class UiModeManagerService extends IUiModeManager.Stub { final int enableFlags = intent.getIntExtra("enableFlags", 0); final int disableFlags = intent.getIntExtra("disableFlags", 0); - + synchronized (mLock) { // Launch a dock activity String category = null; @@ -166,15 +166,15 @@ class UiModeManagerService extends IUiModeManager.Stub { if (LOG) { Slog.v(TAG, String.format( - "Handling broadcast result for action %s: enable=0x%08x disable=0x%08x category=%s", + "Handling broadcast result for action %s: enable=0x%08x disable=0x%08x category=%s", intent.getAction(), enableFlags, disableFlags, category)); } - + if (category != null) { // This is the new activity that will serve as home while // we are in care mode. Intent homeIntent = buildHomeIntent(category); - + // Now we are going to be careful about switching the // configuration and starting the activity -- we need to // do this in a specific order under control of the @@ -479,8 +479,8 @@ class UiModeManagerService extends IUiModeManager.Stub { } if (LOG) { - Slog.d(TAG, - "updateConfigurationLocked: mDockState=" + mDockState + Slog.d(TAG, + "updateConfigurationLocked: mDockState=" + mDockState + "; mCarMode=" + mCarModeEnabled + "; mNightMode=" + mNightMode + "; uiMode=" + uiMode); @@ -657,7 +657,7 @@ class UiModeManagerService extends IUiModeManager.Stub { boolean mNetworkListenerEnabled; boolean mDidFirstInit; long mLastNetworkRegisterTime = -MIN_LOCATION_UPDATE_MS; - + @Override public void handleMessage(Message msg) { switch (msg.what) { @@ -682,12 +682,12 @@ class UiModeManagerService extends IUiModeManager.Stub { // since we last requested an update. return; } - + // Unregister the current location monitor, so we can // register a new one for it to get an immediate update. mNetworkListenerEnabled = false; mLocationManager.removeUpdates(mEmptyLocationListener); - + // Fall through to re-register listener. case MSG_ENABLE_LOCATION_UPDATES: // enable network provider to receive at least location updates for a given diff --git a/services/java/com/android/server/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java index 53d1f0e..96ac493 100644 --- a/services/java/com/android/server/WiredAccessoryObserver.java +++ b/services/java/com/android/server/WiredAccessoryObserver.java @@ -139,11 +139,14 @@ class WiredAccessoryObserver extends UEventObserver { private final Context mContext; private final WakeLock mWakeLock; // held while there is a pending route change + private final AudioManager mAudioManager; + public WiredAccessoryObserver(Context context) { mContext = context; PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryObserver"); mWakeLock.setReferenceCounted(false); + mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE); context.registerReceiver(new BootCompletedReceiver(), new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null); @@ -250,106 +253,65 @@ class WiredAccessoryObserver extends UEventObserver { mPrevHeadsetState = mHeadsetState; mHeadsetState = headsetState; - if (headsetState == 0) { - if (mContext.getResources().getBoolean( - com.android.internal.R.bool.config_sendAudioBecomingNoisy)) { - Intent intent = new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY); - mContext.sendBroadcast(intent); - } - - // It can take hundreds of ms flush the audio pipeline after - // apps pause audio playback, but audio route changes are - // immediate, so delay the route change by 1000ms. - // This could be improved once the audio sub-system provides an - // interface to clear the audio pipeline. - delay = 1000; - } else { - // Insert the same delay for headset connection so that the connection event is not - // broadcast before the disconnection event in case of fast removal/insertion - if (mHandler.hasMessages(0)) { - delay = 1000; - } - } mWakeLock.acquire(); - mHandler.sendMessageDelayed(mHandler.obtainMessage(0, - mHeadsetState, - mPrevHeadsetState, - mHeadsetName), - delay); + mHandler.sendMessage(mHandler.obtainMessage(0, + mHeadsetState, + mPrevHeadsetState, + mHeadsetName)); } - private synchronized final void sendIntents(int headsetState, int prevHeadsetState, String headsetName) { + private synchronized final void setDevicesState(int headsetState, + int prevHeadsetState, + String headsetName) { int allHeadsets = SUPPORTED_HEADSETS; for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) { if ((curHeadset & allHeadsets) != 0) { - sendIntent(curHeadset, headsetState, prevHeadsetState, headsetName); + setDeviceState(curHeadset, headsetState, prevHeadsetState, headsetName); allHeadsets &= ~curHeadset; } } } - private final void sendIntent(int headset, int headsetState, int prevHeadsetState, String headsetName) { + private final void setDeviceState(int headset, + int headsetState, + int prevHeadsetState, + String headsetName) { if ((headsetState & headset) != (prevHeadsetState & headset)) { + int device; + int state; - int state = 0; if ((headsetState & headset) != 0) { state = 1; + } else { + state = 0; } - if((headset == BIT_USB_HEADSET_ANLG) || (headset == BIT_USB_HEADSET_DGTL) || - (headset == BIT_HDMI_AUDIO)) { - Intent intent; - - // Pack up the values and broadcast them to everyone - if (headset == BIT_USB_HEADSET_ANLG) { - intent = new Intent(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - intent.putExtra("state", state); - intent.putExtra("name", headsetName); - ActivityManagerNative.broadcastStickyIntent(intent, null); - } else if (headset == BIT_USB_HEADSET_DGTL) { - intent = new Intent(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - intent.putExtra("state", state); - intent.putExtra("name", headsetName); - ActivityManagerNative.broadcastStickyIntent(intent, null); - } else if (headset == BIT_HDMI_AUDIO) { - intent = new Intent(Intent.ACTION_HDMI_AUDIO_PLUG); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - intent.putExtra("state", state); - intent.putExtra("name", headsetName); - ActivityManagerNative.broadcastStickyIntent(intent, null); - } - if (LOG) Slog.v(TAG, "Intent.ACTION_USB_HEADSET_PLUG: state: "+state+" name: "+headsetName); - // TODO: Should we require a permission? + if (headset == BIT_HEADSET) { + device = AudioManager.DEVICE_OUT_WIRED_HEADSET; + } else if (headset == BIT_HEADSET_NO_MIC){ + device = AudioManager.DEVICE_OUT_WIRED_HEADPHONE; + } else if (headset == BIT_USB_HEADSET_ANLG) { + device = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET; + } else if (headset == BIT_USB_HEADSET_DGTL) { + device = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET; + } else if (headset == BIT_HDMI_AUDIO) { + device = AudioManager.DEVICE_OUT_AUX_DIGITAL; + } else { + Slog.e(TAG, "setDeviceState() invalid headset type: "+headset); + return; } - if((headset == BIT_HEADSET) || (headset == BIT_HEADSET_NO_MIC)) { - // Pack up the values and broadcast them to everyone - Intent intent = new Intent(Intent.ACTION_HEADSET_PLUG); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - //int state = 0; - int microphone = 0; + if (LOG) + Slog.v(TAG, "device "+headsetName+((state == 1) ? " connected" : " disconnected")); - if ((headset & HEADSETS_WITH_MIC) != 0) { - microphone = 1; - } - - intent.putExtra("state", state); - intent.putExtra("name", headsetName); - intent.putExtra("microphone", microphone); - - if (LOG) Slog.v(TAG, "Intent.ACTION_HEADSET_PLUG: state: "+state+" name: "+headsetName+" mic: "+microphone); - // TODO: Should we require a permission? - ActivityManagerNative.broadcastStickyIntent(intent, null); - } + mAudioManager.setWiredDeviceConnectionState(device, state, headsetName); } } private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { - sendIntents(msg.arg1, msg.arg2, (String)msg.obj); + setDevicesState(msg.arg1, msg.arg2, (String)msg.obj); mWakeLock.release(); } }; diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java index 039efbd..3e8f512 100644 --- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -104,10 +104,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE = "registerUiTestAutomationService"; + private static final char COMPONENT_NAME_SEPARATOR = ':'; + private static final int OWN_PROCESS_ID = android.os.Process.myPid(); private static final int MSG_SHOW_ENABLE_TOUCH_EXPLORATION_DIALOG = 1; + private static final int MSG_TOGGLE_TOUCH_EXPLORATION = 2; + private static int sIdCounter = 0; private static int sNextWindowId; @@ -127,12 +131,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>(); + private final Set<ComponentName> mTouchExplorationGrantedServices = new HashSet<ComponentName>(); + private final SparseArray<AccessibilityConnectionWrapper> mWindowIdToInteractionConnectionWrapperMap = new SparseArray<AccessibilityConnectionWrapper>(); private final SparseArray<IBinder> mWindowIdToWindowTokenMap = new SparseArray<IBinder>(); - private final SimpleStringSplitter mStringColonSplitter = new SimpleStringSplitter(':'); + private final SimpleStringSplitter mStringColonSplitter = new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); private final Rect mTempRect = new Rect(); @@ -164,6 +170,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private boolean mTouchExplorationGestureStarted; + private AlertDialog mEnableTouchExplorationDialog; + /** * Creates a new instance. * @@ -208,7 +216,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { String compPkg = comp.getPackageName(); if (compPkg.equals(packageName)) { it.remove(); - updateEnabledAccessibilitySerivcesSettingLocked(mEnabledServices); + // Update the enabled services setting. + persistComponentNamesToSettingLocked( + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + mEnabledServices); + // Update the touch exploration granted services setting. + mTouchExplorationGrantedServices.remove(comp); + persistComponentNamesToSettingLocked( + Settings.Secure. + TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, + mEnabledServices); return; } } @@ -219,7 +236,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) { synchronized (mLock) { - boolean changed = false; Iterator<ComponentName> it = mEnabledServices.iterator(); while (it.hasNext()) { ComponentName comp = it.next(); @@ -230,13 +246,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return true; } it.remove(); - changed = true; + persistComponentNamesToSettingLocked( + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + mEnabledServices); } } } - if (changed) { - updateEnabledAccessibilitySerivcesSettingLocked(mEnabledServices); - } return false; } } @@ -248,33 +263,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // We will update when the automation service dies. if (mUiAutomationService == null) { populateAccessibilityServiceListLocked(); + populateEnabledAccessibilityServicesLocked(); + populateTouchExplorationGrantedAccessibilityServicesLocked(); handleAccessibilityEnabledSettingChangedLocked(); handleTouchExplorationEnabledSettingChangedLocked(); updateInputFilterLocked(); sendStateToClientsLocked(); } } - return; } super.onReceive(context, intent); } - - private void updateEnabledAccessibilitySerivcesSettingLocked( - Set<ComponentName> enabledServices) { - Iterator<ComponentName> it = enabledServices.iterator(); - StringBuilder str = new StringBuilder(); - while (it.hasNext()) { - if (str.length() > 0) { - str.append(':'); - } - str.append(it.next().flattenToShortString()); - } - Settings.Secure.putString(mContext.getContentResolver(), - Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, - str.toString()); - } }; // package changes @@ -338,6 +339,25 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { synchronized (mLock) { // We will update when the automation service dies. if (mUiAutomationService == null) { + populateEnabledAccessibilityServicesLocked(); + manageServicesLocked(); + } + } + } + }); + + Uri touchExplorationGrantedServicesUri = Settings.Secure.getUriFor( + Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES); + contentResolver.registerContentObserver(touchExplorationGrantedServicesUri, false, + new ContentObserver(new Handler()) { + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + synchronized (mLock) { + // We will update when the automation service dies. + if (mUiAutomationService == null) { + populateTouchExplorationGrantedAccessibilityServicesLocked(); + unbindAllServicesLocked(); manageServicesLocked(); } } @@ -647,6 +667,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } + private void populateEnabledAccessibilityServicesLocked() { + populateComponentNamesFromSettingLocked( + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + mEnabledServices); + } + + private void populateTouchExplorationGrantedAccessibilityServicesLocked() { + populateComponentNamesFromSettingLocked( + Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, + mTouchExplorationGrantedServices); + } + /** * Performs {@link AccessibilityService}s delayed notification. The delay is configurable * and denotes the period after the last event before notifying the service. @@ -689,7 +721,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { mServices.add(service); mComponentNameToServiceMap.put(service.mComponentName, service); updateInputFilterLocked(); - tryEnableTouchExploration(service); + tryEnableTouchExplorationLocked(service); } catch (RemoteException e) { /* do nothing */ } @@ -710,7 +742,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { service.unlinkToOwnDeath(); service.dispose(); updateInputFilterLocked(); - tryDisableTouchExploration(service); + tryDisableTouchExplorationLocked(service); return removed; } @@ -762,7 +794,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { * Manages services by starting enabled ones and stopping disabled ones. */ private void manageServicesLocked() { - populateEnabledServicesLocked(mEnabledServices); final int enabledInstalledServicesCount = updateServicesStateLocked(mInstalledServices, mEnabledServices); // No enabled installed services => disable accessibility to avoid @@ -789,20 +820,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } /** - * Populates a list with the {@link ComponentName}s of all enabled - * {@link AccessibilityService}s. + * Populates a set with the {@link ComponentName}s stored in a colon + * separated value setting. * - * @param enabledServices The list. + * @param settingName The setting to parse. + * @param outComponentNames The output component names. */ - private void populateEnabledServicesLocked(Set<ComponentName> enabledServices) { - enabledServices.clear(); + private void populateComponentNamesFromSettingLocked(String settingName, + Set<ComponentName> outComponentNames) { + outComponentNames.clear(); - String servicesValue = Settings.Secure.getString(mContext.getContentResolver(), - Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); + String settingValue = Settings.Secure.getString(mContext.getContentResolver(), settingName); - if (servicesValue != null) { + if (settingValue != null) { TextUtils.SimpleStringSplitter splitter = mStringColonSplitter; - splitter.setString(servicesValue); + splitter.setString(settingValue); while (splitter.hasNext()) { String str = splitter.next(); if (str == null || str.length() <= 0) { @@ -810,13 +842,32 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } ComponentName enabledService = ComponentName.unflattenFromString(str); if (enabledService != null) { - enabledServices.add(enabledService); + outComponentNames.add(enabledService); } } } } /** + * Persists the component names in the specified setting in a + * colon separated fashion. + * + * @param settingName The setting name. + * @param componentNames The component names. + */ + private void persistComponentNamesToSettingLocked(String settingName, + Set<ComponentName> componentNames) { + StringBuilder builder = new StringBuilder(); + for (ComponentName componentName : componentNames) { + if (builder.length() > 0) { + builder.append(COMPONENT_NAME_SEPARATOR); + } + builder.append(componentName.flattenToShortString()); + } + Settings.Secure.putString(mContext.getContentResolver(), settingName, builder.toString()); + } + + /** * Updates the state of each service by starting (or keeping running) enabled ones and * stopping the rest. * @@ -935,20 +986,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1; } - private void tryEnableTouchExploration(final Service service) { + private void tryEnableTouchExplorationLocked(final Service service) { if (!mIsTouchExplorationEnabled && service.mRequestTouchExplorationMode) { - if (!service.mIsAutomation) { + final boolean canToggleTouchExploration = mTouchExplorationGrantedServices.contains( + service.mComponentName); + if (!service.mIsAutomation && !canToggleTouchExploration) { mMainHandler.obtainMessage(MSG_SHOW_ENABLE_TOUCH_EXPLORATION_DIALOG, service).sendToTarget(); } else { - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1); + mMainHandler.obtainMessage(MSG_TOGGLE_TOUCH_EXPLORATION, 1, 0).sendToTarget(); } } } - private void tryDisableTouchExploration(Service service) { - if (mIsTouchExplorationEnabled && service.mReqeustTouchExplorationMode) { + private void tryDisableTouchExplorationLocked(Service service) { + if (mIsTouchExplorationEnabled) { synchronized (mLock) { final int serviceCount = mServices.size(); for (int i = 0; i < serviceCount; i++) { @@ -957,8 +1009,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return; } } - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0); + mMainHandler.obtainMessage(MSG_TOGGLE_TOUCH_EXPLORATION, 0, 0).sendToTarget(); } } } @@ -995,32 +1046,54 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public void handleMessage(Message msg) { final int type = msg.what; switch (type) { + case MSG_TOGGLE_TOUCH_EXPLORATION: { + final int value = msg.arg1; + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.TOUCH_EXPLORATION_ENABLED, value); + } break; case MSG_SHOW_ENABLE_TOUCH_EXPLORATION_DIALOG: { - Service service = (Service) msg.obj; + final Service service = (Service) msg.obj; String label = service.mResolveInfo.loadLabel( mContext.getPackageManager()).toString(); - final AlertDialog dialog = new AlertDialog.Builder(mContext) - .setIcon(android.R.drawable.ic_dialog_alert) - .setPositiveButton(android.R.string.ok, new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1); - } - }) - .setNegativeButton(android.R.string.cancel, new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }) - .setTitle(R.string.enable_explore_by_touch_warning_title) - .setMessage(mContext.getString( - R.string.enable_explore_by_touch_warning_message, label)) - .create(); - dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG); - dialog.setCanceledOnTouchOutside(true); - dialog.show(); + synchronized (mLock) { + if (mIsTouchExplorationEnabled) { + return; + } + if (mEnableTouchExplorationDialog != null + && mEnableTouchExplorationDialog.isShowing()) { + return; + } + mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext) + .setIcon(android.R.drawable.ic_dialog_alert) + .setPositiveButton(android.R.string.ok, new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // The user allowed the service to toggle touch exploration. + mTouchExplorationGrantedServices.add(service.mComponentName); + persistComponentNamesToSettingLocked( + Settings.Secure. + TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, + mTouchExplorationGrantedServices); + // Enable touch exploration. + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1); + } + }) + .setNegativeButton(android.R.string.cancel, new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }) + .setTitle(R.string.enable_explore_by_touch_warning_title) + .setMessage(mContext.getString( + R.string.enable_explore_by_touch_warning_message, label)) + .create(); + mEnableTouchExplorationDialog.getWindow().setType( + WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG); + mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true); + mEnableTouchExplorationDialog.show(); + } } } } @@ -1143,8 +1216,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { mRequestTouchExplorationMode = (info.flags & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0; + // If this service is up and running we may have to enable touch + // exploration, otherwise this will happen when the service connects. synchronized (mLock) { - tryAddServiceLocked(this); + if (isConfigured()) { + if (mRequestTouchExplorationMode) { + tryEnableTouchExplorationLocked(this); + } else { + tryDisableTouchExplorationLocked(this); + } + } } } @@ -1496,6 +1577,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { if (mIsAutomation) { mUiAutomationService = null; + populateEnabledAccessibilityServicesLocked(); + populateTouchExplorationGrantedAccessibilityServicesLocked(); + handleAccessibilityEnabledSettingChangedLocked(); sendStateToClientsLocked(); diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java index b0b2b8d..4c38ab9 100644 --- a/services/java/com/android/server/accessibility/TouchExplorer.java +++ b/services/java/com/android/server/accessibility/TouchExplorer.java @@ -1532,7 +1532,7 @@ public class TouchExplorer { */ public ReceivedPointerTracker(Context context) { mThresholdActivePointer = - ViewConfiguration.get(context).getScaledTouchSlop() * COEFFICIENT_ACTIVE_POINTER; + ViewConfiguration.get(context).getScaledTouchSlop() * COEFFICIENT_ACTIVE_POINTER;//Heie govna } /** diff --git a/services/java/com/android/server/am/ContentProviderConnection.java b/services/java/com/android/server/am/ContentProviderConnection.java index 84f8f02..7f69b24 100644 --- a/services/java/com/android/server/am/ContentProviderConnection.java +++ b/services/java/com/android/server/am/ContentProviderConnection.java @@ -17,6 +17,8 @@ package com.android.server.am; import android.os.Binder; +import android.os.SystemClock; +import android.util.TimeUtils; /** * Represents a link between a content provider and client. @@ -24,6 +26,7 @@ import android.os.Binder; public class ContentProviderConnection extends Binder { public final ContentProviderRecord provider; public final ProcessRecord client; + public final long createTime; public int stableCount; public int unstableCount; // The client of this connection is currently waiting for the provider to appear. @@ -39,6 +42,7 @@ public class ContentProviderConnection extends Binder { public ContentProviderConnection(ContentProviderRecord _provider, ProcessRecord _client) { provider = _provider; client = _client; + createTime = SystemClock.elapsedRealtime(); } public String toString() { @@ -83,5 +87,8 @@ public class ContentProviderConnection extends Binder { if (dead) { sb.append(" DEAD"); } + long nowReal = SystemClock.elapsedRealtime(); + sb.append(" "); + TimeUtils.formatDuration(nowReal-createTime, sb); } } diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java index d85facc..bdd0aa4 100644 --- a/services/java/com/android/server/input/InputManagerService.java +++ b/services/java/com/android/server/input/InputManagerService.java @@ -592,7 +592,7 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. deviceIdAndGeneration[i * 2] = inputDevice.getId(); deviceIdAndGeneration[i * 2 + 1] = inputDevice.getGeneration(); - if (isFullKeyboard(inputDevice)) { + if (!inputDevice.isVirtual() && inputDevice.isFullKeyboard()) { if (!containsInputDeviceWithDescriptor(oldInputDevices, inputDevice.getDescriptor())) { mTempFullKeyboards.add(numFullKeyboardsAdded++, inputDevice); @@ -695,12 +695,6 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. reloadKeyboardLayouts(); } - private static boolean isFullKeyboard(InputDevice inputDevice) { - return !inputDevice.isVirtual() - && (inputDevice.getSources() & InputDevice.SOURCE_KEYBOARD) != 0 - && inputDevice.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC; - } - private static boolean containsInputDeviceWithDescriptor(InputDevice[] inputDevices, String descriptor) { final int numDevices = inputDevices.length; diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 4ce8c97..10919f2 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -6466,17 +6466,18 @@ public class WindowManagerService extends IWindowManager.Stub WindowManagerPolicy.PRESENCE_INTERNAL; if (mIsTouchDevice) { - if ((sources & InputDevice.SOURCE_TOUCHSCREEN) != 0) { + if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == + InputDevice.SOURCE_TOUCHSCREEN) { config.touchscreen = Configuration.TOUCHSCREEN_FINGER; } } else { config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; } - if ((sources & InputDevice.SOURCE_TRACKBALL) != 0) { + if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { config.navigation = Configuration.NAVIGATION_TRACKBALL; navigationPresence |= presenceFlag; - } else if ((sources & InputDevice.SOURCE_DPAD) != 0 + } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD && config.navigation == Configuration.NAVIGATION_NONAV) { config.navigation = Configuration.NAVIGATION_DPAD; navigationPresence |= presenceFlag; diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index 04ec820..9e5e84b 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -226,7 +226,7 @@ bool SensorService::threadLoop() ALOGD("nuSensorService thread starting..."); const size_t numEventMax = 16; - const size_t minBufferSize = numEventMax * mVirtualSensorList.size(); + const size_t minBufferSize = numEventMax + numEventMax * mVirtualSensorList.size(); sensors_event_t buffer[minBufferSize]; sensors_event_t scratch[minBufferSize]; SensorDevice& device(SensorDevice::getInstance()); diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java index 5220d04..1a42f93 100644 --- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java +++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java @@ -263,12 +263,19 @@ public class WifiWatchdogStateMachine extends StateMachine { Context.CONNECTIVITY_SERVICE); sWifiOnly = (cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false); - // Disable for wifi only devices. - if (Settings.Secure.getString(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON) == null - && sWifiOnly) { - log("Disabling watchog for wi-fi only device"); - putSettingsBoolean(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON, false); + // Watchdog is always enabled. Poor network detection & walled garden detection + // can individually be turned on/off + // TODO: Remove this setting & clean up state machine since we always have + // watchdog in an enabled state + putSettingsBoolean(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON, true); + + // Disable poor network avoidance, but keep watchdog active for walled garden detection + if (sWifiOnly) { + log("Disabling poor network avoidance for wi-fi only device"); + putSettingsBoolean(contentResolver, + Settings.Secure.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, false); } + WifiWatchdogStateMachine wwsm = new WifiWatchdogStateMachine(context); wwsm.start(); return wwsm; |
