diff options
46 files changed, 817 insertions, 339 deletions
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java index 6074a0c..9e4ec3c 100644 --- a/core/java/android/webkit/BrowserFrame.java +++ b/core/java/android/webkit/BrowserFrame.java @@ -89,8 +89,19 @@ class BrowserFrame extends Handler { // Is this frame the main frame? private boolean mIsMainFrame; + // Javascript interface object + private class JSObject { + Object object; + boolean requireAnnotation; + + public JSObject(Object object, boolean requireAnnotation) { + this.object = object; + this.requireAnnotation = requireAnnotation; + } + } + // Attached Javascript interfaces - private Map<String, Object> mJavaScriptObjects; + private Map<String, JSObject> mJavaScriptObjects; private Set<Object> mRemovedJavaScriptObjects; // Key store handler when Chromium HTTP stack is used. @@ -234,10 +245,8 @@ class BrowserFrame extends Handler { } sConfigCallback.addHandler(this); - mJavaScriptObjects = javascriptInterfaces; - if (mJavaScriptObjects == null) { - mJavaScriptObjects = new HashMap<String, Object>(); - } + mJavaScriptObjects = new HashMap<String, JSObject>(); + addJavaScriptObjects(javascriptInterfaces); mRemovedJavaScriptObjects = new HashSet<Object>(); mSettings = settings; @@ -590,15 +599,36 @@ class BrowserFrame extends Handler { Iterator<String> iter = mJavaScriptObjects.keySet().iterator(); while (iter.hasNext()) { String interfaceName = iter.next(); - Object object = mJavaScriptObjects.get(interfaceName); - if (object != null) { + JSObject jsobject = mJavaScriptObjects.get(interfaceName); + if (jsobject != null && jsobject.object != null) { nativeAddJavascriptInterface(nativeFramePointer, - mJavaScriptObjects.get(interfaceName), interfaceName); + jsobject.object, interfaceName, jsobject.requireAnnotation); } } mRemovedJavaScriptObjects.clear(); } + /* + * Add javascript objects to the internal list of objects. The default behavior + * is to allow access to inherited methods (no annotation needed). This is only + * used when js objects are passed through a constructor (via a hidden constructor). + * + * @TODO change the default behavior to be compatible with the public addjavascriptinterface + */ + private void addJavaScriptObjects(Map<String, Object> javascriptInterfaces) { + + // TODO in a separate CL provide logic to enable annotations for API level JB_MR1 and above. + if (javascriptInterfaces == null) return; + Iterator<String> iter = javascriptInterfaces.keySet().iterator(); + while (iter.hasNext()) { + String interfaceName = iter.next(); + Object object = javascriptInterfaces.get(interfaceName); + if (object != null) { + mJavaScriptObjects.put(interfaceName, new JSObject(object, false)); + } + } + } + /** * This method is called by WebCore to check whether application * wants to hijack url loading @@ -616,11 +646,11 @@ class BrowserFrame extends Handler { } } - public void addJavascriptInterface(Object obj, String interfaceName) { + public void addJavascriptInterface(Object obj, String interfaceName, + boolean requireAnnotation) { assert obj != null; removeJavascriptInterface(interfaceName); - - mJavaScriptObjects.put(interfaceName, obj); + mJavaScriptObjects.put(interfaceName, new JSObject(obj, requireAnnotation)); } public void removeJavascriptInterface(String interfaceName) { @@ -1245,7 +1275,7 @@ class BrowserFrame extends Handler { * Add a javascript interface to the main frame. */ private native void nativeAddJavascriptInterface(int nativeFramePointer, - Object obj, String interfaceName); + Object obj, String interfaceName, boolean requireAnnotation); public native void clearCache(); diff --git a/core/java/android/webkit/JavascriptInterface.java b/core/java/android/webkit/JavascriptInterface.java new file mode 100644 index 0000000..3f1ed12 --- /dev/null +++ b/core/java/android/webkit/JavascriptInterface.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.webkit; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation that allows exposing methods to JavaScript. Starting from API level + * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} and above, only methods explicitly + * marked with this annotation are available to the Javascript code. See + * {@link android.webkit.Webview#addJavaScriptInterface} for more information about it. + * + * @hide + */ +@SuppressWarnings("javadoc") +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +public @interface JavascriptInterface { +}
\ No newline at end of file diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 82635d7..9d6d929 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -26,6 +26,7 @@ import android.graphics.Picture; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.net.http.SslCertificate; +import android.os.Build; import android.os.Bundle; import android.os.Looper; import android.os.Message; @@ -1507,6 +1508,9 @@ public class WebView extends AbsoluteLayout public void addJavascriptInterface(Object object, String name) { checkThread(); mProvider.addJavascriptInterface(object, name); + // TODO in a separate CL provide logic to enable annotations for API level JB_MR1 and above. Don't forget to + // update the doc, set a link to annotation and unhide the annotation. + // also describe that fields of java objects are not accessible from JS. } /** diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java index 494a28c..351c4f3 100644 --- a/core/java/android/webkit/WebViewClassic.java +++ b/core/java/android/webkit/WebViewClassic.java @@ -4114,12 +4114,15 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc */ @Override public void addJavascriptInterface(Object object, String name) { + if (object == null) { return; } WebViewCore.JSInterfaceData arg = new WebViewCore.JSInterfaceData(); + // TODO in a separate CL provide logic to enable annotations for API level JB_MR1 and above. arg.mObject = object; arg.mInterfaceName = name; + arg.mRequireAnnotation = false; mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg); } diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 59036e7..2d834ff 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -824,6 +824,7 @@ public final class WebViewCore { static class JSInterfaceData { Object mObject; String mInterfaceName; + boolean mRequireAnnotation; } static class JSKeyData { @@ -1489,7 +1490,7 @@ public final class WebViewCore { case ADD_JS_INTERFACE: JSInterfaceData jsData = (JSInterfaceData) msg.obj; mBrowserFrame.addJavascriptInterface(jsData.mObject, - jsData.mInterfaceName); + jsData.mInterfaceName, jsData.mRequireAnnotation); break; case REMOVE_JS_INTERFACE: diff --git a/core/res/res/layout-land/keyguard_host_view.xml b/core/res/res/layout-land/keyguard_host_view.xml index 0028a54..8e7c232 100644 --- a/core/res/res/layout-land/keyguard_host_view.xml +++ b/core/res/res/layout-land/keyguard_host_view.xml @@ -38,7 +38,7 @@ </com.android.internal.policy.impl.keyguard.KeyguardWidgetPager> - <ViewFlipper + <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper android:id="@+id/view_flipper" android:layout_width="0dip" android:layout_height="match_parent" @@ -48,6 +48,6 @@ <!-- SelectorView is always used, so add it here. The rest are loaded dynamically --> <include layout="@layout/keyguard_selector_view"/> - </ViewFlipper> + </com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper> </com.android.internal.policy.impl.keyguard.KeyguardHostView> diff --git a/core/res/res/layout-port/keyguard_host_view.xml b/core/res/res/layout-port/keyguard_host_view.xml index 5e467d1..55c4c0d 100644 --- a/core/res/res/layout-port/keyguard_host_view.xml +++ b/core/res/res/layout-port/keyguard_host_view.xml @@ -28,7 +28,7 @@ android:gravity="center_horizontal" android:clipChildren="false"> - <ViewFlipper + <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper android:id="@+id/view_flipper" android:layout_height="match_parent" android:gravity="center"> @@ -36,7 +36,7 @@ <!-- SelectorView is always used, so add it here. The rest are loaded dynamically --> <include layout="@layout/keyguard_selector_view"/> - </ViewFlipper> + </com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper> </com.android.internal.policy.impl.keyguard.KeyguardHostView> diff --git a/core/res/res/layout-sw600dp-land/keyguard_host_view.xml b/core/res/res/layout-sw600dp-land/keyguard_host_view.xml index 5b6bb2f..652bdde 100644 --- a/core/res/res/layout-sw600dp-land/keyguard_host_view.xml +++ b/core/res/res/layout-sw600dp-land/keyguard_host_view.xml @@ -44,7 +44,7 @@ android:layout_weight="1" android:gravity="center"> - <ViewFlipper + <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper android:id="@+id/view_flipper" android:layout_width="@dimen/kg_security_view_width" android:layout_height="match_parent" @@ -55,7 +55,7 @@ <!-- SelectorView is always used, so add it here. The rest are loaded dynamically --> <include layout="@layout/keyguard_selector_view"/> - </ViewFlipper> + </com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper> </FrameLayout> diff --git a/core/res/res/layout-sw600dp-port/keyguard_host_view.xml b/core/res/res/layout-sw600dp-port/keyguard_host_view.xml index 397b881..0c1dd0c 100644 --- a/core/res/res/layout-sw600dp-port/keyguard_host_view.xml +++ b/core/res/res/layout-sw600dp-port/keyguard_host_view.xml @@ -40,7 +40,7 @@ </com.android.internal.policy.impl.keyguard.KeyguardWidgetPager> - <ViewFlipper + <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper android:id="@+id/view_flipper" android:layout_width="@dimen/kg_security_view_width" android:layout_height="0dip" @@ -50,7 +50,7 @@ <!-- SelectorView is always used, so add it here. The rest are loaded dynamically --> <include layout="@layout/keyguard_selector_view"/> - </ViewFlipper> + </com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper> </com.android.internal.policy.impl.keyguard.KeyguardHostView> diff --git a/core/res/res/layout/keyguard_pattern_view.xml b/core/res/res/layout/keyguard_pattern_view.xml index 954a92c..356bce3 100644 --- a/core/res/res/layout/keyguard_pattern_view.xml +++ b/core/res/res/layout/keyguard_pattern_view.xml @@ -23,42 +23,36 @@ <com.android.internal.policy.impl.keyguard.KeyguardPatternView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/keyguard_pattern_view" + android:orientation="vertical" android:layout_width="match_parent" - android:layout_height="match_parent"> - - <GridLayout - android:orientation="vertical" + android:layout_height="match_parent" + android:gravity="center_horizontal"> + + <include layout="@layout/keyguard_navigation"/> + + <Space android:layout_gravity="fill" /> + + <Button android:id="@+id/forgot_password_button" + android:layout_gravity="right" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size" + android:drawableLeft="@*android:drawable/lockscreen_forgot_password_button" + android:drawablePadding="0dip" + android:visibility="gone"/> + + <!-- We need MATCH_PARENT here only to force the size of the parent to be passed to + the pattern view for it to compute its size. This is an unusual case, caused by + LockPatternView's requirement to maintain a square aspect ratio based on the width + of the screen. --> + <com.android.internal.widget.LockPatternView + android:id="@+id/lockPatternView" android:layout_width="match_parent" android:layout_height="match_parent" - android:gravity="center_horizontal"> - - <include layout="@layout/keyguard_navigation"/> - - <Space android:layout_gravity="fill" /> - - <Button android:id="@+id/forgot_password_button" - android:layout_gravity="right" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size" - android:drawableLeft="@*android:drawable/lockscreen_forgot_password_button" - android:drawablePadding="0dip" - android:visibility="gone"/> - - <!-- We need MATCH_PARENT here only to force the size of the parent to be passed to - the pattern view for it to compute its size. This is an unusual case, caused by - LockPatternView's requirement to maintain a square aspect ratio based on the width - of the screen. --> - <com.android.internal.widget.LockPatternView - android:id="@+id/lockPatternView" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginEnd="8dip" - android:layout_marginBottom="4dip" - android:layout_marginStart="8dip" - android:layout_gravity="center_horizontal" - /> - - </GridLayout> + android:layout_marginEnd="8dip" + android:layout_marginBottom="4dip" + android:layout_marginStart="8dip" + android:layout_gravity="center_horizontal" + /> </com.android.internal.policy.impl.keyguard.KeyguardPatternView> diff --git a/core/res/res/layout/preference_holo.xml b/core/res/res/layout/preference_holo.xml index 7a0a494..1cc803b 100644 --- a/core/res/res/layout/preference_holo.xml +++ b/core/res/res/layout/preference_holo.xml @@ -33,11 +33,12 @@ android:orientation="horizontal"> <ImageView android:id="@+android:id/icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" + android:layout_width="48dp" + android:layout_height="48dp" android:layout_gravity="center" android:minWidth="48dp" - android:paddingRight="@dimen/preference_item_padding_inner" + android:scaleType="centerInside" + android:layout_marginEnd="@dimen/preference_item_padding_inner" /> </LinearLayout> @@ -56,7 +57,7 @@ android:textAppearance="?android:attr/textAppearanceMedium" android:ellipsize="marquee" android:fadingEdge="horizontal" /> - + <TextView android:id="@+android:id/summary" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java index 216344d..561e33e 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java @@ -36,6 +36,7 @@ import android.os.Message; import android.os.PowerManager; import android.os.ServiceManager; import android.os.SystemClock; +import android.os.UserHandle; import android.provider.Settings; import android.util.Log; import android.view.KeyEvent; @@ -696,12 +697,12 @@ public class ConnectivityManagerTestActivity extends Activity { */ public void setAirplaneMode(Context context, boolean enableAM) { //set the airplane mode - Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, + Settings.Global.putInt(context.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, enableAM ? 1 : 0); // Post the intent Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); intent.putExtra("state", enableAM); - context.sendBroadcast(intent); + context.sendBroadcastAsUser(intent, UserHandle.ALL); } protected static String convertToQuotedString(String string) { diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java index bf188d3..7928822 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java @@ -59,8 +59,8 @@ public class ConnectivityManagerMobileTest extends wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "CMWakeLock"); wl.acquire(); // Each test case will start with cellular connection - if (Settings.System.getInt(getInstrumentation().getContext().getContentResolver(), - Settings.System.AIRPLANE_MODE_ON) == 1) { + if (Settings.Global.getInt(getInstrumentation().getContext().getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON) == 1) { log("airplane is not disabled, disable it."); cmActivity.setAirplaneMode(getInstrumentation().getContext(), false); } @@ -84,8 +84,8 @@ public class ConnectivityManagerMobileTest extends wl.release(); cmActivity.removeConfiguredNetworksAndDisableWifi(); // if airplane mode is set, disable it. - if (Settings.System.getInt(getInstrumentation().getContext().getContentResolver(), - Settings.System.AIRPLANE_MODE_ON) == 1) { + if (Settings.Global.getInt(getInstrumentation().getContext().getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON) == 1) { log("disable airplane mode if it is enabled"); cmActivity.setAirplaneMode(getInstrumentation().getContext(), false); } diff --git a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java index b2075ae..af2a944 100644 --- a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java +++ b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java @@ -29,6 +29,7 @@ import android.net.Uri; import android.net.wifi.WifiManager; import android.os.Environment; import android.os.ParcelFileDescriptor; +import android.os.UserHandle; import android.os.ParcelFileDescriptor.AutoCloseInputStream; import android.os.SystemClock; import android.provider.Settings; @@ -553,7 +554,7 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase { int state = enable ? 1 : 0; // Change the system setting - Settings.System.putInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, + Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, state); String timeoutMessage = "Timed out waiting for airplane mode to be " + @@ -561,8 +562,8 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase { // wait for airplane mode to change state int currentWaitTime = 0; - while (Settings.System.getInt(mContext.getContentResolver(), - Settings.System.AIRPLANE_MODE_ON, -1) != state) { + while (Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, -1) != state) { timeoutWait(currentWaitTime, DEFAULT_WAIT_POLL_TIME, DEFAULT_MAX_WAIT_TIME, timeoutMessage); } @@ -570,7 +571,7 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase { // Post the intent Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); intent.putExtra("state", true); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } /** diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java index 1868d1c..785842f 100755 --- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java +++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java @@ -72,6 +72,8 @@ public class PackageManagerTests extends AndroidTestCase { public final long WAIT_TIME_INCR = 5 * 1000; + private static final String APP_LIB_DIR_PREFIX = "/data/app-lib/"; + private static final String SECURE_CONTAINERS_PREFIX = "/mnt/asec/"; private static final int APP_INSTALL_AUTO = PackageHelper.APP_INSTALL_AUTO; @@ -433,7 +435,7 @@ public class PackageManagerTests extends AndroidTestCase { assertEquals(srcPath, appInstallPath); assertEquals(publicSrcPath, appInstallPath); assertStartsWith("Native library should point to shared lib directory", - dataDir.getPath(), + new File(APP_LIB_DIR_PREFIX, info.packageName).getPath(), info.nativeLibraryDir); assertDirOwnerGroupPerms( "Native library directory should be owned by system:system and 0755", diff --git a/include/androidfw/Input.h b/include/androidfw/Input.h index 2c91fab..e88835e 100644 --- a/include/androidfw/Input.h +++ b/include/androidfw/Input.h @@ -49,6 +49,15 @@ enum { }; enum { + /* Used when a motion event is not associated with any display. + * Typically used for non-pointer events. */ + ADISPLAY_ID_NONE = -1, + + /* The default display id. */ + ADISPLAY_ID_DEFAULT = 0, +}; + +enum { /* * Indicates that an input device has switches. * This input source flag is hidden from the API because switches are only used by the system diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp index 6971d8a..abc88fa 100644 --- a/libs/hwui/Patch.cpp +++ b/libs/hwui/Patch.cpp @@ -266,6 +266,11 @@ void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, f const uint32_t oldQuadCount = quadCount; quadCount++; + if (x1 < 0.0f) x1 = 0.0f; + if (x2 < 0.0f) x2 = 0.0f; + if (y1 < 0.0f) y1 = 0.0f; + if (y2 < 0.0f) y2 = 0.0f; + // Skip degenerate and transparent (empty) quads if ((mColorKey >> oldQuadCount) & 0x1) { #if DEBUG_PATCHES_EMPTY_VERTICES diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java index f374c11..cad6d57 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java @@ -32,6 +32,7 @@ import android.hardware.display.DisplayManager; import android.hardware.display.WifiDisplay; import android.hardware.display.WifiDisplayStatus; import android.net.Uri; +import android.os.UserHandle; import android.provider.ContactsContract; import android.provider.Settings; import android.view.LayoutInflater; @@ -147,7 +148,7 @@ class QuickSettingsModel implements BluetoothStateChangeCallback, // TODO: Sets the view to be "awaiting" if not already awaiting // Change the system setting - Settings.System.putInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, + Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, enabled ? 1 : 0); // TODO: Update the UI to reflect system setting @@ -156,7 +157,7 @@ class QuickSettingsModel implements BluetoothStateChangeCallback, // Post the intent Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); intent.putExtra("state", enabled); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } // NetworkSignalChanged callback @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java index edad370..3c8276d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java @@ -74,7 +74,7 @@ public class AirplaneModeController extends BroadcastReceiver private boolean getAirplaneMode() { ContentResolver cr = mContext.getContentResolver(); - return 0 != Settings.System.getInt(cr, Settings.System.AIRPLANE_MODE_ON, 0); + return 0 != Settings.Global.getInt(cr, Settings.Global.AIRPLANE_MODE_ON, 0); } // TODO: Fix this racy API by adding something better to TelephonyManager or @@ -82,9 +82,9 @@ public class AirplaneModeController extends BroadcastReceiver private void unsafe(final boolean enabled) { AsyncTask.execute(new Runnable() { public void run() { - Settings.System.putInt( + Settings.Global.putInt( mContext.getContentResolver(), - Settings.System.AIRPLANE_MODE_ON, + Settings.Global.AIRPLANE_MODE_ON, enabled ? 1 : 0); Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 23f27e7..ea7235d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -509,8 +509,8 @@ public class NetworkController extends BroadcastReceiver { } private void updateAirplaneMode() { - mAirplaneMode = (Settings.System.getInt(mContext.getContentResolver(), - Settings.System.AIRPLANE_MODE_ON, 0) == 1); + mAirplaneMode = (Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 0) == 1); } private final void updateTelephonySignalStrength() { diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java index 10f45a5..753b864 100644 --- a/policy/src/com/android/internal/policy/impl/GlobalActions.java +++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java @@ -115,7 +115,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac context.getSystemService(Context.CONNECTIVITY_SERVICE); mHasTelephony = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); mContext.getContentResolver().registerContentObserver( - Settings.System.getUriFor(Settings.System.AIRPLANE_MODE_ON), true, + Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true, mAirplaneModeObserver); Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); mHasVibrator = vibrator != null && vibrator.hasVibrator(); @@ -849,9 +849,9 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac // Let the service state callbacks handle the state. if (mHasTelephony) return; - boolean airplaneModeOn = Settings.System.getInt( + boolean airplaneModeOn = Settings.Global.getInt( mContext.getContentResolver(), - Settings.System.AIRPLANE_MODE_ON, + Settings.Global.AIRPLANE_MODE_ON, 0) == 1; mAirplaneState = airplaneModeOn ? ToggleAction.State.On : ToggleAction.State.Off; mAirplaneModeOn.updateState(mAirplaneState); @@ -861,9 +861,9 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac * Change the airplane mode system setting */ private void changeAirplaneModeSystemSetting(boolean on) { - Settings.System.putInt( + Settings.Global.putInt( mContext.getContentResolver(), - Settings.System.AIRPLANE_MODE_ON, + Settings.Global.AIRPLANE_MODE_ON, on ? 1 : 0); Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java index e170ec1..863f4f8 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java @@ -32,17 +32,17 @@ import android.content.SharedPreferences; import android.content.pm.UserInfo; import android.content.res.Resources; import android.graphics.Canvas; +import android.graphics.Rect; import android.os.UserManager; -import android.telephony.TelephonyManager; import android.util.AttributeSet; import android.util.Log; import android.util.Slog; import android.view.KeyEvent; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.view.animation.AnimationUtils; -import android.widget.Button; import android.widget.RemoteViews.OnClickHandler; import android.widget.ViewFlipper; @@ -51,7 +51,6 @@ import com.android.internal.policy.impl.keyguard.KeyguardSecurityModel.SecurityM import com.android.internal.widget.LockPatternUtils; import java.io.File; -import java.util.ArrayList; import java.util.List; public class KeyguardHostView extends KeyguardViewBase { @@ -77,6 +76,8 @@ public class KeyguardHostView extends KeyguardViewBase { private KeyguardSecurityModel mSecurityModel; + private Rect mTempRect = new Rect(); + public KeyguardHostView(Context context) { this(context, null); } @@ -94,6 +95,17 @@ public class KeyguardHostView extends KeyguardViewBase { } @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + boolean result = super.dispatchTouchEvent(ev); + mTempRect.set(0, 0, 0, 0); + offsetRectIntoDescendantCoords(mSecurityViewContainer, mTempRect); + ev.offsetLocation(mTempRect.left, mTempRect.top); + result = mSecurityViewContainer.dispatchTouchEvent(ev) || result; + ev.offsetLocation(-mTempRect.left, -mTempRect.top); + return result; + } + + @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); mViewMediatorCallback.keyguardDoneDrawing(); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java index 3a32b5b..6de40e4 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java @@ -22,6 +22,7 @@ import android.accounts.AccountManagerFuture; import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; import android.content.Context; +import android.graphics.Rect; import android.os.Bundle; import android.os.CountDownTimer; import android.os.SystemClock; @@ -31,7 +32,7 @@ import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.Button; -import android.widget.LinearLayout; +import android.widget.GridLayout; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternView; @@ -40,7 +41,7 @@ import com.android.internal.R; import java.io.IOException; import java.util.List; -public class KeyguardPatternView extends LinearLayout implements KeyguardSecurityView { +public class KeyguardPatternView extends GridLayout implements KeyguardSecurityView { private static final String TAG = "SecurityPatternView"; private static final boolean DEBUG = false; @@ -83,6 +84,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit mLockPatternView.clearPattern(); } }; + private Rect mTempRect = new Rect(); enum FooterMode { Normal, @@ -156,13 +158,18 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit @Override public boolean dispatchTouchEvent(MotionEvent ev) { - final boolean result = super.dispatchTouchEvent(ev); + boolean result = super.dispatchTouchEvent(ev); // as long as the user is entering a pattern (i.e sending a touch event that was handled // by this screen), keep poking the wake lock so that the screen will stay on. final long elapsed = SystemClock.elapsedRealtime() - mLastPokeTime; if (result && (elapsed > (UNLOCK_PATTERN_WAKE_INTERVAL_MS - 100))) { mLastPokeTime = SystemClock.elapsedRealtime(); } + mTempRect.set(0, 0, 0, 0); + offsetRectIntoDescendantCoords(mLockPatternView, mTempRect); + ev.offsetLocation(mTempRect.left, mTempRect.top); + result = mLockPatternView.dispatchTouchEvent(ev) || result; + ev.offsetLocation(-mTempRect.left, -mTempRect.top); return result; } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewFlipper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewFlipper.java new file mode 100644 index 0000000..911cfe0 --- /dev/null +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewFlipper.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2012 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.policy.impl.keyguard; + +import android.content.Context; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.widget.ViewFlipper; + +/** + * Subclass of the current view flipper that allows us to overload dispatchTouchEvent() so + * we can emulate {@link WindowManager.LayoutParams#FLAG_SLIPPERY} within a view hierarchy. + * + */ +public class KeyguardSecurityViewFlipper extends ViewFlipper { + private Rect mTempRect = new Rect(); + + public KeyguardSecurityViewFlipper(Context context) { + this(context, null); + } + + public KeyguardSecurityViewFlipper(Context context, AttributeSet attr) { + super(context, attr); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + boolean result = super.dispatchTouchEvent(ev); + mTempRect.set(0, 0, 0, 0); + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + if (child.getVisibility() == View.VISIBLE) { + offsetRectIntoDescendantCoords(child, mTempRect); + ev.offsetLocation(mTempRect.left, mTempRect.top); + result = child.dispatchTouchEvent(ev) || result; + ev.offsetLocation(-mTempRect.left, -mTempRect.top); + } + } + return result; + } + +} diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java index 66c7c10..c48e2d7 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java @@ -73,9 +73,9 @@ public class KeyguardUpdateMonitor { private static final int MSG_PHONE_STATE_CHANGED = 306; private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307; private static final int MSG_DEVICE_PROVISIONED = 308; - protected static final int MSG_DPM_STATE_CHANGED = 309; - protected static final int MSG_USER_SWITCHED = 310; - protected static final int MSG_USER_REMOVED = 311; + private static final int MSG_DPM_STATE_CHANGED = 309; + private static final int MSG_USER_SWITCHED = 310; + private static final int MSG_USER_REMOVED = 311; private static KeyguardUpdateMonitor sInstance; diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java index 3ee82f7..1f0f5ef 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java @@ -41,6 +41,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import android.telephony.TelephonyManager; import android.util.EventLog; @@ -161,6 +162,9 @@ public class KeyguardViewMediator { /** High level access to the power manager for WakeLocks */ private PowerManager mPM; + /** UserManager for querying number of users */ + private UserManager mUserManager; + /** * Used to keep the device awake while the keyguard is showing, i.e for * calls to {@link #pokeWakelock()} @@ -436,6 +440,7 @@ public class KeyguardViewMediator { public KeyguardViewMediator(Context context, LockPatternUtils lockPatternUtils) { mContext = context; mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mWakeLock = mPM.newWakeLock( PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "keyguard"); mWakeLock.setReferenceCounted(false); @@ -779,7 +784,8 @@ public class KeyguardViewMediator { return; } - if (mLockPatternUtils.isLockScreenDisabled() && !lockedOrMissing) { + if (mUserManager.getUsers().size() < 2 + && mLockPatternUtils.isLockScreenDisabled() && !lockedOrMissing) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off"); return; } diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index 8604f95..87a6c1b 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -166,6 +166,10 @@ static bool validateMotionEvent(int32_t action, size_t pointerCount, return true; } +static bool isMainDisplay(int32_t displayId) { + return displayId == ADISPLAY_ID_DEFAULT || displayId == ADISPLAY_ID_NONE; +} + static void dumpRegion(String8& dump, const SkRegion& region) { if (region.isEmpty()) { dump.append("<empty>"); @@ -423,11 +427,12 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY && mInputTargetWaitApplicationHandle != NULL) { + int32_t displayId = motionEntry->displayId; int32_t x = int32_t(motionEntry->pointerCoords[0]. getAxisValue(AMOTION_EVENT_AXIS_X)); int32_t y = int32_t(motionEntry->pointerCoords[0]. getAxisValue(AMOTION_EVENT_AXIS_Y)); - sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(x, y); + sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y); if (touchedWindowHandle != NULL && touchedWindowHandle->inputApplicationHandle != mInputTargetWaitApplicationHandle) { @@ -444,28 +449,31 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { return needWake; } -sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) { +sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, + int32_t x, int32_t y) { // Traverse windows from front to back to find touched window. size_t numWindows = mWindowHandles.size(); for (size_t i = 0; i < numWindows; i++) { sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); const InputWindowInfo* windowInfo = windowHandle->getInfo(); - int32_t flags = windowInfo->layoutParamsFlags; - - if (windowInfo->visible) { - if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) { - bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE - | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0; - if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) { - // Found window. - return windowHandle; + if (windowInfo->displayId == displayId) { + int32_t flags = windowInfo->layoutParamsFlags; + + if (windowInfo->visible) { + if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) { + bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE + | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0; + if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) { + // Found window. + return windowHandle; + } } } - } - if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) { - // Error window is on top but not visible, so touch is dropped. - return NULL; + if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) { + // Error window is on top but not visible, so touch is dropped. + return NULL; + } } } return NULL; @@ -826,7 +834,10 @@ bool InputDispatcher::dispatchMotionLocked( return true; } - addMonitoringTargetsLocked(inputTargets); + // TODO: support sending secondary display events to input monitors + if (isMainDisplay(entry->displayId)) { + addMonitoringTargetsLocked(inputTargets); + } // Dispatch the motion. if (conflictingPointerActions) { @@ -1117,6 +1128,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, // bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE; + int32_t displayId = entry->displayId; int32_t action = entry->action; int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK; @@ -1126,9 +1138,10 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, sp<InputWindowHandle> newHoverWindowHandle; bool isSplit = mTouchState.split; - bool switchedDevice = mTouchState.deviceId >= 0 + bool switchedDevice = mTouchState.deviceId >= 0 && mTouchState.displayId >= 0 && (mTouchState.deviceId != entry->deviceId - || mTouchState.source != entry->source); + || mTouchState.source != entry->source + || mTouchState.displayId != displayId); bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE || maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER || maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT); @@ -1152,6 +1165,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, mTempTouchState.down = down; mTempTouchState.deviceId = entry->deviceId; mTempTouchState.source = entry->source; + mTempTouchState.displayId = displayId; isSplit = false; } else { mTempTouchState.copyFrom(mTouchState); @@ -1174,8 +1188,11 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, for (size_t i = 0; i < numWindows; i++) { sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); const InputWindowInfo* windowInfo = windowHandle->getInfo(); - int32_t flags = windowInfo->layoutParamsFlags; + if (windowInfo->displayId != displayId) { + continue; // wrong display + } + int32_t flags = windowInfo->layoutParamsFlags; if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) { if (topErrorWindowHandle == NULL) { topErrorWindowHandle = windowHandle; @@ -1300,7 +1317,8 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, sp<InputWindowHandle> oldTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle(); - sp<InputWindowHandle> newTouchedWindowHandle = findTouchedWindowAtLocked(x, y); + sp<InputWindowHandle> newTouchedWindowHandle = + findTouchedWindowAtLocked(displayId, x, y); if (oldTouchedWindowHandle != newTouchedWindowHandle && newTouchedWindowHandle != NULL) { #if DEBUG_FOCUS @@ -1438,8 +1456,10 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, if (foregroundWindowHandle->getInfo()->hasWallpaper) { for (size_t i = 0; i < mWindowHandles.size(); i++) { sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); - if (windowHandle->getInfo()->layoutParamsType - == InputWindowInfo::TYPE_WALLPAPER) { + const InputWindowInfo* info = windowHandle->getInfo(); + if (info->displayId == displayId + && windowHandle->getInfo()->layoutParamsType + == InputWindowInfo::TYPE_WALLPAPER) { mTempTouchState.addOrUpdateWindow(windowHandle, InputTarget::FLAG_WINDOW_IS_OBSCURED | InputTarget::FLAG_DISPATCH_AS_IS, @@ -1495,6 +1515,7 @@ Failed: || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) { mTouchState.deviceId = entry->deviceId; mTouchState.source = entry->source; + mTouchState.displayId = displayId; } } else if (maskedAction == AMOTION_EVENT_ACTION_UP || maskedAction == AMOTION_EVENT_ACTION_CANCEL) { @@ -1610,6 +1631,7 @@ bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& wind bool InputDispatcher::isWindowObscuredAtPointLocked( const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const { + int32_t displayId = windowHandle->getInfo()->displayId; size_t numWindows = mWindowHandles.size(); for (size_t i = 0; i < numWindows; i++) { sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i); @@ -1618,7 +1640,8 @@ bool InputDispatcher::isWindowObscuredAtPointLocked( } const InputWindowInfo* otherInfo = otherHandle->getInfo(); - if (otherInfo->visible && ! otherInfo->isTrustedOverlay() + if (otherInfo->displayId == displayId + && otherInfo->visible && !otherInfo->isTrustedOverlay() && otherInfo->frameContainsPoint(x, y)) { return true; } @@ -1845,7 +1868,7 @@ void InputDispatcher::enqueueDispatchEntryLocked( } if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE && !connection->inputState.isHovering( - motionEntry->deviceId, motionEntry->source)) { + motionEntry->deviceId, motionEntry->source, motionEntry->displayId)) { #if DEBUG_DISPATCH_CYCLE ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event", connection->getInputChannelName()); @@ -2271,6 +2294,7 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet originalMotionEntry->xPrecision, originalMotionEntry->yPrecision, originalMotionEntry->downTime, + originalMotionEntry->displayId, splitPointerCount, splitPointerProperties, splitPointerCoords); if (originalMotionEntry->injectionState) { @@ -2351,7 +2375,7 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { { // acquire lock mLock.lock(); - if (mInputFilterEnabled) { + if (shouldSendKeyToInputFilterLocked(args)) { mLock.unlock(); policyFlags |= POLICY_FLAG_FILTERED; @@ -2377,6 +2401,10 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { } } +bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) { + return mInputFilterEnabled; +} + void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { #if DEBUG_INBOUND_EVENT_DETAILS ALOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, " @@ -2415,7 +2443,7 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { { // acquire lock mLock.lock(); - if (mInputFilterEnabled) { + if (shouldSendMotionToInputFilterLocked(args)) { mLock.unlock(); MotionEvent event; @@ -2438,6 +2466,7 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { args->deviceId, args->source, policyFlags, args->action, args->flags, args->metaState, args->buttonState, args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime, + args->displayId, args->pointerCount, args->pointerProperties, args->pointerCoords); needWake = enqueueInboundEventLocked(newEntry); @@ -2449,6 +2478,11 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { } } +bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) { + // TODO: support sending secondary display events to input filter + return mInputFilterEnabled && isMainDisplay(args->displayId); +} + void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) { #if DEBUG_INBOUND_EVENT_DETAILS ALOGD("notifySwitch - eventTime=%lld, policyFlags=0x%x, switchCode=%d, switchValue=%d", @@ -2532,6 +2566,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, case AINPUT_EVENT_TYPE_MOTION: { const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event); + int32_t displayId = ADISPLAY_ID_DEFAULT; int32_t action = motionEvent->getAction(); size_t pointerCount = motionEvent->getPointerCount(); const PointerProperties* pointerProperties = motionEvent->getPointerProperties(); @@ -2553,8 +2588,8 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, motionEvent->getMetaState(), motionEvent->getButtonState(), motionEvent->getEdgeFlags(), motionEvent->getXPrecision(), motionEvent->getYPrecision(), - motionEvent->getDownTime(), uint32_t(pointerCount), - pointerProperties, samplePointerCoords); + motionEvent->getDownTime(), displayId, + uint32_t(pointerCount), pointerProperties, samplePointerCoords); lastInjectedEntry = firstInjectedEntry; for (size_t i = motionEvent->getHistorySize(); i > 0; i--) { sampleEventTimes += 1; @@ -2565,8 +2600,8 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, motionEvent->getMetaState(), motionEvent->getButtonState(), motionEvent->getEdgeFlags(), motionEvent->getXPrecision(), motionEvent->getYPrecision(), - motionEvent->getDownTime(), uint32_t(pointerCount), - pointerProperties, samplePointerCoords); + motionEvent->getDownTime(), displayId, + uint32_t(pointerCount), pointerProperties, samplePointerCoords); lastInjectedEntry->next = nextInjectedEntry; lastInjectedEntry = nextInjectedEntry; } @@ -2939,6 +2974,12 @@ bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel, #endif return true; } + if (fromWindowHandle->getInfo()->displayId != toWindowHandle->getInfo()->displayId) { +#if DEBUG_FOCUS + ALOGD("Cannot transfer focus because windows are on different displays."); +#endif + return false; + } bool found = false; for (size_t i = 0; i < mTouchState.windows.size(); i++) { @@ -3040,6 +3081,7 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) { dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split)); dump.appendFormat(INDENT "TouchDeviceId: %d\n", mTouchState.deviceId); dump.appendFormat(INDENT "TouchSource: 0x%08x\n", mTouchState.source); + dump.appendFormat(INDENT "TouchDisplayId: %d\n", mTouchState.displayId); if (!mTouchState.windows.isEmpty()) { dump.append(INDENT "TouchedWindows:\n"); for (size_t i = 0; i < mTouchState.windows.size(); i++) { @@ -3059,11 +3101,12 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) { const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i); const InputWindowInfo* windowInfo = windowHandle->getInfo(); - dump.appendFormat(INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, " + dump.appendFormat(INDENT2 "%d: name='%s', displayId=%d, " + "paused=%s, hasFocus=%s, hasWallpaper=%s, " "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, " "frame=[%d,%d][%d,%d], scale=%f, " "touchableRegion=", - i, windowInfo->name.string(), + i, windowInfo->name.string(), windowInfo->displayId, toString(windowInfo->paused), toString(windowInfo->hasFocus), toString(windowInfo->hasWallpaper), @@ -3802,14 +3845,14 @@ InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags, float xPrecision, float yPrecision, - nsecs_t downTime, uint32_t pointerCount, + nsecs_t downTime, int32_t displayId, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) : EventEntry(TYPE_MOTION, eventTime, policyFlags), eventTime(eventTime), deviceId(deviceId), source(source), action(action), flags(flags), metaState(metaState), buttonState(buttonState), edgeFlags(edgeFlags), xPrecision(xPrecision), yPrecision(yPrecision), - downTime(downTime), pointerCount(pointerCount) { + downTime(downTime), displayId(displayId), pointerCount(pointerCount) { for (uint32_t i = 0; i < pointerCount; i++) { this->pointerProperties[i].copyFrom(pointerProperties[i]); this->pointerCoords[i].copyFrom(pointerCoords[i]); @@ -3820,8 +3863,8 @@ InputDispatcher::MotionEntry::~MotionEntry() { } void InputDispatcher::MotionEntry::appendDescription(String8& msg) const { - msg.appendFormat("MotionEvent(action=%d, deviceId=%d, source=0x%08x)", - action, deviceId, source); + msg.appendFormat("MotionEvent(action=%d, deviceId=%d, source=0x%08x, displayId=%d)", + action, deviceId, source, displayId); } @@ -3864,11 +3907,13 @@ bool InputDispatcher::InputState::isNeutral() const { return mKeyMementos.isEmpty() && mMotionMementos.isEmpty(); } -bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source) const { +bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source, + int32_t displayId) const { for (size_t i = 0; i < mMotionMementos.size(); i++) { const MotionMemento& memento = mMotionMementos.itemAt(i); if (memento.deviceId == deviceId && memento.source == source + && memento.displayId == displayId && memento.hovering) { return true; } @@ -4025,6 +4070,7 @@ ssize_t InputDispatcher::InputState::findMotionMemento(const MotionEntry* entry, const MotionMemento& memento = mMotionMementos.itemAt(i); if (memento.deviceId == entry->deviceId && memento.source == entry->source + && memento.displayId == entry->displayId && memento.hovering == hovering) { return i; } @@ -4055,6 +4101,7 @@ void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry, memento.xPrecision = entry->xPrecision; memento.yPrecision = entry->yPrecision; memento.downTime = entry->downTime; + memento.displayId = entry->displayId; memento.setPointers(entry); memento.hovering = hovering; memento.policyFlags = entry->policyFlags; @@ -4090,6 +4137,7 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim : AMOTION_EVENT_ACTION_CANCEL, memento.flags, 0, 0, 0, memento.xPrecision, memento.yPrecision, memento.downTime, + memento.displayId, memento.pointerCount, memento.pointerProperties, memento.pointerCoords)); } } @@ -4108,7 +4156,8 @@ void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const { for (size_t j = 0; j < other.mMotionMementos.size(); ) { const MotionMemento& otherMemento = other.mMotionMementos.itemAt(j); if (memento.deviceId == otherMemento.deviceId - && memento.source == otherMemento.source) { + && memento.source == otherMemento.source + && memento.displayId == otherMemento.displayId) { other.mMotionMementos.removeAt(j); } else { j += 1; @@ -4240,7 +4289,7 @@ InputDispatcher::CommandEntry::~CommandEntry() { // --- InputDispatcher::TouchState --- InputDispatcher::TouchState::TouchState() : - down(false), split(false), deviceId(-1), source(0) { + down(false), split(false), deviceId(-1), source(0), displayId(-1) { } InputDispatcher::TouchState::~TouchState() { @@ -4251,6 +4300,7 @@ void InputDispatcher::TouchState::reset() { split = false; deviceId = -1; source = 0; + displayId = -1; windows.clear(); } @@ -4259,6 +4309,7 @@ void InputDispatcher::TouchState::copyFrom(const TouchState& other) { split = other.split; deviceId = other.deviceId; source = other.source; + displayId = other.displayId; windows = other.windows; } diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h index d0824fc..af7ff5e 100644 --- a/services/input/InputDispatcher.h +++ b/services/input/InputDispatcher.h @@ -511,15 +511,17 @@ private: float xPrecision; float yPrecision; nsecs_t downTime; + int32_t displayId; uint32_t pointerCount; PointerProperties pointerProperties[MAX_POINTERS]; PointerCoords pointerCoords[MAX_POINTERS]; MotionEntry(nsecs_t eventTime, - int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, - int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags, + int32_t deviceId, uint32_t source, uint32_t policyFlags, + int32_t action, int32_t flags, + int32_t metaState, int32_t buttonState, int32_t edgeFlags, float xPrecision, float yPrecision, - nsecs_t downTime, uint32_t pointerCount, + nsecs_t downTime, int32_t displayId, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords); virtual void appendDescription(String8& msg) const; @@ -696,7 +698,7 @@ private: // Returns true if the specified source is known to have received a hover enter // motion event. - bool isHovering(int32_t deviceId, uint32_t source) const; + bool isHovering(int32_t deviceId, uint32_t source, int32_t displayId) const; // Records tracking information for a key event that has just been published. // Returns true if the event should be delivered, false if it is inconsistent @@ -752,6 +754,7 @@ private: float xPrecision; float yPrecision; nsecs_t downTime; + int32_t displayId; uint32_t pointerCount; PointerProperties pointerProperties[MAX_POINTERS]; PointerCoords pointerCoords[MAX_POINTERS]; @@ -867,7 +870,7 @@ private: // to transfer focus to a new application. EventEntry* mNextUnblockedEvent; - sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t x, int32_t y); + sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y); // All registered connections mapped by channel file descriptor. KeyedVector<int, sp<Connection> > mConnectionsByFd; @@ -899,6 +902,10 @@ private: bool runCommandsLockedInterruptible(); CommandEntry* postCommandLocked(Command command); + // Input filter processing. + bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args); + bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args); + // Inbound event processing. void drainInboundQueueLocked(); void releasePendingEventLocked(); @@ -928,6 +935,7 @@ private: bool split; int32_t deviceId; // id of the device that is currently down, others are rejected uint32_t source; // source of the device that is current down, others are rejected + int32_t displayId; // id to the display that currently has a touch, others are rejected Vector<TouchedWindow> windows; TouchState(); diff --git a/services/input/InputListener.cpp b/services/input/InputListener.cpp index 657a6b9..c2705b0 100644 --- a/services/input/InputListener.cpp +++ b/services/input/InputListener.cpp @@ -69,12 +69,12 @@ void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const { NotifyMotionArgs::NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, - int32_t edgeFlags, uint32_t pointerCount, + int32_t edgeFlags, int32_t displayId, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords, float xPrecision, float yPrecision, nsecs_t downTime) : eventTime(eventTime), deviceId(deviceId), source(source), policyFlags(policyFlags), action(action), flags(flags), metaState(metaState), buttonState(buttonState), - edgeFlags(edgeFlags), pointerCount(pointerCount), + edgeFlags(edgeFlags), displayId(displayId), pointerCount(pointerCount), xPrecision(xPrecision), yPrecision(yPrecision), downTime(downTime) { for (uint32_t i = 0; i < pointerCount; i++) { this->pointerProperties[i].copyFrom(pointerProperties[i]); @@ -87,7 +87,8 @@ NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other) : policyFlags(other.policyFlags), action(other.action), flags(other.flags), metaState(other.metaState), buttonState(other.buttonState), - edgeFlags(other.edgeFlags), pointerCount(other.pointerCount), + edgeFlags(other.edgeFlags), displayId(other.displayId), + pointerCount(other.pointerCount), xPrecision(other.xPrecision), yPrecision(other.yPrecision), downTime(other.downTime) { for (uint32_t i = 0; i < pointerCount; i++) { pointerProperties[i].copyFrom(other.pointerProperties[i]); diff --git a/services/input/InputListener.h b/services/input/InputListener.h index b1dc0b8..486852b 100644 --- a/services/input/InputListener.h +++ b/services/input/InputListener.h @@ -88,6 +88,7 @@ struct NotifyMotionArgs : public NotifyArgs { int32_t metaState; int32_t buttonState; int32_t edgeFlags; + int32_t displayId; uint32_t pointerCount; PointerProperties pointerProperties[MAX_POINTERS]; PointerCoords pointerCoords[MAX_POINTERS]; @@ -99,7 +100,7 @@ struct NotifyMotionArgs : public NotifyArgs { NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, - int32_t edgeFlags, uint32_t pointerCount, + int32_t edgeFlags, int32_t displayId, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords, float xPrecision, float yPrecision, nsecs_t downTime); diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index 513dc13..d56b9a9 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -2431,6 +2431,7 @@ void CursorInputMapper::sync(nsecs_t when) { mPointerVelocityControl.move(when, &deltaX, &deltaY); + int32_t displayId; if (mPointerController != NULL) { if (moved || scrolled || buttonsChanged) { mPointerController->setPresentation( @@ -2451,9 +2452,11 @@ void CursorInputMapper::sync(nsecs_t when) { mPointerController->getPosition(&x, &y); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); + displayId = ADISPLAY_ID_DEFAULT; } else { pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY); + displayId = ADISPLAY_ID_NONE; } pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f); @@ -2485,7 +2488,8 @@ void CursorInputMapper::sync(nsecs_t when) { NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, motionEventAction, 0, metaState, currentButtonState, 0, - 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); + displayId, 1, &pointerProperties, &pointerCoords, + mXPrecision, mYPrecision, downTime); getListener()->notifyMotion(&args); // Send hover move after UP to tell the application that the mouse is hovering now. @@ -2494,7 +2498,8 @@ void CursorInputMapper::sync(nsecs_t when) { NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE, - 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); + displayId, 1, &pointerProperties, &pointerCoords, + mXPrecision, mYPrecision, downTime); getListener()->notifyMotion(&hoverArgs); } @@ -2506,7 +2511,8 @@ void CursorInputMapper::sync(nsecs_t when) { NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE, - 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); + displayId, 1, &pointerProperties, &pointerCoords, + mXPrecision, mYPrecision, downTime); getListener()->notifyMotion(&scrollArgs); } } @@ -2539,7 +2545,8 @@ void CursorInputMapper::fadePointer() { TouchInputMapper::TouchInputMapper(InputDevice* device) : InputMapper(device), mSource(0), mDeviceMode(DEVICE_MODE_DISABLED), - mSurfaceOrientation(-1), mSurfaceWidth(-1), mSurfaceHeight(-1) { + mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0), + mSurfaceOrientation(DISPLAY_ORIENTATION_0) { } TouchInputMapper::~TouchInputMapper() { @@ -2601,6 +2608,8 @@ void TouchInputMapper::dump(String8& dump) { dumpSurface(dump); dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n"); + dump.appendFormat(INDENT4 "XTranslate: %0.3f\n", mXTranslate); + dump.appendFormat(INDENT4 "YTranslate: %0.3f\n", mYTranslate); dump.appendFormat(INDENT4 "XScale: %0.3f\n", mXScale); dump.appendFormat(INDENT4 "YScale: %0.3f\n", mYScale); dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mXPrecision); @@ -2810,7 +2819,7 @@ void TouchInputMapper::dumpParameters(String8& dump) { ALOG_ASSERT(false); } - dump.appendFormat(INDENT4 "AssociatedDisplay: present=%s, isExternal=%s\n", + dump.appendFormat(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s\n", toString(mParameters.hasAssociatedDisplay), toString(mParameters.associatedDisplayIsExternal)); dump.appendFormat(INDENT4 "OrientationAware: %s\n", @@ -2869,10 +2878,15 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { return; } + // Raw width and height in the natural orientation. + int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; + int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; + // Get associated display dimensions. + bool viewportChanged = false; + DisplayViewport newViewport; if (mParameters.hasAssociatedDisplay) { - if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, - &mAssociatedDisplayViewport)) { + if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, &newViewport)) { ALOGI(INDENT "Touch device '%s' could not query the properties of its associated " "display. The device will be inoperable until the display size " "becomes available.", @@ -2880,25 +2894,77 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mDeviceMode = DEVICE_MODE_DISABLED; return; } - } + } else { + newViewport.setNonDisplayViewport(rawWidth, rawHeight); + } + if (mViewport != newViewport) { + mViewport = newViewport; + viewportChanged = true; + + if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) { + // Convert rotated viewport to natural surface coordinates. + int32_t naturalLogicalWidth, naturalLogicalHeight; + int32_t naturalPhysicalWidth, naturalPhysicalHeight; + int32_t naturalPhysicalLeft, naturalPhysicalTop; + int32_t naturalDeviceWidth, naturalDeviceHeight; + switch (mViewport.orientation) { + case DISPLAY_ORIENTATION_90: + naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop; + naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft; + naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop; + naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft; + naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom; + naturalPhysicalTop = mViewport.physicalLeft; + naturalDeviceWidth = mViewport.deviceHeight; + naturalDeviceHeight = mViewport.deviceWidth; + break; + case DISPLAY_ORIENTATION_180: + naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft; + naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop; + naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft; + naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop; + naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight; + naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom; + naturalDeviceWidth = mViewport.deviceWidth; + naturalDeviceHeight = mViewport.deviceHeight; + break; + case DISPLAY_ORIENTATION_270: + naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop; + naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft; + naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop; + naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft; + naturalPhysicalLeft = mViewport.physicalTop; + naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight; + naturalDeviceWidth = mViewport.deviceHeight; + naturalDeviceHeight = mViewport.deviceWidth; + break; + case DISPLAY_ORIENTATION_0: + default: + naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft; + naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop; + naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft; + naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop; + naturalPhysicalLeft = mViewport.physicalLeft; + naturalPhysicalTop = mViewport.physicalTop; + naturalDeviceWidth = mViewport.deviceWidth; + naturalDeviceHeight = mViewport.deviceHeight; + break; + } + + mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth; + mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight; + mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth; + mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight; - // Configure dimensions. - int32_t width, height, orientation; - if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) { - width = mAssociatedDisplayViewport.logicalRight - mAssociatedDisplayViewport.logicalLeft; - height = mAssociatedDisplayViewport.logicalBottom - mAssociatedDisplayViewport.logicalTop; - if (mAssociatedDisplayViewport.orientation == DISPLAY_ORIENTATION_90 - || mAssociatedDisplayViewport.orientation == DISPLAY_ORIENTATION_270) { - int32_t temp = height; - height = width; - width = temp; + mSurfaceOrientation = mParameters.orientationAware ? + mViewport.orientation : DISPLAY_ORIENTATION_0; + } else { + mSurfaceWidth = rawWidth; + mSurfaceHeight = rawHeight; + mSurfaceLeft = 0; + mSurfaceTop = 0; + mSurfaceOrientation = DISPLAY_ORIENTATION_0; } - orientation = mParameters.orientationAware ? - mAssociatedDisplayViewport.orientation : DISPLAY_ORIENTATION_0; - } else { - width = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; - height = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; - orientation = DISPLAY_ORIENTATION_0; } // If moving between pointer modes, need to reset some state. @@ -2918,22 +2984,17 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mPointerController.clear(); } - bool orientationChanged = mSurfaceOrientation != orientation; - if (orientationChanged) { - mSurfaceOrientation = orientation; - } - - bool sizeChanged = mSurfaceWidth != width || mSurfaceHeight != height; - if (sizeChanged || deviceModeChanged) { - ALOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d, mode is %d", - getDeviceId(), getDeviceName().string(), width, height, mDeviceMode); - - mSurfaceWidth = width; - mSurfaceHeight = height; + if (viewportChanged || deviceModeChanged) { + ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, " + "display id %d", + getDeviceId(), getDeviceName().string(), mSurfaceWidth, mSurfaceHeight, + mSurfaceOrientation, mDeviceMode, mViewport.displayId); // Configure X and Y factors. - mXScale = float(width) / (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1); - mYScale = float(height) / (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1); + mXScale = float(mSurfaceWidth) / rawWidth; + mYScale = float(mSurfaceHeight) / rawHeight; + mXTranslate = -mSurfaceLeft; + mYTranslate = -mSurfaceTop; mXPrecision = 1.0f / mXScale; mYPrecision = 1.0f / mYScale; @@ -2950,7 +3011,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mGeometricScale = avg(mXScale, mYScale); // Size of diagonal axis. - float diagonalSize = hypotf(width, height); + float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight); // Size factors. if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) { @@ -3102,50 +3163,38 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mOrientedRanges.distance.fuzz = mRawPointerAxes.distance.fuzz * mDistanceScale; } - } - if (orientationChanged || sizeChanged || deviceModeChanged) { - // Compute oriented surface dimensions, precision, scales and ranges. + // Compute oriented precision, scales and ranges. // Note that the maximum value reported is an inclusive maximum value so it is one // unit less than the total width or height of surface. switch (mSurfaceOrientation) { case DISPLAY_ORIENTATION_90: case DISPLAY_ORIENTATION_270: - mOrientedSurfaceWidth = mSurfaceHeight; - mOrientedSurfaceHeight = mSurfaceWidth; - mOrientedXPrecision = mYPrecision; mOrientedYPrecision = mXPrecision; - mOrientedRanges.x.min = 0; - mOrientedRanges.x.max = (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue) - * mYScale; + mOrientedRanges.x.min = mYTranslate; + mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1; mOrientedRanges.x.flat = 0; mOrientedRanges.x.fuzz = mYScale; - mOrientedRanges.y.min = 0; - mOrientedRanges.y.max = (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue) - * mXScale; + mOrientedRanges.y.min = mXTranslate; + mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1; mOrientedRanges.y.flat = 0; mOrientedRanges.y.fuzz = mXScale; break; default: - mOrientedSurfaceWidth = mSurfaceWidth; - mOrientedSurfaceHeight = mSurfaceHeight; - mOrientedXPrecision = mXPrecision; mOrientedYPrecision = mYPrecision; - mOrientedRanges.x.min = 0; - mOrientedRanges.x.max = (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue) - * mXScale; + mOrientedRanges.x.min = mXTranslate; + mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1; mOrientedRanges.x.flat = 0; mOrientedRanges.x.fuzz = mXScale; - mOrientedRanges.y.min = 0; - mOrientedRanges.y.max = (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue) - * mYScale; + mOrientedRanges.y.min = mYTranslate; + mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1; mOrientedRanges.y.flat = 0; mOrientedRanges.y.fuzz = mYScale; break; @@ -3153,10 +3202,8 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { // Compute pointer gesture detection parameters. if (mDeviceMode == DEVICE_MODE_POINTER) { - int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; - int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; float rawDiagonal = hypotf(rawWidth, rawHeight); - float displayDiagonal = hypotf(width, height); + float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight); // Scale movements such that one whole swipe of the touch pad covers a // given area relative to the diagonal size of the display when no acceleration @@ -3191,8 +3238,21 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { } void TouchInputMapper::dumpSurface(String8& dump) { + dump.appendFormat(INDENT3 "Viewport: displayId=%d, orientation=%d, " + "logicalFrame=[%d, %d, %d, %d], " + "physicalFrame=[%d, %d, %d, %d], " + "deviceSize=[%d, %d]\n", + mViewport.displayId, mViewport.orientation, + mViewport.logicalLeft, mViewport.logicalTop, + mViewport.logicalRight, mViewport.logicalBottom, + mViewport.physicalLeft, mViewport.physicalTop, + mViewport.physicalRight, mViewport.physicalBottom, + mViewport.deviceWidth, mViewport.deviceHeight); + dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth); dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight); + dump.appendFormat(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft); + dump.appendFormat(INDENT3 "SurfaceTop: %d\n", mSurfaceTop); dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation); } @@ -4087,28 +4147,28 @@ void TouchInputMapper::cookPointerData() { float x, y; switch (mSurfaceOrientation) { case DISPLAY_ORIENTATION_90: - x = float(in.y - mRawPointerAxes.y.minValue) * mYScale; - y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale; + x = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; + y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate; orientation -= M_PI_2; if (orientation < - M_PI_2) { orientation += M_PI; } break; case DISPLAY_ORIENTATION_180: - x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale; - y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale; + x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate; + y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate; break; case DISPLAY_ORIENTATION_270: - x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale; - y = float(in.x - mRawPointerAxes.x.minValue) * mXScale; + x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate; + y = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; orientation += M_PI_2; if (orientation > M_PI_2) { orientation -= M_PI; } break; default: - x = float(in.x - mRawPointerAxes.x.minValue) * mXScale; - y = float(in.y - mRawPointerAxes.y.minValue) * mYScale; + x = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; + y = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; break; } @@ -4364,7 +4424,8 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - 1, &pointerProperties, &pointerCoords, 0, 0, mPointerGesture.downTime); + mViewport.displayId, 1, &pointerProperties, &pointerCoords, + 0, 0, mPointerGesture.downTime); getListener()->notifyMotion(&args); } @@ -5272,6 +5333,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send up. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5284,6 +5346,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send hover exit. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5298,6 +5361,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send down. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5307,6 +5371,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send move. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5320,6 +5385,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send hover enter. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5329,6 +5395,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send hover move. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5349,6 +5416,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.currentProperties, &pointerCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5410,7 +5478,8 @@ void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32 NotifyMotionArgs args(when, getDeviceId(), source, policyFlags, action, flags, metaState, buttonState, edgeFlags, - pointerCount, pointerProperties, pointerCoords, xPrecision, yPrecision, downTime); + mViewport.displayId, pointerCount, pointerProperties, pointerCoords, + xPrecision, yPrecision, downTime); getListener()->notifyMotion(&args); } @@ -6213,7 +6282,7 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) { } } - // Moving a joystick axis should not wake the devide because joysticks can + // Moving a joystick axis should not wake the device because joysticks can // be fairly noisy even when not in use. On the other hand, pushing a gamepad // button will likely wake the device. // TODO: Use the input device configuration to control this behavior more finely. @@ -6221,7 +6290,7 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) { NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - 1, &pointerProperties, &pointerCoords, 0, 0, 0); + ADISPLAY_ID_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, 0); getListener()->notifyMotion(&args); } diff --git a/services/input/InputReader.h b/services/input/InputReader.h index e345a5f..e1a8dd8 100644 --- a/services/input/InputReader.h +++ b/services/input/InputReader.h @@ -62,11 +62,14 @@ struct DisplayViewport { int32_t physicalTop; int32_t physicalRight; int32_t physicalBottom; + int32_t deviceWidth; + int32_t deviceHeight; DisplayViewport() : - displayId(-1), orientation(DISPLAY_ORIENTATION_0), + displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0), logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0), - physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0) { + physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0), + deviceWidth(0), deviceHeight(0) { } bool operator==(const DisplayViewport& other) const { @@ -79,12 +82,33 @@ struct DisplayViewport { && physicalLeft == other.physicalLeft && physicalTop == other.physicalTop && physicalRight == other.physicalRight - && physicalBottom == other.physicalBottom; + && physicalBottom == other.physicalBottom + && deviceWidth == other.deviceWidth + && deviceHeight == other.deviceHeight; } bool operator!=(const DisplayViewport& other) const { return !(*this == other); } + + inline bool isValid() const { + return displayId >= 0; + } + + void setNonDisplayViewport(int32_t width, int32_t height) { + displayId = ADISPLAY_ID_NONE; + orientation = DISPLAY_ORIENTATION_0; + logicalLeft = 0; + logicalTop = 0; + logicalRight = width; + logicalBottom = height; + physicalLeft = 0; + physicalTop = 0; + physicalRight = width; + physicalBottom = height; + deviceWidth = width; + deviceHeight = height; + } }; /* @@ -1297,18 +1321,30 @@ protected: virtual void syncTouch(nsecs_t when, bool* outHavePointerIds) = 0; private: - // The surface orientation and width and height set by configureSurface(). - int32_t mSurfaceOrientation; + // The current viewport. + // The components of the viewport are specified in the display's rotated orientation. + DisplayViewport mViewport; + + // The surface orientation, width and height set by configureSurface(). + // The width and height are derived from the viewport but are specified + // in the natural orientation. + // The surface origin specifies how the surface coordinates should be translated + // to align with the logical display coordinate space. + // The orientation may be different from the viewport orientation as it specifies + // the rotation of the surface coordinates required to produce the viewport's + // requested orientation, so it will depend on whether the device is orientation aware. int32_t mSurfaceWidth; int32_t mSurfaceHeight; - - // The associated display viewport set by configureSurface(). - DisplayViewport mAssociatedDisplayViewport; + int32_t mSurfaceLeft; + int32_t mSurfaceTop; + int32_t mSurfaceOrientation; // Translation and scaling factors, orientation-independent. + float mXTranslate; float mXScale; float mXPrecision; + float mYTranslate; float mYScale; float mYPrecision; @@ -1369,8 +1405,6 @@ private: } mOrientedRanges; // Oriented dimensions and precision. - float mOrientedSurfaceWidth; - float mOrientedSurfaceHeight; float mOrientedXPrecision; float mOrientedYPrecision; diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h index 824a64b..3118099 100644 --- a/services/input/InputWindow.h +++ b/services/input/InputWindow.h @@ -132,6 +132,7 @@ struct InputWindowInfo { int32_t ownerPid; int32_t ownerUid; int32_t inputFeatures; + int32_t displayId; bool touchableRegionContainsPoint(int32_t x, int32_t y) const; bool frameContainsPoint(int32_t x, int32_t y) const; diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp index 03516af..c6dbbf3 100644 --- a/services/input/tests/InputReader_test.cpp +++ b/services/input/tests/InputReader_test.cpp @@ -151,6 +151,8 @@ public: v.physicalTop = 0; v.physicalRight = isRotated ? height : width; v.physicalBottom = isRotated ? width : height; + v.deviceWidth = isRotated ? height : width; + v.deviceHeight = isRotated ? width : height; mConfig.setDisplayInfo(false /*external*/, v); mConfig.setDisplayInfo(true /*external*/, v); } @@ -487,6 +489,7 @@ private: return OK; } } + outAxisInfo->clear(); return -1; } diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java index 9404dce..e68686d 100755 --- a/services/java/com/android/server/BluetoothManagerService.java +++ b/services/java/com/android/server/BluetoothManagerService.java @@ -75,12 +75,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void registerForAirplaneMode(IntentFilter filter) { final ContentResolver resolver = mContext.getContentResolver(); - final String airplaneModeRadios = Settings.System.getString(resolver, - Settings.System.AIRPLANE_MODE_RADIOS); - final String toggleableRadios = Settings.System.getString(resolver, - Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); + final String airplaneModeRadios = Settings.Global.getString(resolver, + Settings.Global.AIRPLANE_MODE_RADIOS); + final String toggleableRadios = Settings.Global.getString(resolver, + Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true : - airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH); + airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH); if (mIsAirplaneSensitive) { filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); } @@ -151,8 +151,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Returns true if airplane mode is currently on */ private final boolean isAirplaneModeOn() { - return Settings.System.getInt(mContext.getContentResolver(), - Settings.System.AIRPLANE_MODE_ON, 0) == 1; + return Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 0) == 1; } /** diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 6bc5e10..7ed4f8a 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -1179,17 +1179,17 @@ public class WifiService extends IWifiManager.Stub { } private boolean isAirplaneSensitive() { - String airplaneModeRadios = Settings.System.getString(mContext.getContentResolver(), - Settings.System.AIRPLANE_MODE_RADIOS); + String airplaneModeRadios = Settings.Global.getString(mContext.getContentResolver(), + Settings.Global.AIRPLANE_MODE_RADIOS); return airplaneModeRadios == null - || airplaneModeRadios.contains(Settings.System.RADIO_WIFI); + || airplaneModeRadios.contains(Settings.Global.RADIO_WIFI); } private boolean isAirplaneToggleable() { - String toggleableRadios = Settings.System.getString(mContext.getContentResolver(), - Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); + String toggleableRadios = Settings.Global.getString(mContext.getContentResolver(), + Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); return toggleableRadios != null - && toggleableRadios.contains(Settings.System.RADIO_WIFI); + && toggleableRadios.contains(Settings.Global.RADIO_WIFI); } /** @@ -1198,8 +1198,8 @@ public class WifiService extends IWifiManager.Stub { * @return {@code true} if airplane mode is on. */ private boolean isAirplaneModeOn() { - return isAirplaneSensitive() && Settings.System.getInt(mContext.getContentResolver(), - Settings.System.AIRPLANE_MODE_ON, 0) == 1; + return isAirplaneSensitive() && Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 0) == 1; } @Override @@ -1213,8 +1213,8 @@ public class WifiService extends IWifiManager.Stub { } pw.println("Wi-Fi is " + mWifiStateMachine.syncGetWifiStateByName()); pw.println("Stay-awake conditions: " + - Settings.System.getInt(mContext.getContentResolver(), - Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0)); + Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0)); pw.println(); pw.println("Internal state:"); diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/java/com/android/server/display/DisplayDevice.java index 8eeefb4..f5aa3d4 100644 --- a/services/java/com/android/server/display/DisplayDevice.java +++ b/services/java/com/android/server/display/DisplayDevice.java @@ -176,6 +176,12 @@ abstract class DisplayDevice { } else { viewport.physicalFrame.setEmpty(); } + + boolean isRotated = (mCurrentOrientation == Surface.ROTATION_90 + || mCurrentOrientation == Surface.ROTATION_270); + DisplayDeviceInfo info = getDisplayDeviceInfoLocked(); + viewport.deviceWidth = isRotated ? info.height : info.width; + viewport.deviceHeight = isRotated ? info.width : info.height; } /** diff --git a/services/java/com/android/server/display/DisplayViewport.java b/services/java/com/android/server/display/DisplayViewport.java index ed4016d..5080556 100644 --- a/services/java/com/android/server/display/DisplayViewport.java +++ b/services/java/com/android/server/display/DisplayViewport.java @@ -44,12 +44,20 @@ public final class DisplayViewport { // should be scaled or translated after rotation. public final Rect physicalFrame = new Rect(); + // The full width and height of the display device, rotated in the same + // manner as physicalFrame. This expresses the full native size of the display device. + // The physical frame should usually fit within this area. + public int deviceWidth; + public int deviceHeight; + public void copyFrom(DisplayViewport viewport) { valid = viewport.valid; displayId = viewport.displayId; orientation = viewport.orientation; logicalFrame.set(viewport.logicalFrame); physicalFrame.set(viewport.physicalFrame); + deviceWidth = viewport.deviceWidth; + deviceHeight = viewport.deviceHeight; } // For debugging purposes. @@ -60,6 +68,8 @@ public final class DisplayViewport { + ", orientation=" + orientation + ", logicalFrame=" + logicalFrame + ", physicalFrame=" + physicalFrame + + ", deviceWidth=" + deviceWidth + + ", deviceHeight=" + deviceHeight + "}"; } } diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java index 95655a5..805818a 100644 --- a/services/java/com/android/server/input/InputManagerService.java +++ b/services/java/com/android/server/input/InputManagerService.java @@ -149,7 +149,8 @@ public class InputManagerService extends IInputManager.Stub private static native void nativeSetDisplayViewport(int ptr, boolean external, int displayId, int rotation, int logicalLeft, int logicalTop, int logicalRight, int logicalBottom, - int physicalLeft, int physicalTop, int physicalRight, int physicalBottom); + int physicalLeft, int physicalTop, int physicalRight, int physicalBottom, + int deviceWidth, int deviceHeight); private static native int nativeGetScanCodeState(int ptr, int deviceId, int sourceMask, int scanCode); @@ -305,7 +306,8 @@ public class InputManagerService extends IInputManager.Stub viewport.logicalFrame.left, viewport.logicalFrame.top, viewport.logicalFrame.right, viewport.logicalFrame.bottom, viewport.physicalFrame.left, viewport.physicalFrame.top, - viewport.physicalFrame.right, viewport.physicalFrame.bottom); + viewport.physicalFrame.right, viewport.physicalFrame.bottom, + viewport.deviceWidth, viewport.deviceHeight); } /** diff --git a/services/java/com/android/server/location/ComprehensiveCountryDetector.java b/services/java/com/android/server/location/ComprehensiveCountryDetector.java index 1026a0d..354858b 100755 --- a/services/java/com/android/server/location/ComprehensiveCountryDetector.java +++ b/services/java/com/android/server/location/ComprehensiveCountryDetector.java @@ -384,8 +384,8 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { } protected boolean isAirplaneModeOff() { - return Settings.System.getInt( - mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) == 0; + return Settings.Global.getInt( + mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) == 0; } /** diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java index 3329acb..4268ae0 100644 --- a/services/java/com/android/server/pm/Installer.java +++ b/services/java/com/android/server/pm/Installer.java @@ -359,6 +359,14 @@ class Installer { return execute("movefiles"); } + /** + * Links the native library directory in an application's directory to its + * real location. + * + * @param dataPath data directory where the application is + * @param nativeLibPath target native library path + * @return -1 on error + */ public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) { if (dataPath == null) { Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null"); diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 4bb6e38..b5ae214 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -25,6 +25,11 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; import static com.android.internal.util.ArrayUtils.appendInt; import static com.android.internal.util.ArrayUtils.removeInt; import static libcore.io.OsConstants.S_ISLNK; +import static libcore.io.OsConstants.S_IRWXU; +import static libcore.io.OsConstants.S_IRGRP; +import static libcore.io.OsConstants.S_IXGRP; +import static libcore.io.OsConstants.S_IROTH; +import static libcore.io.OsConstants.S_IXOTH; import com.android.internal.app.IMediaContainerService; import com.android.internal.app.ResolverActivity; @@ -147,6 +152,7 @@ import java.util.Set; import libcore.io.ErrnoException; import libcore.io.IoUtils; import libcore.io.Libcore; +import libcore.io.OsConstants; import libcore.io.StructStat; /** @@ -276,7 +282,7 @@ public class PackageManagerService extends IPackageManager.Stub { // This is the object monitoring mDrmAppPrivateInstallDir. final FileObserver mDrmAppInstallObserver; - // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages + // Used for privilege escalation. MUST NOT BE CALLED WITH mPackages // LOCK HELD. Can be called with mInstallLock held. final Installer mInstaller; @@ -286,6 +292,12 @@ public class PackageManagerService extends IPackageManager.Stub { final File mAppInstallDir; final File mDalvikCacheDir; + /** + * Directory to which applications installed internally have native + * libraries copied. + */ + private File mAppLibInstallDir; + // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked // apps. final File mDrmAppPrivateInstallDir; @@ -1215,6 +1227,7 @@ public class PackageManagerService extends IPackageManager.Stub { } mAppInstallDir = new File(dataDir, "app"); + mAppLibInstallDir = new File(dataDir, "app-lib"); //look for any incomplete package installations ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr(); //clean up list @@ -3607,6 +3620,13 @@ public class PackageManagerService extends IPackageManager.Stub { res = resInner; } } + + final File nativeLibraryFile = new File(mAppLibInstallDir, packageName); + NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile); + if (!nativeLibraryFile.delete()) { + Slog.w(TAG, "Couldn't delete native library directory " + nativeLibraryFile.getPath()); + } + return res; } @@ -4048,9 +4068,7 @@ public class PackageManagerService extends IPackageManager.Stub { */ if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) { if (pkgSetting.nativeLibraryPathString == null) { - final String nativeLibraryPath = new File(dataPath, LIB_DIR_NAME).getPath(); - pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath; - pkgSetting.nativeLibraryPathString = nativeLibraryPath; + setInternalAppNativeLibraryPath(pkg, pkgSetting); } else { pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString; } @@ -4072,7 +4090,7 @@ public class PackageManagerService extends IPackageManager.Stub { */ if (pkg.applicationInfo.nativeLibraryDir != null) { try { - final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir); + File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir); final String dataPathString = dataPath.getCanonicalPath(); if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) { @@ -4087,30 +4105,31 @@ public class PackageManagerService extends IPackageManager.Stub { Log.i(TAG, "removed obsolete native libraries for system package " + path); } - } else if (nativeLibraryDir.getParentFile().getCanonicalPath() - .equals(dataPathString)) { - /* - * Make sure the native library dir isn't a symlink to - * something. If it is, ask installd to remove it and create - * a directory so we can copy to it afterwards. - */ - boolean isSymLink; - try { - isSymLink = S_ISLNK(Libcore.os.lstat(nativeLibraryDir.getPath()).st_mode); - } catch (ErrnoException e) { - // This shouldn't happen, but we'll fail-safe. - isSymLink = true; + } else if (!isForwardLocked(pkg) && !isExternal(pkg)) { + // Update native library dir if it starts with /data/data + if (nativeLibraryDir.getParent().startsWith(dataPathString)) { + setInternalAppNativeLibraryPath(pkg, pkgSetting); + nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir); } - if (isSymLink) { - mInstaller.unlinkNativeLibraryDirectory(dataPathString); + + try { + if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) { + Slog.e(TAG, "Unable to copy native libraries"); + mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; + return null; + } + } catch (IOException e) { + Slog.e(TAG, "Unable to copy native libraries", e); + mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; + return null; } - /* - * If this is an internal application or our - * nativeLibraryPath points to our data directory, unpack - * the libraries if necessary. - */ - NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir); + if (mInstaller.linkNativeLibraryDirectory(dataPathString, + pkg.applicationInfo.nativeLibraryDir) == -1) { + Slog.e(TAG, "Unable to link native library directory"); + mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; + return null; + } } else { Slog.i(TAG, "Linking native library dir for " + path); int ret = mInstaller.linkNativeLibraryDirectory(dataPathString, @@ -4122,7 +4141,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } } catch (IOException ioe) { - Log.e(TAG, "Unable to get canonical file " + ioe.toString()); + Slog.e(TAG, "Unable to get canonical file " + ioe.toString()); } } pkg.mScanPath = path; @@ -4437,6 +4456,37 @@ public class PackageManagerService extends IPackageManager.Stub { return pkg; } + private void setInternalAppNativeLibraryPath(PackageParser.Package pkg, + PackageSetting pkgSetting) { + final String apkLibPath = getApkName(pkgSetting.codePathString); + final String nativeLibraryPath = new File(mAppLibInstallDir, apkLibPath).getPath(); + pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath; + pkgSetting.nativeLibraryPathString = nativeLibraryPath; + } + + private static int copyNativeLibrariesForInternalApp(File scanFile, final File nativeLibraryDir) + throws IOException { + if (!nativeLibraryDir.isDirectory()) { + nativeLibraryDir.delete(); + if (!nativeLibraryDir.mkdir()) { + throw new IOException("Cannot create " + nativeLibraryDir.getPath()); + } + try { + Libcore.os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH + | S_IXOTH); + } catch (ErrnoException e) { + throw new IOException("Cannot chmod native library directory " + + nativeLibraryDir.getPath(), e); + } + } + + /* + * If this is an internal application or our nativeLibraryPath points to + * the app-lib directory, unpack the libraries if necessary. + */ + return NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir); + } + private void killApplication(String pkgName, int appId) { // Request the ActivityManager to kill the process(only for existing packages) // so that we do not end up in a confused state while the user is still using the older @@ -6737,7 +6787,7 @@ public class PackageManagerService extends IPackageManager.Stub { String apkName = getNextCodePath(null, pkgName, ".apk"); codeFileName = new File(installDir, apkName + ".apk").getPath(); resourceFileName = getResourcePathFromCodePath(); - libraryPath = new File(dataDir, LIB_DIR_NAME).getPath(); + libraryPath = new File(mAppLibInstallDir, pkgName).getPath(); } boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException { @@ -6774,6 +6824,7 @@ public class PackageManagerService extends IPackageManager.Stub { installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir; codeFileName = createTempPackageFile(installDir).getPath(); resourceFileName = getResourcePathFromCodePath(); + libraryPath = getLibraryPathFromCodePath(); created = true; } @@ -6828,6 +6879,23 @@ public class PackageManagerService extends IPackageManager.Stub { return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } } + + final File nativeLibraryFile = new File(getNativeLibraryPath()); + Slog.i(TAG, "Copying native libraries to " + nativeLibraryFile.getPath()); + if (nativeLibraryFile.exists()) { + NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile); + nativeLibraryFile.delete(); + } + try { + int copyRet = copyNativeLibrariesForInternalApp(codeFile, nativeLibraryFile); + if (copyRet != PackageManager.INSTALL_SUCCEEDED) { + return copyRet; + } + } catch (IOException e) { + Slog.e(TAG, "Copying native libraries failed", e); + ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; + } + return ret; } @@ -6845,6 +6913,7 @@ public class PackageManagerService extends IPackageManager.Stub { } else { final File oldCodeFile = new File(getCodePath()); final File oldResourceFile = new File(getResourcePath()); + final File oldLibraryFile = new File(getNativeLibraryPath()); // Rename APK file based on packageName final String apkName = getNextCodePath(oldCodePath, pkgName, ".apk"); @@ -6859,7 +6928,20 @@ public class PackageManagerService extends IPackageManager.Stub { if (isFwdLocked() && !oldResourceFile.renameTo(newResFile)) { return false; } - resourceFileName = getResourcePathFromCodePath(); + resourceFileName = newResFile.getPath(); + + // Rename library path + final File newLibraryFile = new File(getLibraryPathFromCodePath()); + if (newLibraryFile.exists()) { + NativeLibraryHelper.removeNativeBinariesFromDirLI(newLibraryFile); + newLibraryFile.delete(); + } + if (!oldLibraryFile.renameTo(newLibraryFile)) { + Slog.e(TAG, "Cannot rename native library directory " + + oldLibraryFile.getPath() + " to " + newLibraryFile.getPath()); + return false; + } + libraryPath = newLibraryFile.getPath(); // Attempt to set permissions if (!setPermissions()) { @@ -6910,8 +6992,15 @@ public class PackageManagerService extends IPackageManager.Stub { } } + private String getLibraryPathFromCodePath() { + return new File(mAppLibInstallDir, getApkName(getCodePath())).getPath(); + } + @Override String getNativeLibraryPath() { + if (libraryPath == null) { + libraryPath = getLibraryPathFromCodePath(); + } return libraryPath; } @@ -6937,6 +7026,15 @@ public class PackageManagerService extends IPackageManager.Stub { publicSourceFile.delete(); } } + + if (libraryPath != null) { + File nativeLibraryFile = new File(libraryPath); + NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile); + if (!nativeLibraryFile.delete()) { + Slog.w(TAG, "Couldn't delete native library directory " + libraryPath); + } + } + return ret; } @@ -9779,31 +9877,26 @@ public class PackageManagerService extends IPackageManager.Stub { final String newNativePath = mp.targetArgs .getNativeLibraryPath(); - try { - final File newNativeDir = new File(newNativePath); + final File newNativeDir = new File(newNativePath); - final String libParentDir = newNativeDir.getParentFile() - .getCanonicalPath(); - if (newNativeDir.getParentFile().getCanonicalPath() - .equals(pkg.applicationInfo.dataDir)) { - if (mInstaller - .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) { + if (!isForwardLocked(pkg) && !isExternal(pkg)) { + synchronized (mInstallLock) { + if (mInstaller.linkNativeLibraryDirectory( + pkg.applicationInfo.dataDir, newNativePath) < 0) { returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE; - } else { - NativeLibraryHelper.copyNativeBinariesIfNeededLI( - new File(newCodePath), newNativeDir); } - } else { + } + NativeLibraryHelper.copyNativeBinariesIfNeededLI(new File( + newCodePath), newNativeDir); + } else { + synchronized (mInstallLock) { if (mInstaller.linkNativeLibraryDirectory( pkg.applicationInfo.dataDir, newNativePath) < 0) { returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE; } } - } catch (IOException e) { - returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION; } - if (returnCode == PackageManager.MOVE_SUCCEEDED) { pkg.mPath = newCodePath; // Move dex files around diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java index 5ff8a9b..aa18ee4 100644 --- a/services/java/com/android/server/wm/InputMonitor.java +++ b/services/java/com/android/server/wm/InputMonitor.java @@ -19,11 +19,13 @@ package com.android.server.wm; import com.android.server.input.InputManagerService; import com.android.server.input.InputApplicationHandle; import com.android.server.input.InputWindowHandle; +import com.android.server.wm.WindowManagerService.AllWindowsIterator; import android.graphics.Rect; import android.os.RemoteException; import android.util.Log; import android.util.Slog; +import android.view.Display; import android.view.InputChannel; import android.view.KeyEvent; import android.view.WindowManager; @@ -225,10 +227,11 @@ final class InputMonitor implements InputManagerService.Callbacks { addInputWindowHandleLw(mService.mFakeWindows.get(i).mWindowHandle); } - // TODO(multidisplay): Input only occurs on the default display. - final WindowList windows = mService.getDefaultWindowList(); - for (int i = windows.size() - 1; i >= 0; i--) { - final WindowState child = windows.get(i); + // Add all windows on the default display. + final AllWindowsIterator iterator = mService.new AllWindowsIterator( + WindowManagerService.REVERSE_ITERATOR); + while (iterator.hasNext()) { + final WindowState child = iterator.next(); final InputChannel inputChannel = child.mInputChannel; final InputWindowHandle inputWindowHandle = child.mInputWindowHandle; if (inputChannel == null || inputWindowHandle == null || child.mRemoved) { @@ -243,15 +246,16 @@ final class InputMonitor implements InputManagerService.Callbacks { final boolean isVisible = child.isVisibleLw(); final boolean hasWallpaper = (child == mService.mWallpaperTarget) && (type != WindowManager.LayoutParams.TYPE_KEYGUARD); + final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY); // If there's a drag in progress and 'child' is a potential drop target, // make sure it's been told about the drag - if (inDrag && isVisible) { + if (inDrag && isVisible && onDefaultDisplay) { mService.mDragState.sendDragStartedIfNeededLw(child); } if (universeBackground != null && !addedUniverse - && child.mBaseLayer < aboveUniverseLayer) { + && child.mBaseLayer < aboveUniverseLayer && onDefaultDisplay) { final WindowState u = universeBackground.mWin; if (u.mInputChannel != null && u.mInputWindowHandle != null) { addInputWindowHandleLw(u.mInputWindowHandle, u, u.mAttrs.flags, diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index cdca8bc..17f4a96 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -434,6 +434,7 @@ public class WindowManagerService extends IWindowManager.Stub final float[] mTmpFloats = new float[9]; + boolean mDisplayReady; boolean mSafeMode; boolean mDisplayEnabled = false; boolean mSystemBooted = false; @@ -503,8 +504,6 @@ public class WindowManagerService extends IWindowManager.Stub final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>(); final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>(); - Display mDefaultDisplay; - boolean mIsTouchDevice; final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); @@ -2085,7 +2084,7 @@ public class WindowManagerService extends IWindowManager.Stub long origId; synchronized(mWindowMap) { - if (mDefaultDisplay == null) { + if (!mDisplayReady) { throw new IllegalStateException("Display has not been initialialized"); } @@ -5604,8 +5603,10 @@ public class WindowManagerService extends IWindowManager.Stub ">>> OPEN TRANSACTION showStrictModeViolation"); Surface.openTransaction(); try { + // TODO(multi-display): support multiple displays if (mStrictModeFlash == null) { - mStrictModeFlash = new StrictModeFlash(mDefaultDisplay, mFxSession); + mStrictModeFlash = new StrictModeFlash( + getDefaultDisplayContent().getDisplay(), mFxSession); } mStrictModeFlash.setVisibility(on); } finally { @@ -5718,7 +5719,7 @@ public class WindowManagerService extends IWindowManager.Stub } // The screenshot API does not apply the current screen rotation. - rot = mDefaultDisplay.getRotation(); + rot = getDefaultDisplayContent().getDisplay().getRotation(); int fw = frame.width(); int fh = frame.height(); @@ -6751,7 +6752,7 @@ public class WindowManagerService extends IWindowManager.Stub } boolean computeScreenConfigurationLocked(Configuration config) { - if (mDefaultDisplay == null) { + if (!mDisplayReady) { return false; } @@ -6785,13 +6786,8 @@ public class WindowManagerService extends IWindowManager.Stub } if (config != null) { - int orientation = Configuration.ORIENTATION_SQUARE; - if (dw < dh) { - orientation = Configuration.ORIENTATION_PORTRAIT; - } else if (dw > dh) { - orientation = Configuration.ORIENTATION_LANDSCAPE; - } - config.orientation = orientation; + config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : + Configuration.ORIENTATION_LANDSCAPE; } // Update application display metrics. @@ -6958,9 +6954,12 @@ public class WindowManagerService extends IWindowManager.Stub synchronized (mWindowMap) { try { if (mDragState == null) { + // TODO(multi-display): support other displays + final DisplayContent displayContent = getDefaultDisplayContent(); + final Display display = displayContent.getDisplay(); Surface surface = new Surface(session, "drag surface", width, height, PixelFormat.TRANSLUCENT, Surface.HIDDEN); - surface.setLayerStack(mDefaultDisplay.getLayerStack()); + surface.setLayerStack(display.getLayerStack()); if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " + surface + ": CREATE"); outSurface.copyFrom(surface); @@ -7102,26 +7101,28 @@ public class WindowManagerService extends IWindowManager.Stub } public void displayReady() { - WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); - final Display display = wm.getDefaultDisplay(); - displayReady(display.getDisplayId()); + displayReady(Display.DEFAULT_DISPLAY); synchronized(mWindowMap) { - readForcedDisplaySizeAndDensityLocked(getDefaultDisplayContent()); + final DisplayContent displayContent = getDefaultDisplayContent(); + final Display display = displayContent.getDisplay(); + readForcedDisplaySizeAndDensityLocked(displayContent); - mDefaultDisplay = display; + mDisplayReady = true; mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_TOUCHSCREEN); + PackageManager.FEATURE_TOUCHSCREEN); mAnimator.initializeLocked(display.getLayerStack()); final DisplayInfo displayInfo = getDefaultDisplayInfo(); - mAnimator.setDisplayDimensions(displayInfo.logicalWidth, displayInfo.logicalHeight, - displayInfo.appWidth, displayInfo.appHeight); + mAnimator.setDisplayDimensions( + displayInfo.logicalWidth, displayInfo.logicalHeight, + displayInfo.appWidth, displayInfo.appHeight); - final DisplayContent displayContent = getDefaultDisplayContent(); - mPolicy.setInitialDisplaySize(mDefaultDisplay, displayContent.mInitialDisplayWidth, - displayContent.mInitialDisplayHeight, displayContent.mInitialDisplayDensity); + mPolicy.setInitialDisplaySize(displayContent.getDisplay(), + displayContent.mInitialDisplayWidth, + displayContent.mInitialDisplayHeight, + displayContent.mInitialDisplayDensity); } try { @@ -7802,6 +7803,7 @@ public class WindowManagerService extends IWindowManager.Stub } // TODO(multidisplay): For now rotations are only main screen. final DisplayContent displayContent = getDefaultDisplayContent(); + final Display display = displayContent.getDisplay(); if (displayContent.mBaseDisplayWidth < displayContent.mInitialDisplayWidth || displayContent.mBaseDisplayHeight < displayContent.mInitialDisplayHeight) { int initW, initH, baseW, baseH; @@ -7829,7 +7831,7 @@ public class WindowManagerService extends IWindowManager.Stub Rect inner = new Rect(0, 0, baseW, baseH); try { mBlackFrame = new BlackFrame(mFxSession, outer, inner, MASK_LAYER, - mDefaultDisplay.getLayerStack()); + display.getLayerStack()); } catch (Surface.OutOfResourcesException e) { } } @@ -7929,8 +7931,10 @@ public class WindowManagerService extends IWindowManager.Stub private void reconfigureDisplayLocked(DisplayContent displayContent) { // TODO: Multidisplay: for now only use with default display. - mPolicy.setInitialDisplaySize(mDefaultDisplay, displayContent.mBaseDisplayWidth, - displayContent.mBaseDisplayHeight, displayContent.mBaseDisplayDensity); + mPolicy.setInitialDisplaySize(displayContent.getDisplay(), + displayContent.mBaseDisplayWidth, + displayContent.mBaseDisplayHeight, + displayContent.mBaseDisplayDensity); displayContent.layoutNeeded = true; @@ -8154,7 +8158,7 @@ public class WindowManagerService extends IWindowManager.Stub return; } - if (mDefaultDisplay == null) { + if (!mDisplayReady) { // Not yet initialized, nothing to do. return; } @@ -8600,11 +8604,14 @@ public class WindowManagerService extends IWindowManager.Stub Rect dirty = new Rect(0, 0, mNextAppTransitionThumbnail.getWidth(), mNextAppTransitionThumbnail.getHeight()); try { + // TODO(multi-display): support other displays + final DisplayContent displayContent = getDefaultDisplayContent(); + final Display display = displayContent.getDisplay(); Surface surface = new Surface(mFxSession, "thumbnail anim", dirty.width(), dirty.height(), PixelFormat.TRANSLUCENT, Surface.HIDDEN); - surface.setLayerStack(mDefaultDisplay.getLayerStack()); + surface.setLayerStack(display.getLayerStack()); topOpeningApp.mAppAnimator.thumbnail = surface; if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surface + ": CREATE"); @@ -9857,7 +9864,7 @@ public class WindowManagerService extends IWindowManager.Stub return; } - if (mDefaultDisplay == null || !mPolicy.isScreenOnFully()) { + if (!mDisplayReady || !mPolicy.isScreenOnFully()) { // No need to freeze the screen before the system is ready or if // the screen is off. return; @@ -9889,10 +9896,12 @@ public class WindowManagerService extends IWindowManager.Stub } // TODO(multidisplay): rotation on main screen only. - DisplayInfo displayInfo = getDefaultDisplayContent().getDisplayInfo(); + final DisplayContent displayContent = getDefaultDisplayContent(); + final Display display = displayContent.getDisplay(); + final DisplayInfo displayInfo = displayContent.getDisplayInfo(); mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext, - mDefaultDisplay, mFxSession, inTransaction, displayInfo.logicalWidth, - displayInfo.logicalHeight, mDefaultDisplay.getRotation()); + display, mFxSession, inTransaction, displayInfo.logicalWidth, + displayInfo.logicalHeight, display.getRotation()); } } @@ -10003,8 +10012,8 @@ public class WindowManagerService extends IWindowManager.Stub if (line != null) { String[] toks = line.split("%"); if (toks != null && toks.length > 0) { - mWatermark = - new Watermark(mDefaultDisplay, mRealDisplayMetrics, mFxSession, toks); + mWatermark = new Watermark(getDefaultDisplayContent().getDisplay(), + mRealDisplayMetrics, mFxSession, toks); } } } catch (FileNotFoundException e) { @@ -10372,7 +10381,7 @@ public class WindowManagerService extends IWindowManager.Stub } } pw.println(); - if (mDefaultDisplay != null) { + if (mDisplayReady) { DisplayContentsIterator dCIterator = new DisplayContentsIterator(); while (dCIterator.hasNext()) { dCIterator.next().dump(pw); @@ -10744,7 +10753,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - boolean REVERSE_ITERATOR = true; + final static boolean REVERSE_ITERATOR = true; class AllWindowsIterator implements Iterator<WindowState> { private DisplayContent mDisplayContent; private DisplayContentsIterator mDisplayContentsIterator; @@ -10804,9 +10813,7 @@ public class WindowManagerService extends IWindowManager.Stub } public DisplayContent getDefaultDisplayContent() { - final int displayId = mDefaultDisplay == null - ? Display.DEFAULT_DISPLAY : mDefaultDisplay.getDisplayId(); - return getDisplayContent(displayId); + return getDisplayContent(Display.DEFAULT_DISPLAY); } public WindowList getDefaultWindowList() { diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp index 5e36bf8..319cacd 100644 --- a/services/jni/com_android_server_input_InputManagerService.cpp +++ b/services/jni/com_android_server_input_InputManagerService.cpp @@ -993,7 +993,8 @@ static void nativeStart(JNIEnv* env, jclass clazz, jint ptr) { static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz, jint ptr, jboolean external, jint displayId, jint orientation, jint logicalLeft, jint logicalTop, jint logicalRight, jint logicalBottom, - jint physicalLeft, jint physicalTop, jint physicalRight, jint physicalBottom) { + jint physicalLeft, jint physicalTop, jint physicalRight, jint physicalBottom, + jint deviceWidth, jint deviceHeight) { NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); DisplayViewport v; @@ -1007,6 +1008,8 @@ static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz, jint ptr, jboole v.physicalTop = physicalTop; v.physicalRight = physicalRight; v.physicalBottom = physicalBottom; + v.deviceWidth = deviceWidth; + v.deviceHeight = deviceHeight; im->setDisplayViewport(external, v); } @@ -1288,7 +1291,7 @@ static JNINativeMethod gInputManagerMethods[] = { (void*) nativeInit }, { "nativeStart", "(I)V", (void*) nativeStart }, - { "nativeSetDisplayViewport", "(IZIIIIIIIIII)V", + { "nativeSetDisplayViewport", "(IZIIIIIIIIIIII)V", (void*) nativeSetDisplayViewport }, { "nativeGetScanCodeState", "(IIII)I", (void*) nativeGetScanCodeState }, diff --git a/services/jni/com_android_server_input_InputWindowHandle.cpp b/services/jni/com_android_server_input_InputWindowHandle.cpp index 01fb781..6692994 100644 --- a/services/jni/com_android_server_input_InputWindowHandle.cpp +++ b/services/jni/com_android_server_input_InputWindowHandle.cpp @@ -52,6 +52,7 @@ static struct { jfieldID ownerPid; jfieldID ownerUid; jfieldID inputFeatures; + jfieldID displayId; } gInputWindowHandleClassInfo; static Mutex gHandleMutex; @@ -151,6 +152,8 @@ bool NativeInputWindowHandle::updateInfo() { gInputWindowHandleClassInfo.ownerUid); mInfo->inputFeatures = env->GetIntField(obj, gInputWindowHandleClassInfo.inputFeatures); + mInfo->displayId = env->GetIntField(obj, + gInputWindowHandleClassInfo.displayId); env->DeleteLocalRef(obj); return true; @@ -291,6 +294,9 @@ int register_android_server_InputWindowHandle(JNIEnv* env) { GET_FIELD_ID(gInputWindowHandleClassInfo.inputFeatures, clazz, "inputFeatures", "I"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.displayId, clazz, + "displayId", "I"); return 0; } |
