Merge "Fix typo preventing layers from scrolling to top"
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4bd5b94..4d589d7 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4056,9 +4056,13 @@
mChoreographer.removeCallbacks(Choreographer.CALLBACK_INPUT,
mConsumedBatchedInputRunnable, null);
}
- if (mInputEventReceiver != null) {
- mInputEventReceiver.consumeBatchedInputEvents();
- }
+ }
+
+ // Always consume batched input events even if not scheduled, because there
+ // might be new input there waiting for us that we have no noticed yet because
+ // the Looper has not had a chance to run again.
+ if (mInputEventReceiver != null) {
+ mInputEventReceiver.consumeBatchedInputEvents();
}
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index aca1fa2..6e36fdb 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -35,5 +35,7 @@
void setImeWindowStatus(in IBinder token, int vis, int backDisposition);
void setHardKeyboardStatus(boolean available, boolean enabled);
void toggleRecentApps();
+ void preloadRecentApps();
+ void cancelPreloadRecentApps();
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index ecebfc0..118e541 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -47,4 +47,6 @@
void setSystemUiVisibility(int vis);
void setHardKeyboardEnabled(boolean enabled);
void toggleRecentApps();
+ void preloadRecentApps();
+ void cancelPreloadRecentApps();
}
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index 8a1c4a9..72c171c 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -49,7 +49,6 @@
status_t initialize();
status_t scheduleVsync();
- static int handleReceiveCallback(int receiveFd, int events, void* data);
protected:
virtual ~NativeDisplayEventReceiver();
@@ -59,6 +58,9 @@
sp<Looper> mLooper;
DisplayEventReceiver mReceiver;
bool mWaitingForVsync;
+
+ static int handleReceiveCallback(int receiveFd, int events, void* data);
+ bool readLastVsyncMessage(nsecs_t* outTimestamp, uint32_t* outCount);
};
@@ -100,16 +102,9 @@
ALOGV("receiver %p ~ Scheduling vsync.", this);
// Drain all pending events.
- DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
- ssize_t n;
- while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
- ALOGV("receiver %p ~ Drained %d events.", this, int(n));
- }
-
- if (n < 0) {
- ALOGW("Failed to drain events from display event receiver, status=%d", status_t(n));
- return status_t(n);
- }
+ nsecs_t vsyncTimestamp;
+ uint32_t vsyncCount;
+ readLastVsyncMessage(&vsyncTimestamp, &vsyncCount);
status_t status = mReceiver.requestNextVsync();
if (status) {
@@ -138,23 +133,9 @@
}
// Drain all pending events, keep the last vsync.
- nsecs_t vsyncTimestamp = -1;
- uint32_t vsyncCount = 0;
-
- DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
- ssize_t n;
- while ((n = r->mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
- ALOGV("receiver %p ~ Read %d events.", data, int(n));
- while (n-- > 0) {
- if (buf[n].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
- vsyncTimestamp = buf[n].header.timestamp;
- vsyncCount = buf[n].vsync.count;
- break; // stop at last vsync in the buffer
- }
- }
- }
-
- if (vsyncTimestamp < 0) {
+ nsecs_t vsyncTimestamp;
+ uint32_t vsyncCount;
+ if (!r->readLastVsyncMessage(&vsyncTimestamp, &vsyncCount)) {
ALOGV("receiver %p ~ Woke up but there was no vsync pulse!", data);
return 1; // keep the callback, did not obtain a vsync pulse
}
@@ -179,6 +160,26 @@
return 1; // keep the callback
}
+bool NativeDisplayEventReceiver::readLastVsyncMessage(
+ nsecs_t* outTimestamp, uint32_t* outCount) {
+ DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
+ ssize_t n;
+ while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
+ ALOGV("receiver %p ~ Read %d events.", this, int(n));
+ while (n-- > 0) {
+ if (buf[n].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
+ *outTimestamp = buf[n].header.timestamp;
+ *outCount = buf[n].vsync.count;
+ return true; // stop at last vsync in the buffer
+ }
+ }
+ }
+ if (n < 0) {
+ ALOGW("Failed to get events from display event receiver, status=%d", status_t(n));
+ }
+ return false;
+}
+
static jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,
jobject messageQueueObj) {
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9c5f4d6..7b4f50b 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -850,6 +850,8 @@
<java-symbol type="string" name="wifi_watchdog_network_disabled" />
<java-symbol type="string" name="wifi_watchdog_network_disabled_detailed" />
<java-symbol type="string" name="yesterday" />
+ <java-symbol type="string" name="imei" />
+ <java-symbol type="string" name="meid" />
<java-symbol type="plurals" name="abbrev_in_num_days" />
<java-symbol type="plurals" name="abbrev_in_num_hours" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 7799f74..6c9576f 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -97,6 +97,12 @@
the SIM card. -->
<string name="needPuk">Your SIM card is PUK-locked. Type the PUK code to unlock it.</string>
<string name="needPuk2">Type PUK2 to unblock SIM card.</string>
+ <!-- Title for the dialog used to display the user's IMEI number [CHAR LIMIT=10] -->
+ <string name="imei">IMEI</string>
+
+ <!-- Title for the dialog used to display the user's MEID number on CDMA network
+ [CHAR LIMIT=10] -->
+ <string name="meid">MEID</string>
<!-- Displayed as the title for a success/failure report enabling/disabling caller ID. -->
<string name="ClipMmi">Incoming Caller ID</string>
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index a8144a7..43df8a1 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -839,7 +839,7 @@
// and EXIF local time is not less than 1 Day, otherwise MediaProvider
// will use file time as taken time.
time = exif.getDateTime();
- if (Math.abs(mLastModified * 1000 - time) >= 86400000) {
+ if (time != -1 && Math.abs(mLastModified * 1000 - time) >= 86400000) {
values.put(Images.Media.DATE_TAKEN, time);
}
}
@@ -1183,7 +1183,7 @@
static class MediaBulkDeleter {
StringBuilder whereClause = new StringBuilder();
- ArrayList<String> whereArgs = new ArrayList<String>(100);
+ ArrayList<String> whereArgs = new ArrayList<String>(100);
IContentProvider mProvider;
Uri mBaseUri;
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index b868049..c937a09 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -779,8 +779,7 @@
if (LOG_THREADS) {
Log.i("DefaultContextFactory", "tid=" + Thread.currentThread().getId());
}
- throw new RuntimeException("eglDestroyContext failed: "
- + EGLLogWrapper.getErrorString(egl.eglGetError()));
+ EglHelper.throwEglException("eglDestroyContex", egl.eglGetError());
}
}
}
@@ -1094,7 +1093,12 @@
* the context is current and bound to a surface.
*/
if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
- throwEglException("eglMakeCurrent");
+ /*
+ * Could not make the context current, probably because the underlying
+ * SurfaceView surface has been destroyed.
+ */
+ logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError());
+ return false;
}
return true;
@@ -1134,7 +1138,7 @@
*/
public int swap() {
if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
- return mEgl.eglGetError();
+ return mEgl.eglGetError();
}
return EGL10.EGL_SUCCESS;
}
@@ -1180,14 +1184,23 @@
throwEglException(function, mEgl.eglGetError());
}
- private void throwEglException(String function, int error) {
- String message = function + " failed: " + EGLLogWrapper.getErrorString(error);
+ public static void throwEglException(String function, int error) {
+ String message = formatEglError(function, error);
if (LOG_THREADS) {
- Log.e("EglHelper", "throwEglException tid=" + Thread.currentThread().getId() + " " + message);
+ Log.e("EglHelper", "throwEglException tid=" + Thread.currentThread().getId() + " "
+ + message);
}
throw new RuntimeException(message);
}
+ public static void logEglErrorAsWarning(String tag, String function, int error) {
+ Log.w(tag, formatEglError(function, error));
+ }
+
+ public static String formatEglError(String function, int error) {
+ return function + " failed: " + EGLLogWrapper.getErrorString(error);
+ }
+
private WeakReference<GLSurfaceView> mGLSurfaceViewWeakRef;
EGL10 mEgl;
EGLDisplay mEglDisplay;
@@ -1334,7 +1347,7 @@
}
}
- // Have we lost the surface view surface?
+ // Have we lost the SurfaceView surface?
if ((! mHasSurface) && (! mWaitingForSurface)) {
if (LOG_SURFACE) {
Log.i("GLThread", "noticed surfaceView surface lost tid=" + getId());
@@ -1446,8 +1459,8 @@
Log.w("GLThread", "egl createSurface");
}
if (!mEglHelper.createSurface()) {
- // Couldn't create a surface. Quit quietly.
- break;
+ mSurfaceIsBad = true;
+ continue;
}
createEglSurface = false;
}
@@ -1502,12 +1515,10 @@
break;
default:
// Other errors typically mean that the current surface is bad,
- // probably because the surfaceview surface has been destroyed,
+ // probably because the SurfaceView surface has been destroyed,
// but we haven't been notified yet.
// Log the error to help developers understand why rendering stopped.
- Log.w("GLThread", "eglSwapBuffers error: " + swapError +
- ". Assume surfaceview surface is being destroyed. tid="
- + getId());
+ EglHelper.logEglErrorAsWarning("GLThread", "eglSwapBuffers", swapError);
mSurfaceIsBad = true;
break;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 564b07b..ebed522 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -456,6 +456,9 @@
mPreloadTasksRunnable = new Runnable() {
public void run() {
+ // If we set our visibility to INVISIBLE here, we avoid an extra call to
+ // onLayout later when we become visible (because onLayout is always called
+ // when going from GONE)
if (!mShowing) {
setVisibility(INVISIBLE);
refreshRecentTasksList();
@@ -562,9 +565,6 @@
if (!mShowing) {
int action = ev.getAction() & MotionEvent.ACTION_MASK;
if (action == MotionEvent.ACTION_DOWN) {
- // If we set our visibility to INVISIBLE here, we avoid an extra call to
- // onLayout later when we become visible (because onLayout is always called
- // when going from GONE)
post(mPreloadTasksRunnable);
} else if (action == MotionEvent.ACTION_CANCEL) {
setVisibility(GONE);
@@ -583,9 +583,15 @@
return false;
}
+ public void preloadRecentTasksList() {
+ if (!mShowing) {
+ mPreloadTasksRunnable.run();
+ }
+ }
+
public void clearRecentTasksList() {
// Clear memory used by screenshots
- if (mRecentTaskDescriptions != null) {
+ if (!mShowing && mRecentTaskDescriptions != null) {
mRecentTasksLoader.cancelLoadingThumbnailsAndIcons();
mRecentTaskDescriptions.clear();
mListAdapter.notifyDataSetInvalidated();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 3a06127..23222f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -19,31 +19,53 @@
import java.util.ArrayList;
import android.content.Context;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.util.Slog;
import android.view.Display;
import android.view.IWindowManager;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
+import android.view.WindowManagerImpl;
+import android.widget.LinearLayout;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.statusbar.StatusBarIconList;
import com.android.internal.statusbar.StatusBarNotification;
import com.android.systemui.SystemUI;
+import com.android.systemui.recent.RecentsPanelView;
+import com.android.systemui.recent.RecentTasksLoader;
+import com.android.systemui.recent.TaskDescription;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.tablet.StatusBarPanel;
import com.android.systemui.R;
-public abstract class BaseStatusBar extends SystemUI implements CommandQueue.Callbacks {
+public abstract class BaseStatusBar extends SystemUI implements
+ CommandQueue.Callbacks, RecentsPanelView.OnRecentsPanelVisibilityChangedListener {
static final String TAG = "StatusBar";
private static final boolean DEBUG = false;
+ protected static final int MSG_OPEN_RECENTS_PANEL = 1020;
+ protected static final int MSG_CLOSE_RECENTS_PANEL = 1021;
+ protected static final int MSG_PRELOAD_RECENT_APPS = 1022;
+ protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
+
protected CommandQueue mCommandQueue;
protected IStatusBarService mBarService;
+ protected H mHandler = createHandler();
+
+ // Recent apps
+ protected RecentsPanelView mRecentsPanel;
+ protected RecentTasksLoader mRecentTasksLoader;
// UI-specific methods
@@ -162,4 +184,121 @@
public void dismissIntruder() {
// pass
}
+
+ @Override
+ public void toggleRecentApps() {
+ int msg = (mRecentsPanel.getVisibility() == View.VISIBLE)
+ ? MSG_CLOSE_RECENTS_PANEL : MSG_OPEN_RECENTS_PANEL;
+ mHandler.removeMessages(msg);
+ mHandler.sendEmptyMessage(msg);
+ }
+
+ @Override
+ public void preloadRecentApps() {
+ int msg = MSG_PRELOAD_RECENT_APPS;
+ mHandler.removeMessages(msg);
+ mHandler.sendEmptyMessage(msg);
+ }
+
+ @Override
+ public void cancelPreloadRecentApps() {
+ int msg = MSG_CANCEL_PRELOAD_RECENT_APPS;
+ mHandler.removeMessages(msg);
+ mHandler.sendEmptyMessage(msg);
+ }
+
+ @Override
+ public void onRecentsPanelVisibilityChanged(boolean visible) {
+ }
+
+ protected abstract WindowManager.LayoutParams getRecentsLayoutParams(
+ LayoutParams layoutParams);
+
+ protected void updateRecentsPanel() {
+ // Recents Panel
+ boolean visible = false;
+ ArrayList<TaskDescription> recentTasksList = null;
+ boolean firstScreenful = false;
+ if (mRecentsPanel != null) {
+ visible = mRecentsPanel.isShowing();
+ WindowManagerImpl.getDefault().removeView(mRecentsPanel);
+ if (visible) {
+ recentTasksList = mRecentsPanel.getRecentTasksList();
+ firstScreenful = mRecentsPanel.getFirstScreenful();
+ }
+ }
+
+ // Provide RecentsPanelView with a temporary parent to allow layout params to work.
+ LinearLayout tmpRoot = new LinearLayout(mContext);
+ mRecentsPanel = (RecentsPanelView) LayoutInflater.from(mContext).inflate(
+ R.layout.status_bar_recent_panel, tmpRoot, false);
+ mRecentsPanel.setRecentTasksLoader(mRecentTasksLoader);
+ mRecentTasksLoader.setRecentsPanel(mRecentsPanel);
+ mRecentsPanel.setOnTouchListener(
+ new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL, mRecentsPanel));
+ mRecentsPanel.setVisibility(View.GONE);
+
+
+ WindowManager.LayoutParams lp = getRecentsLayoutParams(mRecentsPanel.getLayoutParams());
+
+ WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
+ mRecentsPanel.setBar(this);
+ if (visible) {
+ mRecentsPanel.show(true, false, recentTasksList, firstScreenful);
+ }
+
+ }
+
+ protected H createHandler() {
+ return new H();
+ }
+
+ protected class H extends Handler {
+ public void handleMessage(Message m) {
+ switch (m.what) {
+ case MSG_OPEN_RECENTS_PANEL:
+ if (DEBUG) Slog.d(TAG, "opening recents panel");
+ if (mRecentsPanel != null) {
+ mRecentsPanel.show(true, true);
+ }
+ break;
+ case MSG_CLOSE_RECENTS_PANEL:
+ if (DEBUG) Slog.d(TAG, "closing recents panel");
+ if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
+ mRecentsPanel.show(false, true);
+ }
+ break;
+ case MSG_PRELOAD_RECENT_APPS:
+ if (DEBUG) Slog.d(TAG, "preloading recents");
+ mRecentsPanel.preloadRecentTasksList();
+ break;
+ case MSG_CANCEL_PRELOAD_RECENT_APPS:
+ if (DEBUG) Slog.d(TAG, "cancel preloading recents");
+ mRecentsPanel.clearRecentTasksList();
+ break;
+ }
+ }
+ }
+
+ public class TouchOutsideListener implements View.OnTouchListener {
+ private int mMsg;
+ private StatusBarPanel mPanel;
+
+ public TouchOutsideListener(int msg, StatusBarPanel panel) {
+ mMsg = msg;
+ mPanel = panel;
+ }
+
+ public boolean onTouch(View v, MotionEvent ev) {
+ final int action = ev.getAction();
+ if (action == MotionEvent.ACTION_OUTSIDE
+ || (action == MotionEvent.ACTION_DOWN
+ && !mPanel.isInContentArea((int)ev.getX(), (int)ev.getY()))) {
+ mHandler.removeMessages(mMsg);
+ mHandler.sendEmptyMessage(mMsg);
+ return true;
+ }
+ return false;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index f8dfa8f..37ab58a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -61,8 +61,10 @@
private static final int MSG_SET_HARD_KEYBOARD_STATUS = 10 << MSG_SHIFT;
private static final int MSG_TOGGLE_RECENT_APPS = 11 << MSG_SHIFT;
+ private static final int MSG_PRELOAD_RECENT_APPS = 12 << MSG_SHIFT;
+ private static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 13 << MSG_SHIFT;
- private static final int MSG_SET_NAVIGATION_ICON_HINTS = 13 << MSG_SHIFT;
+ private static final int MSG_SET_NAVIGATION_ICON_HINTS = 14 << MSG_SHIFT;
private StatusBarIconList mList;
private Callbacks mCallbacks;
@@ -92,6 +94,8 @@
public void setImeWindowStatus(IBinder token, int vis, int backDisposition);
public void setHardKeyboardStatus(boolean available, boolean enabled);
public void toggleRecentApps();
+ public void preloadRecentApps();
+ public void cancelPreloadRecentApps();
public void setNavigationIconHints(int hints);
}
@@ -199,6 +203,20 @@
}
}
+ public void preloadRecentApps() {
+ synchronized (mList) {
+ mHandler.removeMessages(MSG_PRELOAD_RECENT_APPS);
+ mHandler.obtainMessage(MSG_PRELOAD_RECENT_APPS, 0, 0, null).sendToTarget();
+ }
+ }
+
+ public void cancelPreloadRecentApps() {
+ synchronized (mList) {
+ mHandler.removeMessages(MSG_CANCEL_PRELOAD_RECENT_APPS);
+ mHandler.obtainMessage(MSG_CANCEL_PRELOAD_RECENT_APPS, 0, 0, null).sendToTarget();
+ }
+ }
+
public void setNavigationIconHints(int hints) {
synchronized (mList) {
mHandler.removeMessages(MSG_SET_NAVIGATION_ICON_HINTS);
@@ -275,6 +293,12 @@
case MSG_TOGGLE_RECENT_APPS:
mCallbacks.toggleRecentApps();
break;
+ case MSG_PRELOAD_RECENT_APPS:
+ mCallbacks.preloadRecentApps();
+ break;
+ case MSG_CANCEL_PRELOAD_RECENT_APPS:
+ mCallbacks.cancelPreloadRecentApps();
+ break;
case MSG_SET_NAVIGATION_ICON_HINTS:
mCallbacks.setNavigationIconHints(msg.arg1);
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 023b21f..7c679b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -30,24 +30,22 @@
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
import android.content.res.Configuration;
-import android.inputmethodservice.InputMethodService;
+import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
+import android.inputmethodservice.InputMethodService;
import android.os.Build;
import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.Handler;
import android.os.Message;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.DisplayMetrics;
-import android.util.Slog;
import android.util.Log;
+import android.util.Slog;
import android.view.Display;
import android.view.Gravity;
import android.view.IWindowManager;
@@ -76,19 +74,16 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.statusbar.StatusBarNotification;
-
import com.android.systemui.R;
import com.android.systemui.SwipeHelper;
import com.android.systemui.recent.RecentTasksLoader;
-import com.android.systemui.recent.RecentsPanelView;
-import com.android.systemui.recent.TaskDescription;
-import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.BaseStatusBar;
-import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.SignalClusterView;
-import com.android.systemui.statusbar.policy.DateView;
+import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.IntruderAlertView;
+import com.android.systemui.statusbar.policy.DateView;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NotificationRowLayout;
@@ -116,8 +111,7 @@
private static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
private static final int MSG_SHOW_INTRUDER = 1002;
private static final int MSG_HIDE_INTRUDER = 1003;
- private static final int MSG_OPEN_RECENTS_PANEL = 1020;
- private static final int MSG_CLOSE_RECENTS_PANEL = 1021;
+ // 1020-1030 reserved for BaseStatusBar
// will likely move to a resource or other tunable param at some point
private static final int INTRUDER_ALERT_DECAY_MS = 0; // disabled, was 10000;
@@ -152,7 +146,6 @@
PhoneStatusBarView mStatusBarView;
int mPixelFormat;
- H mHandler = new H();
Object mQueueLock = new Object();
// icons
@@ -202,10 +195,6 @@
private View mTickerView;
private boolean mTicking;
- // Recent apps
- private RecentsPanelView mRecentsPanel;
- private RecentTasksLoader mRecentTasksLoader;
-
// Tracking finger for opening/closing.
int mEdgeBorder; // corresponds to R.dimen.status_bar_edge_ignore
boolean mTracking;
@@ -382,6 +371,7 @@
return sb;
}
+ @Override
protected WindowManager.LayoutParams getRecentsLayoutParams(LayoutParams layoutParams) {
boolean opaque = false;
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
@@ -406,42 +396,13 @@
return lp;
}
+ @Override
protected void updateRecentsPanel() {
- // Recents Panel
- boolean visible = false;
- ArrayList<TaskDescription> recentTasksList = null;
- boolean firstScreenful = false;
- if (mRecentsPanel != null) {
- visible = mRecentsPanel.isShowing();
- WindowManagerImpl.getDefault().removeView(mRecentsPanel);
- if (visible) {
- recentTasksList = mRecentsPanel.getRecentTasksList();
- firstScreenful = mRecentsPanel.getFirstScreenful();
- }
- }
-
- // Provide RecentsPanelView with a temporary parent to allow layout params to work.
- LinearLayout tmpRoot = new LinearLayout(mContext);
- mRecentsPanel = (RecentsPanelView) LayoutInflater.from(mContext).inflate(
- R.layout.status_bar_recent_panel, tmpRoot, false);
- mRecentsPanel.setRecentTasksLoader(mRecentTasksLoader);
- mRecentTasksLoader.setRecentsPanel(mRecentsPanel);
- mRecentsPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL,
- mRecentsPanel));
- mRecentsPanel.setVisibility(View.GONE);
-
+ super.updateRecentsPanel();
// Make .03 alpha the minimum so you always see the item a bit-- slightly below
// .03, the item disappears entirely (as if alpha = 0) and that discontinuity looks
// a bit jarring
mRecentsPanel.setMinSwipeAlpha(0.03f);
- WindowManager.LayoutParams lp = getRecentsLayoutParams(mRecentsPanel.getLayoutParams());
-
- WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
- mRecentsPanel.setBar(this);
- if (visible) {
- mRecentsPanel.show(true, false, recentTasksList, firstScreenful);
- }
-
}
protected int getStatusBarGravity() {
@@ -1076,11 +1037,17 @@
}
}
+ @Override
+ protected BaseStatusBar.H createHandler() {
+ return new PhoneStatusBar.H();
+ }
+
/**
* All changes to the status bar and notifications funnel through here and are batched.
*/
- private class H extends Handler {
+ private class H extends BaseStatusBar.H {
public void handleMessage(Message m) {
+ super.handleMessage(m);
switch (m.what) {
case MSG_ANIMATE:
doAnimation();
@@ -1101,18 +1068,6 @@
setIntruderAlertVisibility(false);
mCurrentlyIntrudingNotification = null;
break;
- case MSG_OPEN_RECENTS_PANEL:
- if (DEBUG) Slog.d(TAG, "opening recents panel");
- if (mRecentsPanel != null) {
- mRecentsPanel.show(true, true);
- }
- break;
- case MSG_CLOSE_RECENTS_PANEL:
- if (DEBUG) Slog.d(TAG, "closing recents panel");
- if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
- mRecentsPanel.show(false, true);
- }
- break;
}
}
}
@@ -2041,13 +1996,6 @@
}
}
- public void toggleRecentApps() {
- int msg = (mRecentsPanel.getVisibility() == View.VISIBLE)
- ? MSG_CLOSE_RECENTS_PANEL : MSG_OPEN_RECENTS_PANEL;
- mHandler.removeMessages(msg);
- mHandler.sendEmptyMessage(msg);
- }
-
/**
* The LEDs are turned o)ff when the notification panel is shown, even just a little bit.
* This was added last-minute and is inconsistent with the way the rest of the notifications
@@ -2335,27 +2283,5 @@
vibrate();
}
};
-
- public class TouchOutsideListener implements View.OnTouchListener {
- private int mMsg;
- private RecentsPanelView mPanel;
-
- public TouchOutsideListener(int msg, RecentsPanelView panel) {
- mMsg = msg;
- mPanel = panel;
- }
-
- public boolean onTouch(View v, MotionEvent ev) {
- final int action = ev.getAction();
- if (action == MotionEvent.ACTION_OUTSIDE
- || (action == MotionEvent.ACTION_DOWN
- && !mPanel.isInContentArea((int)ev.getX(), (int)ev.getY()))) {
- mHandler.removeMessages(mMsg);
- mHandler.sendEmptyMessage(mMsg);
- return true;
- }
- return false;
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 9d5faa4..2491d18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -36,21 +36,19 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.inputmethodservice.InputMethodService;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
+import android.inputmethodservice.InputMethodService;
import android.os.Build;
-import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.text.TextUtils;
import android.util.Slog;
-import android.view.accessibility.AccessibilityEvent;
import android.view.Display;
import android.view.Gravity;
import android.view.IWindowManager;
@@ -62,8 +60,10 @@
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
+import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RemoteViews;
@@ -78,7 +78,6 @@
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.SignalClusterView;
-import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
@@ -100,8 +99,7 @@
public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
public static final int MSG_OPEN_NOTIFICATION_PEEK = 1002;
public static final int MSG_CLOSE_NOTIFICATION_PEEK = 1003;
- public static final int MSG_OPEN_RECENTS_PANEL = 1020;
- public static final int MSG_CLOSE_RECENTS_PANEL = 1021;
+ // 1020-1029 reserved for BaseStatusBar
public static final int MSG_SHOW_CHROME = 1030;
public static final int MSG_HIDE_CHROME = 1031;
public static final int MSG_OPEN_INPUT_METHODS_PANEL = 1040;
@@ -127,8 +125,6 @@
int mMenuNavIconWidth = -1;
private int mMaxNotificationIcons = 5;
- H mHandler = new H();
-
IWindowManager mWindowManager;
// tracking all current notifications
@@ -189,8 +185,6 @@
// for disabling the status bar
int mDisabled = 0;
- private RecentsPanelView mRecentsPanel;
- private RecentTasksLoader mRecentTasksLoader;
private InputMethodsPanel mInputMethodsPanel;
private CompatModePanel mCompatModePanel;
@@ -348,33 +342,7 @@
// Recents Panel
mRecentTasksLoader = new RecentTasksLoader(context);
- mRecentsPanel = (RecentsPanelView) View.inflate(context,
- R.layout.status_bar_recent_panel, null);
- mRecentsPanel.setVisibility(View.GONE);
- mRecentsPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL,
- mRecentsPanel));
- mRecentsPanel.setOnVisibilityChangedListener(this);
- mRecentsPanel.setRecentTasksLoader(mRecentTasksLoader);
- mRecentTasksLoader.setRecentsPanel(mRecentsPanel);
-
- lp = new WindowManager.LayoutParams(
- (int) res.getDimension(R.dimen.status_bar_recents_width),
- ViewGroup.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
- | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
- PixelFormat.TRANSLUCENT);
- lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
- lp.setTitle("RecentsPanel");
- lp.windowAnimations = R.style.Animation_RecentPanel;
- lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
- | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
-
- WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
- mRecentsPanel.setBar(this);
- mRecentsPanel.setStatusBarView(mStatusBarView);
+ updateRecentsPanel();
// Input methods Panel
mInputMethodsPanel = (InputMethodsPanel) View.inflate(context,
@@ -680,6 +648,31 @@
return sb;
}
+ @Override
+ protected WindowManager.LayoutParams getRecentsLayoutParams(LayoutParams layoutParams) {
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ (int) mContext.getResources().getDimension(R.dimen.status_bar_recents_width),
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+ | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
+ PixelFormat.TRANSLUCENT);
+ lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
+ lp.setTitle("RecentsPanel");
+ lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
+ lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
+ | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
+
+ return lp;
+ }
+
+ protected void updateRecentsPanel() {
+ super.updateRecentsPanel();
+ mRecentsPanel.setStatusBarView(mStatusBarView);
+ }
+
public int getStatusBarHeight() {
return mHeightReceiver.getHeight();
}
@@ -702,8 +695,14 @@
}
}
- private class H extends Handler {
+ @Override
+ protected BaseStatusBar.H createHandler() {
+ return new TabletStatusBar.H();
+ }
+
+ private class H extends BaseStatusBar.H {
public void handleMessage(Message m) {
+ super.handleMessage(m);
switch (m.what) {
case MSG_OPEN_NOTIFICATION_PEEK:
if (DEBUG) Slog.d(TAG, "opening notification peek window; arg=" + m.arg1);
@@ -798,18 +797,6 @@
mNotificationArea.setVisibility(View.VISIBLE);
}
break;
- case MSG_OPEN_RECENTS_PANEL:
- if (DEBUG) Slog.d(TAG, "opening recents panel");
- if (mRecentsPanel != null) {
- mRecentsPanel.show(true, true);
- }
- break;
- case MSG_CLOSE_RECENTS_PANEL:
- if (DEBUG) Slog.d(TAG, "closing recents panel");
- if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
- mRecentsPanel.show(false, true);
- }
- break;
case MSG_OPEN_INPUT_METHODS_PANEL:
if (DEBUG) Slog.d(TAG, "opening input methods panel");
if (mInputMethodsPanel != null) mInputMethodsPanel.openPanel();
@@ -1921,13 +1908,6 @@
visibilityChanged(false);
}
- public void toggleRecentApps() {
- int msg = (mRecentsPanel.getVisibility() == View.VISIBLE)
- ? MSG_CLOSE_RECENTS_PANEL : MSG_OPEN_RECENTS_PANEL;
- mHandler.removeMessages(msg);
- mHandler.sendEmptyMessage(msg);
- }
-
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
@@ -1953,28 +1933,6 @@
}
};
- public class TouchOutsideListener implements View.OnTouchListener {
- private int mMsg;
- private StatusBarPanel mPanel;
-
- public TouchOutsideListener(int msg, StatusBarPanel panel) {
- mMsg = msg;
- mPanel = panel;
- }
-
- public boolean onTouch(View v, MotionEvent ev) {
- final int action = ev.getAction();
- if (action == MotionEvent.ACTION_OUTSIDE
- || (action == MotionEvent.ACTION_DOWN
- && !mPanel.isInContentArea((int)ev.getX(), (int)ev.getY()))) {
- mHandler.removeMessages(mMsg);
- mHandler.sendEmptyMessage(mMsg);
- return true;
- }
- return false;
- }
- }
-
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.print("mDisabled=0x");
pw.println(Integer.toHexString(mDisabled));
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 92c94a9..6214086 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -430,6 +430,7 @@
boolean mHideLockScreen;
boolean mDismissKeyguard;
boolean mHomePressed;
+ boolean mHomeLongPressed;
Intent mHomeIntent;
Intent mCarDockIntent;
Intent mDeskDockIntent;
@@ -744,7 +745,7 @@
// Eat the longpress so it won't dismiss the recent apps dialog when
// the user lets go of the home key
- mHomePressed = false;
+ mHomeLongPressed = true;
}
if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
@@ -1619,33 +1620,45 @@
// it handle it, because that gives us the correct 5 second
// timeout.
if (keyCode == KeyEvent.KEYCODE_HOME) {
+
// If we have released the home key, and didn't do anything else
// while it was pressed, then it is time to go home!
- if (mHomePressed && !down) {
+ if (!down) {
+ final boolean homeWasLongPressed = mHomeLongPressed;
mHomePressed = false;
- if (!canceled) {
- // If an incoming call is ringing, HOME is totally disabled.
- // (The user is already on the InCallScreen at this point,
- // and his ONLY options are to answer or reject the call.)
- boolean incomingRinging = false;
+ mHomeLongPressed = false;
+ if (!homeWasLongPressed) {
try {
- ITelephony telephonyService = getTelephonyService();
- if (telephonyService != null) {
- incomingRinging = telephonyService.isRinging();
- }
- } catch (RemoteException ex) {
- Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
+ mStatusBarService.cancelPreloadRecentApps();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "RemoteException when showing recent apps", e);
}
- if (incomingRinging) {
- Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
+ mHomePressed = false;
+ if (!canceled) {
+ // If an incoming call is ringing, HOME is totally disabled.
+ // (The user is already on the InCallScreen at this point,
+ // and his ONLY options are to answer or reject the call.)
+ boolean incomingRinging = false;
+ try {
+ ITelephony telephonyService = getTelephonyService();
+ if (telephonyService != null) {
+ incomingRinging = telephonyService.isRinging();
+ }
+ } catch (RemoteException ex) {
+ Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
+ }
+
+ if (incomingRinging) {
+ Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
+ } else {
+ launchHomeFromHotKey();
+ }
} else {
- launchHomeFromHotKey();
+ Log.i(TAG, "Ignoring HOME; event canceled.");
}
- } else {
- Log.i(TAG, "Ignoring HOME; event canceled.");
+ return -1;
}
- return -1;
}
// If a system window has focus, then it doesn't make sense
@@ -1666,8 +1679,14 @@
}
}
}
-
if (down) {
+ if (!mHomePressed) {
+ try {
+ mStatusBarService.preloadRecentApps();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "RemoteException when preloading recent apps", e);
+ }
+ }
if (repeatCount == 0) {
mHomePressed = true;
} else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index a9ff6c5..6452be7 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -352,6 +352,24 @@
}
}
+ @Override
+ public void preloadRecentApps() {
+ if (mBar != null) {
+ try {
+ mBar.preloadRecentApps();
+ } catch (RemoteException ex) {}
+ }
+ }
+
+ @Override
+ public void cancelPreloadRecentApps() {
+ if (mBar != null) {
+ try {
+ mBar.cancelPreloadRecentApps();
+ } catch (RemoteException ex) {}
+ }
+ }
+
private void enforceStatusBar() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR,
"StatusBarManagerService");
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index cecc0a0..3d60c6b 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -600,7 +600,6 @@
private boolean mSyswin = false;
private float mScreenBrightness = -1;
private float mButtonBrightness = -1;
- private boolean mUpdateRotation = false;
}
LayoutAndSurfaceFields mInnerFields = new LayoutAndSurfaceFields();
@@ -8575,17 +8574,17 @@
mTurnOnScreen = false;
}
- if (mInnerFields.mUpdateRotation) {
+ if (mAnimator.mUpdateRotation) {
if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
if (updateRotationUncheckedLocked(false)) {
mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
} else {
- mInnerFields.mUpdateRotation = false;
+ mAnimator.mUpdateRotation = false;
}
}
if (mInnerFields.mOrientationChangeComplete && !mLayoutNeeded &&
- !mInnerFields.mUpdateRotation) {
+ !mAnimator.mUpdateRotation) {
checkDrawnWindowsLocked();
}
@@ -8924,11 +8923,11 @@
mAnimator.mScreenRotationAnimation.kill();
mAnimator.mScreenRotationAnimation = null;
}
- if (mAnimator.mScreenRotationAnimation == null) {
- mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
- mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight,
- mDisplay.getRotation());
- }
+
+ mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
+ mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight,
+ mDisplay.getRotation());
+
if (!mAnimator.mScreenRotationAnimation.hasScreenshot()) {
Surface.freezeDisplay(0);
}
@@ -8943,6 +8942,10 @@
}
if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) {
+ if (DEBUG_ORIENTATION) Slog.d(TAG,
+ "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
+ + ", mAppsFreezingScreen=" + mAppsFreezingScreen
+ + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen);
return;
}
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 789bfaa..d22b17c 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -24,8 +24,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import com.android.server.wm.WindowManagerService.H;
-
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Matrix;
@@ -40,15 +38,10 @@
import android.view.IApplicationToken;
import android.view.IWindow;
import android.view.InputChannel;
-import android.view.Surface;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.WindowManagerPolicy;
-import android.view.WindowManager.LayoutParams;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Transformation;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -57,6 +50,8 @@
* A window in the window manager.
*/
final class WindowState implements WindowManagerPolicy.WindowState {
+ static final String TAG = "WindowState";
+
static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY;
static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS;
static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
@@ -276,7 +271,7 @@
mSeq = seq;
mEnforceSizeCompat = (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
if (WindowManagerService.localLOGV) Slog.v(
- WindowManagerService.TAG, "Window " + this + " client=" + c.asBinder()
+ TAG, "Window " + this + " client=" + c.asBinder()
+ " token=" + token + " (" + mAttrs.token + ")");
try {
c.asBinder().linkToDeath(deathRecipient, 0);
@@ -304,7 +299,7 @@
+ WindowManagerService.TYPE_LAYER_OFFSET;
mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
mAttachedWindow = attachedWindow;
- if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Adding " + this + " to " + mAttachedWindow);
+ if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + mAttachedWindow);
mAttachedWindow.mChildWindows.add(this);
mLayoutAttached = mAttrs.type !=
WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -358,7 +353,7 @@
void attach() {
if (WindowManagerService.localLOGV) Slog.v(
- WindowManagerService.TAG, "Attaching " + this + " token=" + mToken
+ TAG, "Attaching " + this + " token=" + mToken
+ ", list=" + mToken.windows);
mSession.windowAddedLocked();
}
@@ -496,7 +491,7 @@
if (WindowManagerService.localLOGV) {
//if ("com.google.android.youtube".equals(mAttrs.packageName)
// && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
- Slog.v(WindowManagerService.TAG, "Resolving (mRequestedWidth="
+ Slog.v(TAG, "Resolving (mRequestedWidth="
+ mRequestedWidth + ", mRequestedheight="
+ mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
+ "): frame=" + mFrame.toShortString()
@@ -600,10 +595,11 @@
return mAppToken != null ? mAppToken.firstWindowDrawn : false;
}
+ // TODO(cmautner): Move to WindowStateAnimator
boolean finishDrawingLocked() {
if (mDrawPending) {
if (SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION) Slog.v(
- WindowManagerService.TAG, "finishDrawingLocked: " + this + " in "
+ TAG, "finishDrawingLocked: " + this + " in "
+ mWinAnimator.mSurface);
mCommitDrawPending = true;
mDrawPending = false;
@@ -612,6 +608,7 @@
return false;
}
+ // TODO(cmautner): Move to WindowStateAnimator
// This must be called while inside a transaction.
boolean commitFinishDrawingLocked(long currentTime) {
//Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
@@ -820,7 +817,7 @@
disposeInputChannel();
if (mAttachedWindow != null) {
- if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Removing " + this + " from " + mAttachedWindow);
+ if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mAttachedWindow);
mAttachedWindow.mChildWindows.remove(this);
}
mWinAnimator.destroyDeferredSurfaceLocked();
@@ -859,7 +856,7 @@
try {
synchronized(mService.mWindowMap) {
WindowState win = mService.windowForClientLocked(mSession, mClient, false);
- Slog.i(WindowManagerService.TAG, "WIN DEATH: " + win);
+ Slog.i(TAG, "WIN DEATH: " + win);
if (win != null) {
mService.removeWindowLocked(mSession, win);
}
@@ -891,9 +888,9 @@
// Already showing.
return false;
}
- if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility true: " + this);
+ if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
if (doAnimation) {
- if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "doAnimation: mPolicyVisibility="
+ if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
+ mPolicyVisibility + " mAnimation=" + mWinAnimator.mAnimation);
if (!mService.okToDisplay()) {
doAnimation = false;
@@ -940,7 +937,7 @@
if (doAnimation) {
mPolicyVisibilityAfterAnim = false;
} else {
- if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility false: " + this);
+ if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
mPolicyVisibilityAfterAnim = false;
mPolicyVisibility = false;
// Window is no longer visible -- make sure if we were waiting
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 789e74b..d1539ba 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -554,7 +554,7 @@
mPendingDestroySurface.destroy();
}
} catch (RuntimeException e) {
- Slog.w(WindowManagerService.TAG, "Exception thrown when destroying Window "
+ Slog.w(TAG, "Exception thrown when destroying Window "
+ this + " surface " + mPendingDestroySurface
+ " session " + mSession + ": " + e.toString());
}
@@ -705,6 +705,7 @@
mDsDy = 0;
mDtDy = mWin.mGlobalScale;
}
+
public void prepareSurfaceLocked(final boolean recoveringMemory) {
final WindowState w = mWin;
if (mSurface == null) {
@@ -892,7 +893,7 @@
e = new RuntimeException();
e.fillInStackTrace();
}
- Slog.v(WindowManagerService.TAG, "performShow on " + this
+ Slog.v(TAG, "performShow on " + this
+ ": readyToShow=" + mWin.mReadyToShow + " readyForDisplay="
+ mWin.isReadyForDisplay()
+ " starting=" + (mWin.mAttrs.type == TYPE_APPLICATION_STARTING), e);
@@ -900,7 +901,7 @@
if (mWin.mReadyToShow && mWin.isReadyForDisplay()) {
if (SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION)
WindowManagerService.logSurface(mWin, "SHOW (performShowLocked)", null);
- if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Showing " + this
+ if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
+ " during animation: policyVis=" + mWin.mPolicyVisibility
+ " attHidden=" + mWin.mAttachedHidden
+ " tok.hiddenRequested="
@@ -947,7 +948,7 @@
if (mWin.mAppToken.startingData != null) {
if (WindowManagerService.DEBUG_STARTING_WINDOW ||
- WindowManagerService.DEBUG_ANIM) Slog.v(WindowManagerService.TAG,
+ WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
"Finish starting " + mWin.mToken
+ ": first real window is shown, no animation");
// If this initial window is animating, stop it -- we
@@ -1059,7 +1060,7 @@
a = mService.loadAnimation(mWin.mAttrs, attr);
}
}
- if (WindowManagerService.DEBUG_ANIM) Slog.v(WindowManagerService.TAG,
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
"applyAnimation: win=" + this
+ " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
+ " mAnimation=" + mAnimation
@@ -1071,7 +1072,7 @@
e = new RuntimeException();
e.fillInStackTrace();
}
- Slog.v(WindowManagerService.TAG, "Loaded animation " + a + " for " + this, e);
+ Slog.v(TAG, "Loaded animation " + a + " for " + this, e);
}
setAnimation(a);
mAnimationIsEntrance = isEntrance;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyCapabilities.java b/telephony/java/com/android/internal/telephony/TelephonyCapabilities.java
new file mode 100644
index 0000000..061a6cb
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/TelephonyCapabilities.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.util.Log;
+
+import com.android.internal.telephony.Phone;
+
+/**
+ * Utilities that check if the phone supports specified capabilities.
+ */
+public class TelephonyCapabilities {
+ private static final String LOG_TAG = "TelephonyCapabilities";
+
+ /** This class is never instantiated. */
+ private TelephonyCapabilities() {
+ }
+
+ /**
+ * Return true if the current phone supports ECM ("Emergency Callback
+ * Mode"), which is a feature where the device goes into a special
+ * state for a short period of time after making an outgoing emergency
+ * call.
+ *
+ * (On current devices, that state lasts 5 minutes. It prevents data
+ * usage by other apps, to avoid conflicts with any possible incoming
+ * calls. It also puts up a notification in the status bar, showing a
+ * countdown while ECM is active, and allowing the user to exit ECM.)
+ *
+ * Currently this is assumed to be true for CDMA phones, and false
+ * otherwise.
+ */
+ public static boolean supportsEcm(Phone phone) {
+ return (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
+ }
+
+ /**
+ * Return true if the current phone supports Over The Air Service
+ * Provisioning (OTASP)
+ *
+ * Currently this is assumed to be true for CDMA phones, and false
+ * otherwise.
+ *
+ * TODO: Watch out: this is also highly carrier-specific, since the
+ * OTASP procedure is different from one carrier to the next, *and* the
+ * different carriers may want very different onscreen UI as well.
+ * The procedure may even be different for different devices with the
+ * same carrier.
+ *
+ * So we eventually will need a much more flexible, pluggable design.
+ * This method here is just a placeholder to reduce hardcoded
+ * "if (CDMA)" checks sprinkled throughout the phone app.
+ */
+ public static boolean supportsOtasp(Phone phone) {
+ return (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
+ }
+
+ /**
+ * Return true if the current phone can retrieve the voice message count.
+ *
+ * Currently this is assumed to be true on CDMA phones and false otherwise.
+ */
+ public static boolean supportsVoiceMessageCount(Phone phone) {
+ return (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
+ }
+
+ /**
+ * Return true if this phone allows the user to select which
+ * network to use.
+ *
+ * Currently this is assumed to be true only on GSM phones.
+ *
+ * TODO: Should CDMA phones allow this as well?
+ */
+ public static boolean supportsNetworkSelection(Phone phone) {
+ return (phone.getPhoneType() == Phone.PHONE_TYPE_GSM);
+ }
+
+ /**
+ * Returns a resource ID for a label to use when displaying the
+ * "device id" of the current device. (This is currently used as the
+ * title of the "device id" dialog.)
+ *
+ * This is specific to the device's telephony technology: the device
+ * id is called "IMEI" on GSM phones and "MEID" on CDMA phones.
+ */
+ public static int getDeviceIdLabel(Phone phone) {
+ if (phone.getPhoneType() == Phone.PHONE_TYPE_GSM) {
+ return com.android.internal.R.string.imei;
+ } else if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+ return com.android.internal.R.string.meid;
+ } else {
+ Log.w(LOG_TAG, "getDeviceIdLabel: no known label for phone "
+ + phone.getPhoneName());
+ return 0;
+ }
+ }
+
+ /**
+ * Return true if the current phone supports the ability to explicitly
+ * manage the state of a conference call (i.e. view the participants,
+ * and hangup or separate individual callers.)
+ *
+ * The in-call screen's "Manage conference" UI is available only on
+ * devices that support this feature.
+ *
+ * Currently this is assumed to be true on GSM phones and false otherwise.
+ */
+ public static boolean supportsConferenceCallManagement(Phone phone) {
+ return ((phone.getPhoneType() == Phone.PHONE_TYPE_GSM)
+ || (phone.getPhoneType() == Phone.PHONE_TYPE_SIP));
+ }
+
+ /**
+ * Return true if the current phone supports explicit "Hold" and
+ * "Unhold" actions for an active call. (If so, the in-call UI will
+ * provide onscreen "Hold" / "Unhold" buttons.)
+ *
+ * Currently this is assumed to be true on GSM phones and false
+ * otherwise. (In particular, CDMA has no concept of "putting a call
+ * on hold.")
+ */
+ public static boolean supportsHoldAndUnhold(Phone phone) {
+ return ((phone.getPhoneType() == Phone.PHONE_TYPE_GSM)
+ || (phone.getPhoneType() == Phone.PHONE_TYPE_SIP));
+ }
+
+ /**
+ * Return true if the current phone supports distinct "Answer & Hold"
+ * and "Answer & End" behaviors in the call-waiting scenario. If so,
+ * the in-call UI may provide separate buttons or menu items for these
+ * two actions.
+ *
+ * Currently this is assumed to be true on GSM phones and false
+ * otherwise. (In particular, CDMA has no concept of explicitly
+ * managing the background call, or "putting a call on hold.")
+ *
+ * TODO: It might be better to expose this capability in a more
+ * generic form, like maybe "supportsExplicitMultipleLineManagement()"
+ * rather than focusing specifically on call-waiting behavior.
+ */
+ public static boolean supportsAnswerAndHold(Phone phone) {
+ return ((phone.getPhoneType() == Phone.PHONE_TYPE_GSM)
+ || (phone.getPhoneType() == Phone.PHONE_TYPE_SIP));
+ }
+}