diff options
Diffstat (limited to 'services/java')
30 files changed, 1879 insertions, 1248 deletions
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java index 0574405..32ac8e1 100644 --- a/services/java/com/android/server/AlarmManagerService.java +++ b/services/java/com/android/server/AlarmManagerService.java @@ -34,9 +34,9 @@ import android.os.Message; import android.os.PowerManager; import android.os.SystemClock; import android.os.SystemProperties; +import android.os.WorkSource; import android.text.TextUtils; import android.text.format.Time; -import android.util.EventLog; import android.util.Slog; import android.util.TimeUtils; @@ -50,6 +50,7 @@ import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedList; import java.util.Map; import java.util.TimeZone; @@ -89,6 +90,7 @@ class AlarmManagerService extends IAlarmManager.Stub { private int mDescriptor; private int mBroadcastRefCount = 0; private PowerManager.WakeLock mWakeLock; + private LinkedList<PendingIntent> mInFlight = new LinkedList<PendingIntent>(); private final AlarmThread mWaitThread = new AlarmThread(); private final AlarmHandler mHandler = new AlarmHandler(); private ClockReceiver mClockReceiver; @@ -668,10 +670,12 @@ class AlarmManagerService extends IAlarmManager.Stub { Intent.EXTRA_ALARM_COUNT, alarm.count), mResultReceiver, mHandler); - // we have an active broadcast so stay awake. + // we have an active broadcast so stay awake. if (mBroadcastRefCount == 0) { + setWakelockWorkSource(alarm.operation); mWakeLock.acquire(); } + mInFlight.add(alarm.operation); mBroadcastRefCount++; BroadcastStats bs = getStatsLocked(alarm.operation); @@ -700,7 +704,22 @@ class AlarmManagerService extends IAlarmManager.Stub { } } } - + + void setWakelockWorkSource(PendingIntent pi) { + try { + final int uid = ActivityManagerNative.getDefault() + .getUidForIntentSender(pi.getTarget()); + if (uid >= 0) { + mWakeLock.setWorkSource(new WorkSource(uid)); + return; + } + } catch (Exception e) { + } + + // Something went wrong; fall back to attributing the lock to the OS + mWakeLock.setWorkSource(null); + } + private class AlarmHandler extends Handler { public static final int ALARM_EVENT = 1; public static final int MINUTE_CHANGE_EVENT = 2; @@ -876,9 +895,20 @@ class AlarmManagerService extends IAlarmManager.Stub { fs.count++; } } + mInFlight.removeFirst(); mBroadcastRefCount--; if (mBroadcastRefCount == 0) { mWakeLock.release(); + } else { + // the next of our alarms is now in flight. reattribute the wakelock. + final PendingIntent nowInFlight = mInFlight.peekFirst(); + if (nowInFlight != null) { + setWakelockWorkSource(nowInFlight); + } else { + // should never happen + Slog.e(TAG, "Alarm wakelock still held but sent queue empty"); + mWakeLock.setWorkSource(null); + } } } } diff --git a/services/java/com/android/server/NsdService.java b/services/java/com/android/server/NsdService.java new file mode 100644 index 0000000..768be7d --- /dev/null +++ b/services/java/com/android/server/NsdService.java @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.net.nsd.DnsSdServiceInfo; +import android.net.nsd.DnsSdTxtRecord; +import android.net.nsd.INsdManager; +import android.net.nsd.NsdManager; +import android.os.Binder; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Message; +import android.os.Messenger; +import android.os.IBinder; +import android.util.Slog; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.List; + +import com.android.internal.app.IBatteryStats; +import com.android.internal.telephony.TelephonyIntents; +import com.android.internal.util.AsyncChannel; +import com.android.server.am.BatteryStatsService; +import com.android.server.NativeDaemonConnector.Command; +import com.android.internal.R; + +/** + * Network Service Discovery Service handles remote service discovery operation requests by + * implementing the INsdManager interface. + * + * @hide + */ +public class NsdService extends INsdManager.Stub { + private static final String TAG = "NsdService"; + private static final String MDNS_TAG = "mDnsConnector"; + + private static final boolean DBG = true; + + private Context mContext; + + /** + * Clients receiving asynchronous messages + */ + private List<AsyncChannel> mClients = new ArrayList<AsyncChannel>(); + + private AsyncChannel mReplyChannel = new AsyncChannel(); + + /** + * Handles client(app) connections + */ + private class AsyncServiceHandler extends Handler { + + AsyncServiceHandler(android.os.Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: + if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { + AsyncChannel c = (AsyncChannel) msg.obj; + if (DBG) Slog.d(TAG, "New client listening to asynchronous messages"); + c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED); + mClients.add(c); + } else { + Slog.e(TAG, "Client connection failure, error=" + msg.arg1); + } + break; + case AsyncChannel.CMD_CHANNEL_DISCONNECTED: + if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) { + Slog.e(TAG, "Send failed, client connection lost"); + } else { + if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); + } + mClients.remove((AsyncChannel) msg.obj); + break; + case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: + AsyncChannel ac = new AsyncChannel(); + ac.connect(mContext, this, msg.replyTo); + break; + case NsdManager.DISCOVER_SERVICES: + if (DBG) Slog.d(TAG, "Discover services"); + DnsSdServiceInfo s = (DnsSdServiceInfo) msg.obj; + discoverServices(1, s.getServiceType()); + mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED); + break; + case NsdManager.STOP_DISCOVERY: + if (DBG) Slog.d(TAG, "Stop service discovery"); + mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED); + break; + case NsdManager.REGISTER_SERVICE: + if (DBG) Slog.d(TAG, "Register service"); + mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED); + break; + case NsdManager.UPDATE_SERVICE: + if (DBG) Slog.d(TAG, "Update service"); + mReplyChannel.replyToMessage(msg, NsdManager.UPDATE_SERVICE_FAILED); + break; + default: + Slog.d(TAG, "NsdServicehandler.handleMessage ignoring msg=" + msg); + break; + } + } + } + private AsyncServiceHandler mAsyncServiceHandler; + + private NativeDaemonConnector mNativeConnector; + private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1); + + private NsdService(Context context) { + mContext = context; + + HandlerThread nsdThread = new HandlerThread("NsdService"); + nsdThread.start(); + mAsyncServiceHandler = new AsyncServiceHandler(nsdThread.getLooper()); + + /* + mNativeConnector = new NativeDaemonConnector(new NativeCallbackReceiver(), "mdns", 10, + MDNS_TAG, 25); + Thread th = new Thread(mNativeConnector, MDNS_TAG); + th.start(); + */ + } + + public static NsdService create(Context context) throws InterruptedException { + NsdService service = new NsdService(context); + /* service.mNativeDaemonConnected.await(); */ + return service; + } + + public Messenger getMessenger() { + return new Messenger(mAsyncServiceHandler); + } + + /* These should be in sync with system/netd/mDnsResponseCode.h */ + class NativeResponseCode { + public static final int SERVICE_FOUND = 101; + public static final int SERVICE_LOST = 102; + public static final int SERVICE_DISCOVERY_FAILED = 103; + + public static final int SERVICE_REGISTERED = 104; + public static final int SERVICE_REGISTRATION_FAILED = 105; + + public static final int SERVICE_UPDATED = 106; + public static final int SERVICE_UPDATE_FAILED = 107; + + public static final int SERVICE_RESOLVED = 108; + public static final int SERVICE_RESOLUTION_FAILED = 109; + } + + + class NativeCallbackReceiver implements INativeDaemonConnectorCallbacks { + public void onDaemonConnected() { + mNativeDaemonConnected.countDown(); + } + + public boolean onEvent(int code, String raw, String[] cooked) { + switch (code) { + case NativeResponseCode.SERVICE_FOUND: + /* NNN uniqueId serviceName regType */ + break; + case NativeResponseCode.SERVICE_LOST: + /* NNN uniqueId serviceName regType */ + break; + case NativeResponseCode.SERVICE_DISCOVERY_FAILED: + /* NNN uniqueId errorCode */ + break; + case NativeResponseCode.SERVICE_REGISTERED: + /* NNN regId serviceName regType */ + break; + case NativeResponseCode.SERVICE_REGISTRATION_FAILED: + /* NNN regId errorCode */ + break; + case NativeResponseCode.SERVICE_UPDATED: + /* NNN regId */ + break; + case NativeResponseCode.SERVICE_UPDATE_FAILED: + /* NNN regId errorCode */ + break; + case NativeResponseCode.SERVICE_RESOLVED: + /* NNN resolveId fullName hostName port txtlen txtdata */ + break; + case NativeResponseCode.SERVICE_RESOLUTION_FAILED: + /* NNN resovleId errorCode */ + break; + default: + break; + } + return false; + } + } + + private void registerService(int regId, DnsSdServiceInfo service) { + try { + //Add txtlen and txtdata + mNativeConnector.execute("mdnssd", "register", regId, service.getServiceName(), + service.getServiceType(), service.getPort()); + } catch(NativeDaemonConnectorException e) { + Slog.e(TAG, "Failed to execute registerService"); + } + } + + private void updateService(int regId, DnsSdTxtRecord t) { + try { + if (t == null) return; + mNativeConnector.execute("mdnssd", "update", regId, t.size(), t.getRawData()); + } catch(NativeDaemonConnectorException e) { + Slog.e(TAG, "Failed to updateServices"); + } + } + + private void discoverServices(int discoveryId, String serviceType) { + try { + mNativeConnector.execute("mdnssd", "discover", discoveryId, serviceType); + } catch(NativeDaemonConnectorException e) { + Slog.e(TAG, "Failed to discoverServices"); + } + } + + private void stopServiceDiscovery(int discoveryId) { + try { + mNativeConnector.execute("mdnssd", "stopdiscover", discoveryId); + } catch(NativeDaemonConnectorException e) { + Slog.e(TAG, "Failed to stopServiceDiscovery"); + } + } + + private void resolveService(DnsSdServiceInfo service) { + try { + mNativeConnector.execute("mdnssd", "resolve", service.getServiceName(), + service.getServiceType()); + } catch(NativeDaemonConnectorException e) { + Slog.e(TAG, "Failed to resolveService"); + } + } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump ServiceDiscoverService from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + pw.println("Internal state:"); + } +} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 423dad6..7dd736d 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -47,6 +47,7 @@ import android.view.WindowManager; import com.android.internal.app.ShutdownThread; import com.android.internal.os.BinderInternal; import com.android.internal.os.SamplingProfilerIntegration; +import com.android.internal.widget.LockSettingsService; import com.android.server.accessibility.AccessibilityManagerService; import com.android.server.am.ActivityManagerService; import com.android.server.net.NetworkPolicyManagerService; @@ -120,6 +121,7 @@ class ServerThread extends Thread { ConnectivityService connectivity = null; WifiP2pService wifiP2p = null; WifiService wifi = null; + NsdService serviceDiscovery= null; IPackageManager pm = null; Context context = null; WindowManagerService wm = null; @@ -219,6 +221,7 @@ class ServerThread extends Thread { factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL, !firstBoot); ServiceManager.addService(Context.WINDOW_SERVICE, wm); + ServiceManager.addService(Context.INPUT_SERVICE, wm.getInputManagerService()); ActivityManagerService.self().setWindowManager(wm); @@ -265,6 +268,7 @@ class ServerThread extends Thread { LocationManagerService location = null; CountryDetectorService countryDetector = null; TextServicesManagerService tsms = null; + LockSettingsService lockSettings = null; // Bring up services needed for UI. if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { @@ -307,6 +311,14 @@ class ServerThread extends Thread { if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { try { + Slog.i(TAG, "LockSettingsService"); + lockSettings = new LockSettingsService(context); + ServiceManager.addService("lock_settings", lockSettings); + } catch (Throwable e) { + reportWtf("starting LockSettingsService service", e); + } + + try { Slog.i(TAG, "Device Policy"); devicePolicy = new DevicePolicyManagerService(context); ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, devicePolicy); @@ -394,6 +406,15 @@ class ServerThread extends Thread { } try { + Slog.i(TAG, "Network Service Discovery Service"); + serviceDiscovery = NsdService.create(context); + ServiceManager.addService( + Context.NSD_SERVICE, serviceDiscovery); + } catch (Throwable e) { + reportWtf("starting Service Discovery Service", e); + } + + try { Slog.i(TAG, "Throttle Service"); throttle = new ThrottleService(context); ServiceManager.addService( @@ -651,6 +672,11 @@ class ServerThread extends Thread { } catch (Throwable e) { reportWtf("making Package Manager Service ready", e); } + try { + lockSettings.systemReady(); + } catch (Throwable e) { + reportWtf("making Lock Settings Service ready", e); + } // These are needed to propagate to the runnable below. final Context contextF = context; diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java index 8c8e725..1b1638a 100644 --- a/services/java/com/android/server/TelephonyRegistry.java +++ b/services/java/com/android/server/TelephonyRegistry.java @@ -29,6 +29,7 @@ import android.telephony.CellLocation; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SignalStrength; +import android.telephony.CellInfo; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Slog; @@ -107,6 +108,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private int mOtaspMode = ServiceStateTracker.OTASP_UNKNOWN; + private CellInfo mCellInfo = null; + static final int PHONE_STATE_PERMISSION_MASK = PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR | PhoneStateListener.LISTEN_CALL_STATE | @@ -236,6 +239,13 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { remove(r.binder); } } + if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) { + try { + r.callback.onCellInfoChanged(new CellInfo(mCellInfo)); + } catch (RemoteException ex) { + remove(r.binder); + } + } } } } else { @@ -325,6 +335,26 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { broadcastSignalStrengthChanged(signalStrength); } + public void notifyCellInfo(CellInfo cellInfo) { + if (!checkNotifyPermission("notifyCellInfo()")) { + return; + } + + synchronized (mRecords) { + mCellInfo = cellInfo; + for (Record r : mRecords) { + if ((r.events & PhoneStateListener.LISTEN_CELL_INFO) != 0) { + try { + r.callback.onCellInfoChanged(new CellInfo(cellInfo)); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + } + public void notifyMessageWaitingChanged(boolean mwi) { if (!checkNotifyPermission("notifyMessageWaitingChanged()")) { return; @@ -530,6 +560,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println(" mDataConnectionLinkProperties=" + mDataConnectionLinkProperties); pw.println(" mDataConnectionLinkCapabilities=" + mDataConnectionLinkCapabilities); pw.println(" mCellLocation=" + mCellLocation); + pw.println(" mCellInfo=" + mCellInfo); pw.println("registrations: count=" + recordCount); for (Record r : mRecords) { pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events)); @@ -655,6 +686,12 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } + if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_COARSE_LOCATION, null); + + } + if ((events & PHONE_STATE_PERMISSION_MASK) != 0) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.READ_PHONE_STATE, null); diff --git a/services/java/com/android/server/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java index 9b4eddc..53d1f0e 100644 --- a/services/java/com/android/server/WiredAccessoryObserver.java +++ b/services/java/com/android/server/WiredAccessoryObserver.java @@ -301,13 +301,13 @@ class WiredAccessoryObserver extends UEventObserver { // Pack up the values and broadcast them to everyone if (headset == BIT_USB_HEADSET_ANLG) { - intent = new Intent(Intent.ACTION_USB_ANLG_HEADSET_PLUG); + intent = new Intent(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra("state", state); intent.putExtra("name", headsetName); ActivityManagerNative.broadcastStickyIntent(intent, null); } else if (headset == BIT_USB_HEADSET_DGTL) { - intent = new Intent(Intent.ACTION_USB_DGTL_HEADSET_PLUG); + intent = new Intent(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra("state", state); intent.putExtra("name", headsetName); diff --git a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java index 769cb6a..31aa21e 100644 --- a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java +++ b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java @@ -16,7 +16,7 @@ package com.android.server.accessibility; -import com.android.server.wm.InputFilter; +import com.android.server.input.InputFilter; import android.content.Context; import android.util.Slog; diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java index 41cf9a6..d07aa7a 100644 --- a/services/java/com/android/server/accessibility/TouchExplorer.java +++ b/services/java/com/android/server/accessibility/TouchExplorer.java @@ -29,7 +29,7 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import com.android.server.accessibility.AccessibilityInputFilter.Explorer; -import com.android.server.wm.InputFilter; +import com.android.server.input.InputFilter; import java.util.Arrays; diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index a6fbdd7..80e59cd 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -62,10 +62,10 @@ import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentFilter; import android.content.IIntentReceiver; import android.content.IIntentSender; +import android.content.Intent; +import android.content.IntentFilter; import android.content.IntentSender; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; @@ -75,12 +75,12 @@ import android.content.pm.IPackageManager; import android.content.pm.InstrumentationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PathPermission; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; -import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Bitmap; @@ -113,10 +113,10 @@ import android.os.UserId; import android.provider.Settings; import android.text.format.Time; import android.util.EventLog; -import android.util.Pair; -import android.util.Slog; import android.util.Log; +import android.util.Pair; import android.util.PrintWriterPrinter; +import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.TimeUtils; @@ -140,7 +140,6 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.StringWriter; -import java.lang.IllegalStateException; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; @@ -4445,6 +4444,17 @@ public final class ActivityManagerService extends ActivityManagerNative return null; } + public int getUidForIntentSender(IIntentSender sender) { + if (sender instanceof PendingIntentRecord) { + try { + PendingIntentRecord res = (PendingIntentRecord)sender; + return res.uid; + } catch (ClassCastException e) { + } + } + return -1; + } + public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) { if (!(pendingResult instanceof PendingIntentRecord)) { return false; @@ -10263,6 +10273,29 @@ public final class ActivityManagerService extends ActivityManagerNative } pw.println(); pw.print("Total PSS: "); pw.print(totalPss); pw.println(" kB"); + final int[] SINGLE_LONG_FORMAT = new int[] { + Process.PROC_SPACE_TERM|Process.PROC_OUT_LONG + }; + long[] longOut = new long[1]; + Process.readProcFile("/sys/kernel/mm/ksm/pages_shared", + SINGLE_LONG_FORMAT, null, longOut, null); + long shared = longOut[0] * ProcessList.PAGE_SIZE / 1024; + longOut[0] = 0; + Process.readProcFile("/sys/kernel/mm/ksm/pages_sharing", + SINGLE_LONG_FORMAT, null, longOut, null); + long sharing = longOut[0] * ProcessList.PAGE_SIZE / 1024; + longOut[0] = 0; + Process.readProcFile("/sys/kernel/mm/ksm/pages_unshared", + SINGLE_LONG_FORMAT, null, longOut, null); + long unshared = longOut[0] * ProcessList.PAGE_SIZE / 1024; + longOut[0] = 0; + Process.readProcFile("/sys/kernel/mm/ksm/pages_volatile", + SINGLE_LONG_FORMAT, null, longOut, null); + long voltile = longOut[0] * ProcessList.PAGE_SIZE / 1024; + pw.print(" KSM: "); pw.print(sharing); pw.print(" kB saved from shared "); + pw.print(shared); pw.println(" kB"); + pw.print(" "); pw.print(unshared); pw.print(" kB unshared; "); + pw.print(voltile); pw.println(" kB volatile"); } } @@ -13281,6 +13314,102 @@ public final class ActivityManagerService extends ActivityManagerNative } } + @Override + public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity) { + ActivityRecord srec = ActivityRecord.forToken(token); + return srec.task.affinity != null && srec.task.affinity.equals(destAffinity); + } + + public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode, + Intent resultData) { + ComponentName dest = destIntent.getComponent(); + + synchronized (this) { + ActivityRecord srec = ActivityRecord.forToken(token); + ArrayList<ActivityRecord> history = srec.stack.mHistory; + final int start = history.indexOf(srec); + if (start < 0) { + // Current activity is not in history stack; do nothing. + return false; + } + int finishTo = start - 1; + ActivityRecord parent = null; + boolean foundParentInTask = false; + if (dest != null) { + TaskRecord tr = srec.task; + for (int i = start - 1; i >= 0; i--) { + ActivityRecord r = history.get(i); + if (tr != r.task) { + // Couldn't find parent in the same task; stop at the one above this. + // (Root of current task; in-app "home" behavior) + // Always at least finish the current activity. + finishTo = Math.min(start - 1, i + 1); + parent = history.get(finishTo); + break; + } else if (r.info.packageName.equals(dest.getPackageName()) && + r.info.name.equals(dest.getClassName())) { + finishTo = i; + parent = r; + foundParentInTask = true; + break; + } + } + } + + if (mController != null) { + ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0); + if (next != null) { + // ask watcher if this is allowed + boolean resumeOK = true; + try { + resumeOK = mController.activityResuming(next.packageName); + } catch (RemoteException e) { + mController = null; + } + + if (!resumeOK) { + return false; + } + } + } + final long origId = Binder.clearCallingIdentity(); + for (int i = start; i > finishTo; i--) { + ActivityRecord r = history.get(i); + mMainStack.requestFinishActivityLocked(r.appToken, resultCode, resultData, + "navigate-up"); + // Only return the supplied result for the first activity finished + resultCode = Activity.RESULT_CANCELED; + resultData = null; + } + + if (parent != null && foundParentInTask) { + final int parentLaunchMode = parent.info.launchMode; + final int destIntentFlags = destIntent.getFlags(); + if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE || + parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK || + parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP || + (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { + parent.deliverNewIntentLocked(srec.app.uid, destIntent); + } else { + try { + ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo( + destIntent.getComponent(), 0, UserId.getCallingUserId()); + int res = mMainStack.startActivityLocked(srec.app.thread, destIntent, + null, aInfo, parent.appToken, null, + 0, -1, parent.launchedFromUid, 0, null, true, null); + foundParentInTask = res == ActivityManager.START_SUCCESS; + } catch (RemoteException e) { + foundParentInTask = false; + } + mMainStack.requestFinishActivityLocked(parent.appToken, resultCode, + resultData, "navigate-up"); + } + } + Binder.restoreCallingIdentity(origId); + return foundParentInTask; + } + } + // ========================================================= // LIFETIME MANAGEMENT // ========================================================= diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index d60ff2b..a098f18 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -16,6 +16,7 @@ package com.android.server.am; +import com.android.internal.app.ResolverActivity; import com.android.server.AttributeCache; import com.android.server.am.ActivityStack.ActivityState; @@ -382,7 +383,7 @@ final class ActivityRecord { _intent.getData() == null && _intent.getType() == null && (intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && - !"android".equals(realActivity.getClassName())) { + !ResolverActivity.class.getName().equals(realActivity.getClassName())) { // This sure looks like a home activity! // Note the last check is so we don't count the resolver // activity as being home... really, we don't care about diff --git a/services/java/com/android/server/wm/InputApplicationHandle.java b/services/java/com/android/server/input/InputApplicationHandle.java index 1812f11..42c1052 100644 --- a/services/java/com/android/server/wm/InputApplicationHandle.java +++ b/services/java/com/android/server/input/InputApplicationHandle.java @@ -14,8 +14,7 @@ * limitations under the License. */ -package com.android.server.wm; - +package com.android.server.input; /** * Functions as a handle for an application that can receive input. @@ -30,7 +29,7 @@ public final class InputApplicationHandle { private int ptr; // The window manager's application window token. - public final AppWindowToken appWindowToken; + public final Object appWindowToken; // Application name. public String name; @@ -40,7 +39,7 @@ public final class InputApplicationHandle { private native void nativeDispose(); - public InputApplicationHandle(AppWindowToken appWindowToken) { + public InputApplicationHandle(Object appWindowToken) { this.appWindowToken = appWindowToken; } diff --git a/services/java/com/android/server/wm/InputFilter.java b/services/java/com/android/server/input/InputFilter.java index 8f0001a..2ce0a02 100644 --- a/services/java/com/android/server/wm/InputFilter.java +++ b/services/java/com/android/server/input/InputFilter.java @@ -14,7 +14,9 @@ * limitations under the License. */ -package com.android.server.wm; +package com.android.server.input; + +import com.android.server.wm.WindowManagerService; import android.os.Handler; import android.os.Looper; @@ -33,7 +35,7 @@ import android.view.WindowManagerPolicy; * system's behavior changes as follows: * <ul> * <li>Input events are first delivered to the {@link WindowManagerPolicy} - * interception methods before queueing as usual. This critical step takes care of managing + * interception methods before queuing as usual. This critical step takes care of managing * the power state of the device and handling wake keys.</li> * <li>Input events are then asynchronously delivered to the input filter's * {@link #onInputEvent(InputEvent)} method instead of being enqueued for dispatch to @@ -79,7 +81,7 @@ import android.view.WindowManagerPolicy; * {@link WindowManagerPolicy#FLAG_PASS_TO_USER} policy flag. The input filter may * sometimes receive events that do not have this flag set. It should take note of * the fact that the policy intends to drop the event, clean up its state, and - * then send appropriate cancelation events to the dispatcher if needed. + * then send appropriate cancellation events to the dispatcher if needed. * </p><p> * For example, suppose the input filter is processing a gesture and one of the touch events * it receives does not have the {@link WindowManagerPolicy#FLAG_PASS_TO_USER} flag set. @@ -89,8 +91,8 @@ import android.view.WindowManagerPolicy; * Corollary: Events that set sent to the dispatcher should usually include the * {@link WindowManagerPolicy#FLAG_PASS_TO_USER} flag. Otherwise, they will be dropped! * </p><p> - * It may be prudent to disable automatic key repeating for synthetically generated - * keys by setting the {@link WindowManagerPolicy#FLAG_DISABLE_KEY_REPEAT} policy flag. + * It may be prudent to disable automatic key repeating for synthetic key events + * by setting the {@link WindowManagerPolicy#FLAG_DISABLE_KEY_REPEAT} policy flag. * </p> */ public abstract class InputFilter { diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/input/InputManagerService.java index 56c3519..b8cc65e 100644 --- a/services/java/com/android/server/wm/InputManager.java +++ b/services/java/com/android/server/input/InputManagerService.java @@ -14,10 +14,12 @@ * limitations under the License. */ -package com.android.server.wm; +package com.android.server.input; import com.android.internal.util.XmlUtils; import com.android.server.Watchdog; +import com.android.server.input.InputFilter.Host; +import com.android.server.wm.WindowManagerService; import org.xmlpull.v1.XmlPullParser; @@ -25,9 +27,14 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.database.ContentObserver; +import android.hardware.input.IInputManager; +import android.hardware.input.InputManager; +import android.os.Binder; import android.os.Environment; +import android.os.Handler; import android.os.Looper; import android.os.MessageQueue; +import android.os.Process; import android.os.SystemProperties; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; @@ -44,6 +51,7 @@ import android.view.WindowManager; import android.view.WindowManagerPolicy; import java.io.File; +import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; @@ -53,62 +61,65 @@ import java.util.ArrayList; /* * Wraps the C++ InputManager and provides its callbacks. */ -public class InputManager implements Watchdog.Monitor { +public class InputManagerService extends IInputManager.Stub implements Watchdog.Monitor { static final String TAG = "InputManager"; - - private static final boolean DEBUG = false; + static final boolean DEBUG = false; + + private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml"; + + // Pointer to native input manager service object. + private final int mPtr; - private final Callbacks mCallbacks; private final Context mContext; - private final WindowManagerService mWindowManagerService; - - private static native void nativeInit(Context context, - Callbacks callbacks, MessageQueue messageQueue); - private static native void nativeStart(); - private static native void nativeSetDisplaySize(int displayId, int width, int height, - int externalWidth, int externalHeight); - private static native void nativeSetDisplayOrientation(int displayId, int rotation); + private final Callbacks mCallbacks; + private final Handler mHandler; + + private static native int nativeInit(InputManagerService service, + Context context, MessageQueue messageQueue); + private static native void nativeStart(int ptr); + private static native void nativeSetDisplaySize(int ptr, int displayId, + int width, int height, int externalWidth, int externalHeight); + private static native void nativeSetDisplayOrientation(int ptr, int displayId, int rotation); - private static native int nativeGetScanCodeState(int deviceId, int sourceMask, - int scanCode); - private static native int nativeGetKeyCodeState(int deviceId, int sourceMask, - int keyCode); - private static native int nativeGetSwitchState(int deviceId, int sourceMask, - int sw); - private static native boolean nativeHasKeys(int deviceId, int sourceMask, - int[] keyCodes, boolean[] keyExists); - private static native void nativeRegisterInputChannel(InputChannel inputChannel, + private static native int nativeGetScanCodeState(int ptr, + int deviceId, int sourceMask, int scanCode); + private static native int nativeGetKeyCodeState(int ptr, + int deviceId, int sourceMask, int keyCode); + private static native int nativeGetSwitchState(int ptr, + int deviceId, int sourceMask, int sw); + private static native boolean nativeHasKeys(int ptr, + int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists); + private static native void nativeRegisterInputChannel(int ptr, InputChannel inputChannel, InputWindowHandle inputWindowHandle, boolean monitor); - private static native void nativeUnregisterInputChannel(InputChannel inputChannel); - private static native void nativeSetInputFilterEnabled(boolean enable); - private static native int nativeInjectInputEvent(InputEvent event, + private static native void nativeUnregisterInputChannel(int ptr, InputChannel inputChannel); + private static native void nativeSetInputFilterEnabled(int ptr, boolean enable); + private static native int nativeInjectInputEvent(int ptr, InputEvent event, int injectorPid, int injectorUid, int syncMode, int timeoutMillis, int policyFlags); - private static native void nativeSetInputWindows(InputWindowHandle[] windowHandles); - private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen); - private static native void nativeSetSystemUiVisibility(int visibility); - private static native void nativeSetFocusedApplication(InputApplicationHandle application); - private static native InputDevice nativeGetInputDevice(int deviceId); - private static native void nativeGetInputConfiguration(Configuration configuration); - private static native int[] nativeGetInputDeviceIds(); - private static native boolean nativeTransferTouchFocus(InputChannel fromChannel, - InputChannel toChannel); - private static native void nativeSetPointerSpeed(int speed); - private static native void nativeSetShowTouches(boolean enabled); - private static native String nativeDump(); - private static native void nativeMonitor(); - + private static native void nativeSetInputWindows(int ptr, InputWindowHandle[] windowHandles); + private static native void nativeSetInputDispatchMode(int ptr, boolean enabled, boolean frozen); + private static native void nativeSetSystemUiVisibility(int ptr, int visibility); + private static native void nativeSetFocusedApplication(int ptr, + InputApplicationHandle application); + private static native InputDevice nativeGetInputDevice(int ptr, int deviceId); + private static native void nativeGetInputConfiguration(int ptr, Configuration configuration); + private static native int[] nativeGetInputDeviceIds(int ptr); + private static native boolean nativeTransferTouchFocus(int ptr, + InputChannel fromChannel, InputChannel toChannel); + private static native void nativeSetPointerSpeed(int ptr, int speed); + private static native void nativeSetShowTouches(int ptr, boolean enabled); + private static native String nativeDump(int ptr); + private static native void nativeMonitor(int ptr); + // Input event injection constants defined in InputDispatcher.h. - static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0; - static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1; - static final int INPUT_EVENT_INJECTION_FAILED = 2; - static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3; - - // Input event injection synchronization modes defined in InputDispatcher.h - static final int INPUT_EVENT_INJECTION_SYNC_NONE = 0; - static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1; - static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH = 2; - + private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0; + private static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1; + private static final int INPUT_EVENT_INJECTION_FAILED = 2; + private static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3; + + // Maximum number of milliseconds to wait for input event injection. + private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000; + // Key states (may be returned by queries about the current state of a // particular key code, scan code or switch). @@ -129,23 +140,21 @@ public class InputManager implements Watchdog.Monitor { InputFilter mInputFilter; InputFilterHost mInputFilterHost; - public InputManager(Context context, WindowManagerService windowManagerService) { + public InputManagerService(Context context, Callbacks callbacks) { this.mContext = context; - this.mWindowManagerService = windowManagerService; - this.mCallbacks = new Callbacks(); - - Looper looper = windowManagerService.mH.getLooper(); + this.mCallbacks = callbacks; + this.mHandler = new Handler(); Slog.i(TAG, "Initializing input manager"); - nativeInit(mContext, mCallbacks, looper.getQueue()); - - // Add ourself to the Watchdog monitors. - Watchdog.getInstance().addMonitor(this); + mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue()); } public void start() { Slog.i(TAG, "Starting input manager"); - nativeStart(); + nativeStart(mPtr); + + // Add ourself to the Watchdog monitors. + Watchdog.getInstance().addMonitor(this); registerPointerSpeedSettingObserver(); registerShowTouchesSettingObserver(); @@ -164,7 +173,7 @@ public class InputManager implements Watchdog.Monitor { Slog.d(TAG, "Setting display #" + displayId + " size to " + width + "x" + height + " external size " + externalWidth + "x" + externalHeight); } - nativeSetDisplaySize(displayId, width, height, externalWidth, externalHeight); + nativeSetDisplaySize(mPtr, displayId, width, height, externalWidth, externalHeight); } public void setDisplayOrientation(int displayId, int rotation) { @@ -175,7 +184,7 @@ public class InputManager implements Watchdog.Monitor { if (DEBUG) { Slog.d(TAG, "Setting display #" + displayId + " orientation to " + rotation); } - nativeSetDisplayOrientation(displayId, rotation); + nativeSetDisplayOrientation(mPtr, displayId, rotation); } public void getInputConfiguration(Configuration config) { @@ -183,9 +192,9 @@ public class InputManager implements Watchdog.Monitor { throw new IllegalArgumentException("config must not be null."); } - nativeGetInputConfiguration(config); + nativeGetInputConfiguration(mPtr, config); } - + /** * Gets the current state of a key or button by key code. * @param deviceId The input device id, or -1 to consult all devices. @@ -196,7 +205,7 @@ public class InputManager implements Watchdog.Monitor { * @return The key state. */ public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) { - return nativeGetKeyCodeState(deviceId, sourceMask, keyCode); + return nativeGetKeyCodeState(mPtr, deviceId, sourceMask, keyCode); } /** @@ -209,7 +218,7 @@ public class InputManager implements Watchdog.Monitor { * @return The key state. */ public int getScanCodeState(int deviceId, int sourceMask, int scanCode) { - return nativeGetScanCodeState(deviceId, sourceMask, scanCode); + return nativeGetScanCodeState(mPtr, deviceId, sourceMask, scanCode); } /** @@ -222,7 +231,7 @@ public class InputManager implements Watchdog.Monitor { * @return The switch state. */ public int getSwitchState(int deviceId, int sourceMask, int switchCode) { - return nativeGetSwitchState(deviceId, sourceMask, switchCode); + return nativeGetSwitchState(mPtr, deviceId, sourceMask, switchCode); } /** @@ -237,6 +246,7 @@ public class InputManager implements Watchdog.Monitor { * key codes. * @return True if the lookup was successful, false otherwise. */ + @Override public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) { if (keyCodes == null) { throw new IllegalArgumentException("keyCodes must not be null."); @@ -246,7 +256,7 @@ public class InputManager implements Watchdog.Monitor { + "least as large as keyCodes."); } - return nativeHasKeys(deviceId, sourceMask, keyCodes, keyExists); + return nativeHasKeys(mPtr, deviceId, sourceMask, keyCodes, keyExists); } /** @@ -260,7 +270,7 @@ public class InputManager implements Watchdog.Monitor { } InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName); - nativeRegisterInputChannel(inputChannels[0], null, true); + nativeRegisterInputChannel(mPtr, inputChannels[0], null, true); inputChannels[0].dispose(); // don't need to retain the Java object reference return inputChannels[1]; } @@ -277,7 +287,7 @@ public class InputManager implements Watchdog.Monitor { throw new IllegalArgumentException("inputChannel must not be null."); } - nativeRegisterInputChannel(inputChannel, inputWindowHandle, false); + nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false); } /** @@ -289,7 +299,7 @@ public class InputManager implements Watchdog.Monitor { throw new IllegalArgumentException("inputChannel must not be null."); } - nativeUnregisterInputChannel(inputChannel); + nativeUnregisterInputChannel(mPtr, inputChannel); } /** @@ -323,47 +333,46 @@ public class InputManager implements Watchdog.Monitor { filter.install(mInputFilterHost); } - nativeSetInputFilterEnabled(filter != null); + nativeSetInputFilterEnabled(mPtr, filter != null); } } - /** - * Injects an input event into the event system on behalf of an application. - * The synchronization mode determines whether the method blocks while waiting for - * input injection to proceed. - * - * {@link #INPUT_EVENT_INJECTION_SYNC_NONE} never blocks. Injection is asynchronous and - * is assumed always to be successful. - * - * {@link #INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT} waits for previous events to be - * dispatched so that the input dispatcher can determine whether input event injection will - * be permitted based on the current input focus. Does not wait for the input event to - * finish processing. - * - * {@link #INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH} waits for the input event to - * be completely processed. - * - * @param event The event to inject. - * @param injectorPid The pid of the injecting application. - * @param injectorUid The uid of the injecting application. - * @param syncMode The synchronization mode. - * @param timeoutMillis The injection timeout in milliseconds. - * @return One of the INPUT_EVENT_INJECTION_XXX constants. - */ - public int injectInputEvent(InputEvent event, int injectorPid, int injectorUid, - int syncMode, int timeoutMillis) { + @Override + public boolean injectInputEvent(InputEvent event, int mode) { if (event == null) { throw new IllegalArgumentException("event must not be null"); } - if (injectorPid < 0 || injectorUid < 0) { - throw new IllegalArgumentException("injectorPid and injectorUid must not be negative."); - } - if (timeoutMillis <= 0) { - throw new IllegalArgumentException("timeoutMillis must be positive"); + if (mode != InputManager.INJECT_INPUT_EVENT_MODE_ASYNC + && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH + && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) { + throw new IllegalArgumentException("mode is invalid"); } - return nativeInjectInputEvent(event, injectorPid, injectorUid, syncMode, timeoutMillis, - WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT); + final int pid = Binder.getCallingPid(); + final int uid = Binder.getCallingUid(); + final long ident = Binder.clearCallingIdentity(); + final int result; + try { + result = nativeInjectInputEvent(mPtr, event, pid, uid, mode, + INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT); + } finally { + Binder.restoreCallingIdentity(ident); + } + switch (result) { + case INPUT_EVENT_INJECTION_PERMISSION_DENIED: + Slog.w(TAG, "Input event injection from pid " + pid + " permission denied."); + throw new SecurityException( + "Injecting to another application requires INJECT_EVENTS permission"); + case INPUT_EVENT_INJECTION_SUCCEEDED: + return true; + case INPUT_EVENT_INJECTION_TIMED_OUT: + Slog.w(TAG, "Input event injection from pid " + pid + " timed out."); + return false; + case INPUT_EVENT_INJECTION_FAILED: + default: + Slog.w(TAG, "Input event injection from pid " + pid + " failed."); + return false; + } } /** @@ -371,32 +380,34 @@ public class InputManager implements Watchdog.Monitor { * @param id The device id. * @return The input device or null if not found. */ + @Override public InputDevice getInputDevice(int deviceId) { - return nativeGetInputDevice(deviceId); + return nativeGetInputDevice(mPtr, deviceId); } /** * Gets the ids of all input devices in the system. * @return The input device ids. */ + @Override public int[] getInputDeviceIds() { - return nativeGetInputDeviceIds(); + return nativeGetInputDeviceIds(mPtr); } public void setInputWindows(InputWindowHandle[] windowHandles) { - nativeSetInputWindows(windowHandles); + nativeSetInputWindows(mPtr, windowHandles); } public void setFocusedApplication(InputApplicationHandle application) { - nativeSetFocusedApplication(application); + nativeSetFocusedApplication(mPtr, application); } public void setInputDispatchMode(boolean enabled, boolean frozen) { - nativeSetInputDispatchMode(enabled, frozen); + nativeSetInputDispatchMode(mPtr, enabled, frozen); } public void setSystemUiVisibility(int visibility) { - nativeSetSystemUiVisibility(visibility); + nativeSetSystemUiVisibility(mPtr, visibility); } /** @@ -419,7 +430,7 @@ public class InputManager implements Watchdog.Monitor { if (toChannel == null) { throw new IllegalArgumentException("toChannel must not be null."); } - return nativeTransferTouchFocus(fromChannel, toChannel); + return nativeTransferTouchFocus(mPtr, fromChannel, toChannel); } /** @@ -427,20 +438,31 @@ public class InputManager implements Watchdog.Monitor { * @param speed The pointer speed as a value between -7 (slowest) and 7 (fastest) * where 0 is the default speed. */ - public void setPointerSpeed(int speed) { - speed = Math.min(Math.max(speed, -7), 7); - nativeSetPointerSpeed(speed); + @Override + public void tryPointerSpeed(int speed) { + if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED, + "tryPointerSpeed()")) { + throw new SecurityException("Requires SET_POINTER_SPEED permission"); + } + + setPointerSpeedUnchecked(speed); } public void updatePointerSpeedFromSettings() { - int speed = getPointerSpeedSetting(0); - setPointerSpeed(speed); + int speed = getPointerSpeedSetting(); + setPointerSpeedUnchecked(speed); + } + + private void setPointerSpeedUnchecked(int speed) { + speed = Math.min(Math.max(speed, InputManager.MIN_POINTER_SPEED), + InputManager.MAX_POINTER_SPEED); + nativeSetPointerSpeed(mPtr, speed); } private void registerPointerSpeedSettingObserver() { mContext.getContentResolver().registerContentObserver( Settings.System.getUriFor(Settings.System.POINTER_SPEED), true, - new ContentObserver(mWindowManagerService.mH) { + new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange) { updatePointerSpeedFromSettings(); @@ -448,8 +470,8 @@ public class InputManager implements Watchdog.Monitor { }); } - private int getPointerSpeedSetting(int defaultValue) { - int speed = defaultValue; + private int getPointerSpeedSetting() { + int speed = InputManager.DEFAULT_POINTER_SPEED; try { speed = Settings.System.getInt(mContext.getContentResolver(), Settings.System.POINTER_SPEED); @@ -460,13 +482,13 @@ public class InputManager implements Watchdog.Monitor { public void updateShowTouchesFromSettings() { int setting = getShowTouchesSetting(0); - nativeSetShowTouches(setting != 0); + nativeSetShowTouches(mPtr, setting != 0); } private void registerShowTouchesSettingObserver() { mContext.getContentResolver().registerContentObserver( Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), true, - new ContentObserver(mWindowManagerService.mH) { + new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange) { updateShowTouchesFromSettings(); @@ -484,200 +506,238 @@ public class InputManager implements Watchdog.Monitor { return result; } - public void dump(PrintWriter pw) { - String dumpStr = nativeDump(); + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump InputManager from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + pw.println("INPUT MANAGER (dumpsys input)\n"); + String dumpStr = nativeDump(mPtr); if (dumpStr != null) { pw.println(dumpStr); } } - // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). + private boolean checkCallingPermission(String permission, String func) { + // Quick check: if the calling permission is me, it's all okay. + if (Binder.getCallingPid() == Process.myPid()) { + return true; + } + + if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) { + return true; + } + String msg = "Permission Denial: " + func + " from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid() + + " requires " + permission; + Slog.w(TAG, msg); + return false; + } + + // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection). public void monitor() { synchronized (mInputFilterLock) { } - nativeMonitor(); + nativeMonitor(mPtr); } - private final class InputFilterHost implements InputFilter.Host { - private boolean mDisconnected; + // Native callback. + private void notifyConfigurationChanged(long whenNanos) { + mCallbacks.notifyConfigurationChanged(); + } - public void disconnectLocked() { - mDisconnected = true; - } + // Native callback. + private void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { + mCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen); + } - public void sendInputEvent(InputEvent event, int policyFlags) { - if (event == null) { - throw new IllegalArgumentException("event must not be null"); - } + // Native callback. + private void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) { + mCallbacks.notifyInputChannelBroken(inputWindowHandle); + } - synchronized (mInputFilterLock) { - if (!mDisconnected) { - nativeInjectInputEvent(event, 0, 0, INPUT_EVENT_INJECTION_SYNC_NONE, 0, - policyFlags | WindowManagerPolicy.FLAG_FILTERED); - } + // Native callback. + private long notifyANR(InputApplicationHandle inputApplicationHandle, + InputWindowHandle inputWindowHandle) { + return mCallbacks.notifyANR(inputApplicationHandle, inputWindowHandle); + } + + // Native callback. + final boolean filterInputEvent(InputEvent event, int policyFlags) { + synchronized (mInputFilterLock) { + if (mInputFilter != null) { + mInputFilter.filterInputEvent(event, policyFlags); + return false; } } + event.recycle(); + return true; } - /* - * Callbacks from native. - */ - private final class Callbacks { - static final String TAG = "InputManager-Callbacks"; - - private static final boolean DEBUG_VIRTUAL_KEYS = false; - private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml"; - private static final String CALIBRATION_DIR_PATH = "usr/idc/"; - - @SuppressWarnings("unused") - public void notifyConfigurationChanged(long whenNanos) { - mWindowManagerService.mInputMonitor.notifyConfigurationChanged(); - } - - @SuppressWarnings("unused") - public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { - mWindowManagerService.mInputMonitor.notifyLidSwitchChanged(whenNanos, lidOpen); - } - - @SuppressWarnings("unused") - public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) { - mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputWindowHandle); - } - - @SuppressWarnings("unused") - public long notifyANR(InputApplicationHandle inputApplicationHandle, - InputWindowHandle inputWindowHandle) { - return mWindowManagerService.mInputMonitor.notifyANR( - inputApplicationHandle, inputWindowHandle); - } + // Native callback. + private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) { + return mCallbacks.interceptKeyBeforeQueueing( + event, policyFlags, isScreenOn); + } - @SuppressWarnings("unused") - final boolean filterInputEvent(InputEvent event, int policyFlags) { - synchronized (mInputFilterLock) { - if (mInputFilter != null) { - mInputFilter.filterInputEvent(event, policyFlags); - return false; - } - } - event.recycle(); - return true; - } + // Native callback. + private int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) { + return mCallbacks.interceptMotionBeforeQueueingWhenScreenOff(policyFlags); + } - @SuppressWarnings("unused") - public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) { - return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing( - event, policyFlags, isScreenOn); - } + // Native callback. + private long interceptKeyBeforeDispatching(InputWindowHandle focus, + KeyEvent event, int policyFlags) { + return mCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags); + } - @SuppressWarnings("unused") - public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) { - return mWindowManagerService.mInputMonitor.interceptMotionBeforeQueueingWhenScreenOff( - policyFlags); - } + // Native callback. + private KeyEvent dispatchUnhandledKey(InputWindowHandle focus, + KeyEvent event, int policyFlags) { + return mCallbacks.dispatchUnhandledKey(focus, event, policyFlags); + } - @SuppressWarnings("unused") - public long interceptKeyBeforeDispatching(InputWindowHandle focus, - KeyEvent event, int policyFlags) { - return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching( - focus, event, policyFlags); - } - - @SuppressWarnings("unused") - public KeyEvent dispatchUnhandledKey(InputWindowHandle focus, - KeyEvent event, int policyFlags) { - return mWindowManagerService.mInputMonitor.dispatchUnhandledKey( - focus, event, policyFlags); - } - - @SuppressWarnings("unused") - public boolean checkInjectEventsPermission(int injectorPid, int injectorUid) { - return mContext.checkPermission( - android.Manifest.permission.INJECT_EVENTS, injectorPid, injectorUid) - == PackageManager.PERMISSION_GRANTED; - } + // Native callback. + private boolean checkInjectEventsPermission(int injectorPid, int injectorUid) { + return mContext.checkPermission(android.Manifest.permission.INJECT_EVENTS, + injectorPid, injectorUid) == PackageManager.PERMISSION_GRANTED; + } - @SuppressWarnings("unused") - public int getVirtualKeyQuietTimeMillis() { - return mContext.getResources().getInteger( - com.android.internal.R.integer.config_virtualKeyQuietTimeMillis); - } + // Native callback. + private int getVirtualKeyQuietTimeMillis() { + return mContext.getResources().getInteger( + com.android.internal.R.integer.config_virtualKeyQuietTimeMillis); + } - @SuppressWarnings("unused") - public String[] getExcludedDeviceNames() { - ArrayList<String> names = new ArrayList<String>(); - - // Read partner-provided list of excluded input devices - XmlPullParser parser = null; - // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system". - File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH); - FileReader confreader = null; - try { - confreader = new FileReader(confFile); - parser = Xml.newPullParser(); - parser.setInput(confreader); - XmlUtils.beginDocument(parser, "devices"); - - while (true) { - XmlUtils.nextElement(parser); - if (!"device".equals(parser.getName())) { - break; - } - String name = parser.getAttributeValue(null, "name"); - if (name != null) { - names.add(name); - } + // Native callback. + private String[] getExcludedDeviceNames() { + ArrayList<String> names = new ArrayList<String>(); + + // Read partner-provided list of excluded input devices + XmlPullParser parser = null; + // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system". + File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH); + FileReader confreader = null; + try { + confreader = new FileReader(confFile); + parser = Xml.newPullParser(); + parser.setInput(confreader); + XmlUtils.beginDocument(parser, "devices"); + + while (true) { + XmlUtils.nextElement(parser); + if (!"device".equals(parser.getName())) { + break; + } + String name = parser.getAttributeValue(null, "name"); + if (name != null) { + names.add(name); } - } catch (FileNotFoundException e) { - // It's ok if the file does not exist. - } catch (Exception e) { - Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e); - } finally { - try { if (confreader != null) confreader.close(); } catch (IOException e) { } } - - return names.toArray(new String[names.size()]); + } catch (FileNotFoundException e) { + // It's ok if the file does not exist. + } catch (Exception e) { + Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e); + } finally { + try { if (confreader != null) confreader.close(); } catch (IOException e) { } } - @SuppressWarnings("unused") - public int getKeyRepeatTimeout() { - return ViewConfiguration.getKeyRepeatTimeout(); - } + return names.toArray(new String[names.size()]); + } - @SuppressWarnings("unused") - public int getKeyRepeatDelay() { - return ViewConfiguration.getKeyRepeatDelay(); - } + // Native callback. + private int getKeyRepeatTimeout() { + return ViewConfiguration.getKeyRepeatTimeout(); + } - @SuppressWarnings("unused") - public int getHoverTapTimeout() { - return ViewConfiguration.getHoverTapTimeout(); - } + // Native callback. + private int getKeyRepeatDelay() { + return ViewConfiguration.getKeyRepeatDelay(); + } - @SuppressWarnings("unused") - public int getHoverTapSlop() { - return ViewConfiguration.getHoverTapSlop(); - } + // Native callback. + private int getHoverTapTimeout() { + return ViewConfiguration.getHoverTapTimeout(); + } - @SuppressWarnings("unused") - public int getDoubleTapTimeout() { - return ViewConfiguration.getDoubleTapTimeout(); - } + // Native callback. + private int getHoverTapSlop() { + return ViewConfiguration.getHoverTapSlop(); + } - @SuppressWarnings("unused") - public int getLongPressTimeout() { - return ViewConfiguration.getLongPressTimeout(); - } + // Native callback. + private int getDoubleTapTimeout() { + return ViewConfiguration.getDoubleTapTimeout(); + } + + // Native callback. + private int getLongPressTimeout() { + return ViewConfiguration.getLongPressTimeout(); + } - @SuppressWarnings("unused") - public int getPointerLayer() { - return mWindowManagerService.mPolicy.windowTypeToLayerLw( - WindowManager.LayoutParams.TYPE_POINTER) - * WindowManagerService.TYPE_LAYER_MULTIPLIER - + WindowManagerService.TYPE_LAYER_OFFSET; + // Native callback. + private int getPointerLayer() { + return mCallbacks.getPointerLayer(); + } + + // Native callback. + private PointerIcon getPointerIcon() { + return PointerIcon.getDefaultIcon(mContext); + } + + /** + * Callback interface implemented by the Window Manager. + */ + public interface Callbacks { + public void notifyConfigurationChanged(); + + public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen); + + public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle); + + public long notifyANR(InputApplicationHandle inputApplicationHandle, + InputWindowHandle inputWindowHandle); + + public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn); + + public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags); + + public long interceptKeyBeforeDispatching(InputWindowHandle focus, + KeyEvent event, int policyFlags); + + public KeyEvent dispatchUnhandledKey(InputWindowHandle focus, + KeyEvent event, int policyFlags); + + public int getPointerLayer(); + } + + /** + * Hosting interface for input filters to call back into the input manager. + */ + private final class InputFilterHost implements InputFilter.Host { + private boolean mDisconnected; + + public void disconnectLocked() { + mDisconnected = true; } - @SuppressWarnings("unused") - public PointerIcon getPointerIcon() { - return PointerIcon.getDefaultIcon(mContext); + public void sendInputEvent(InputEvent event, int policyFlags) { + if (event == null) { + throw new IllegalArgumentException("event must not be null"); + } + + synchronized (mInputFilterLock) { + if (!mDisconnected) { + nativeInjectInputEvent(mPtr, event, 0, 0, + InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0, + policyFlags | WindowManagerPolicy.FLAG_FILTERED); + } + } } } } diff --git a/services/java/com/android/server/wm/InputWindowHandle.java b/services/java/com/android/server/input/InputWindowHandle.java index 264877c..03d66af 100644 --- a/services/java/com/android/server/wm/InputWindowHandle.java +++ b/services/java/com/android/server/input/InputWindowHandle.java @@ -14,11 +14,10 @@ * limitations under the License. */ -package com.android.server.wm; +package com.android.server.input; import android.graphics.Region; import android.view.InputChannel; -import android.view.WindowManagerPolicy; /** * Functions as a handle for a window that can receive input. @@ -35,7 +34,7 @@ public final class InputWindowHandle { public final InputApplicationHandle inputApplicationHandle; // The window manager's window state. - public final WindowManagerPolicy.WindowState windowState; + public final Object windowState; // The input channel associated with the window. public InputChannel inputChannel; @@ -91,7 +90,7 @@ public final class InputWindowHandle { private native void nativeDispose(); public InputWindowHandle(InputApplicationHandle inputApplicationHandle, - WindowManagerPolicy.WindowState windowState) { + Object windowState) { this.inputApplicationHandle = inputApplicationHandle; this.windowState = windowState; } diff --git a/services/java/com/android/server/net/NetworkIdentitySet.java b/services/java/com/android/server/net/NetworkIdentitySet.java index af03fb3..397f9f4 100644 --- a/services/java/com/android/server/net/NetworkIdentitySet.java +++ b/services/java/com/android/server/net/NetworkIdentitySet.java @@ -21,7 +21,6 @@ import android.net.NetworkIdentity; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.net.ProtocolException; import java.util.HashSet; /** @@ -33,48 +32,46 @@ import java.util.HashSet; public class NetworkIdentitySet extends HashSet<NetworkIdentity> { private static final int VERSION_INIT = 1; private static final int VERSION_ADD_ROAMING = 2; + private static final int VERSION_ADD_NETWORK_ID = 3; public NetworkIdentitySet() { } public NetworkIdentitySet(DataInputStream in) throws IOException { final int version = in.readInt(); - switch (version) { - case VERSION_INIT: { - final int size = in.readInt(); - for (int i = 0; i < size; i++) { - final int ignoredVersion = in.readInt(); - final int type = in.readInt(); - final int subType = in.readInt(); - final String subscriberId = readOptionalString(in); - add(new NetworkIdentity(type, subType, subscriberId, false)); - } - break; + final int size = in.readInt(); + for (int i = 0; i < size; i++) { + if (version <= VERSION_INIT) { + final int ignored = in.readInt(); } - case VERSION_ADD_ROAMING: { - final int size = in.readInt(); - for (int i = 0; i < size; i++) { - final int type = in.readInt(); - final int subType = in.readInt(); - final String subscriberId = readOptionalString(in); - final boolean roaming = in.readBoolean(); - add(new NetworkIdentity(type, subType, subscriberId, roaming)); - } - break; + final int type = in.readInt(); + final int subType = in.readInt(); + final String subscriberId = readOptionalString(in); + final String networkId; + if (version >= VERSION_ADD_NETWORK_ID) { + networkId = readOptionalString(in); + } else { + networkId = null; } - default: { - throw new ProtocolException("unexpected version: " + version); + final boolean roaming; + if (version >= VERSION_ADD_ROAMING) { + roaming = in.readBoolean(); + } else { + roaming = false; } + + add(new NetworkIdentity(type, subType, subscriberId, networkId, false)); } } public void writeToStream(DataOutputStream out) throws IOException { - out.writeInt(VERSION_ADD_ROAMING); + out.writeInt(VERSION_ADD_NETWORK_ID); out.writeInt(size()); for (NetworkIdentity ident : this) { out.writeInt(ident.getType()); out.writeInt(ident.getSubType()); writeOptionalString(out, ident.getSubscriberId()); + writeOptionalString(out, ident.getNetworkId()); out.writeBoolean(ident.getRoaming()); } } diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java index 1f1e720..fa62e49 100644 --- a/services/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java @@ -48,6 +48,7 @@ import static android.net.NetworkTemplate.MATCH_MOBILE_ALL; import static android.net.NetworkTemplate.MATCH_WIFI; import static android.net.NetworkTemplate.buildTemplateMobileAll; import static android.net.TrafficStats.MB_IN_BYTES; +import static android.telephony.TelephonyManager.SIM_STATE_READY; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT; @@ -113,6 +114,7 @@ import android.util.Xml; import com.android.internal.R; import com.android.internal.os.AtomicFile; import com.android.internal.util.FastXmlSerializer; +import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Objects; import com.google.android.collect.Lists; import com.google.android.collect.Maps; @@ -160,6 +162,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final int VERSION_ADDED_TIMEZONE = 6; private static final int VERSION_ADDED_INFERRED = 7; private static final int VERSION_SWITCH_APP_ID = 8; + private static final int VERSION_ADDED_NETWORK_ID = 9; + private static final int VERSION_LATEST = VERSION_ADDED_NETWORK_ID; // @VisibleForTesting public static final int TYPE_WARNING = 0x1; @@ -175,6 +179,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground"; private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate"; private static final String ATTR_SUBSCRIBER_ID = "subscriberId"; + private static final String ATTR_NETWORK_ID = "networkId"; private static final String ATTR_CYCLE_DAY = "cycleDay"; private static final String ATTR_CYCLE_TIMEZONE = "cycleTimezone"; private static final String ATTR_WARNING_BYTES = "warningBytes"; @@ -491,6 +496,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { for (NetworkPolicy policy : mNetworkPolicy.values()) { // ignore policies that aren't relevant to user if (!isTemplateRelevant(policy.template)) continue; + if (!policy.hasCycle()) continue; final long start = computeLastCycleBoundary(currentTime, policy); final long end = currentTime; @@ -528,21 +534,24 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { /** * Test if given {@link NetworkTemplate} is relevant to user based on - * current device state, such as when {@link #getActiveSubscriberId()} - * matches. This is regardless of data connection status. + * current device state, such as when + * {@link TelephonyManager#getSubscriberId()} matches. This is regardless of + * data connection status. */ private boolean isTemplateRelevant(NetworkTemplate template) { + final TelephonyManager tele = TelephonyManager.from(mContext); + switch (template.getMatchRule()) { case MATCH_MOBILE_3G_LOWER: case MATCH_MOBILE_4G: case MATCH_MOBILE_ALL: - // mobile templates aren't relevant in airplane mode - if (isAirplaneModeOn(mContext)) { + // mobile templates are relevant when SIM is ready and + // subscriberId matches. + if (tele.getSimState() == SIM_STATE_READY) { + return Objects.equal(tele.getSubscriberId(), template.getSubscriberId()); + } else { return false; } - - // mobile templates are relevant when subscriberid is active - return Objects.equal(getActiveSubscriberId(), template.getSubscriberId()); } return true; } @@ -761,7 +770,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final long currentTime = currentTimeMillis(); for (NetworkPolicy policy : mNetworkPolicy.values()) { // shortcut when policy has no limit - if (policy.limitBytes == LIMIT_DISABLED) { + if (policy.limitBytes == LIMIT_DISABLED || !policy.hasCycle()) { setNetworkTemplateEnabled(policy.template, true); continue; } @@ -784,13 +793,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * for the given {@link NetworkTemplate}. */ private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) { + final TelephonyManager tele = TelephonyManager.from(mContext); + switch (template.getMatchRule()) { case MATCH_MOBILE_3G_LOWER: case MATCH_MOBILE_4G: case MATCH_MOBILE_ALL: // TODO: offer more granular control over radio states once // 4965893 is available. - if (Objects.equal(getActiveSubscriberId(), template.getSubscriberId())) { + if (tele.getSimState() == SIM_STATE_READY + && Objects.equal(tele.getSubscriberId(), template.getSubscriberId())) { setPolicyDataEnable(TYPE_MOBILE, enabled); setPolicyDataEnable(TYPE_WIMAX, enabled); } @@ -863,9 +875,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { for (NetworkPolicy policy : mNetworkRules.keySet()) { final String[] ifaces = mNetworkRules.get(policy); - final long start = computeLastCycleBoundary(currentTime, policy); - final long end = currentTime; - final long totalBytes = getTotalBytes(policy.template, start, end); + final long start; + final long totalBytes; + if (policy.hasCycle()) { + start = computeLastCycleBoundary(currentTime, policy); + totalBytes = getTotalBytes(policy.template, start, currentTime); + } else { + start = Long.MAX_VALUE; + totalBytes = 0; + } if (LOGD) { Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces " @@ -923,9 +941,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()"); if (mSuppressDefaultPolicy) return; - final String subscriberId = getActiveSubscriberId(); + final TelephonyManager tele = TelephonyManager.from(mContext); + + // avoid creating policy when SIM isn't ready + if (tele.getSimState() != SIM_STATE_READY) return; + + final String subscriberId = tele.getSubscriberId(); final NetworkIdentity probeIdent = new NetworkIdentity( - TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, false); + TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false); // examine to see if any policy is defined for active mobile boolean mobileDefined = false; @@ -986,6 +1009,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } else if (TAG_NETWORK_POLICY.equals(tag)) { final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE); final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID); + final String networkId; + if (version >= VERSION_ADDED_NETWORK_ID) { + networkId = in.getAttributeValue(null, ATTR_NETWORK_ID); + } else { + networkId = null; + } final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY); final String cycleTimezone; if (version >= VERSION_ADDED_TIMEZONE) { @@ -1031,12 +1060,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } final NetworkTemplate template = new NetworkTemplate( - networkTemplate, subscriberId); + networkTemplate, subscriberId, networkId); mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay, cycleTimezone, warningBytes, limitBytes, lastWarningSnooze, lastLimitSnooze, metered, inferred)); - } else if (TAG_UID_POLICY.equals(tag)) { + } else if (TAG_UID_POLICY.equals(tag) && version < VERSION_SWITCH_APP_ID) { final int uid = readIntAttribute(in, ATTR_UID); final int policy = readIntAttribute(in, ATTR_POLICY); @@ -1046,7 +1075,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } else { Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring"); } - } else if (TAG_APP_POLICY.equals(tag)) { + } else if (TAG_APP_POLICY.equals(tag) && version >= VERSION_SWITCH_APP_ID) { final int appId = readIntAttribute(in, ATTR_APP_ID); final int policy = readIntAttribute(in, ATTR_POLICY); @@ -1099,7 +1128,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { out.startDocument(null, true); out.startTag(null, TAG_POLICY_LIST); - writeIntAttribute(out, ATTR_VERSION, VERSION_SWITCH_APP_ID); + writeIntAttribute(out, ATTR_VERSION, VERSION_LATEST); writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground); // write all known network policies @@ -1112,6 +1141,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if (subscriberId != null) { out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId); } + final String networkId = template.getNetworkId(); + if (networkId != null) { + out.attribute(null, ATTR_NETWORK_ID, networkId); + } writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay); out.attribute(null, ATTR_CYCLE_TIMEZONE, policy.cycleTimezone); writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes); @@ -1318,7 +1351,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { policy = findPolicyForNetworkLocked(ident); } - if (policy == null) { + if (policy == null || !policy.hasCycle()) { // missing policy means we can't derive useful quota info return null; } @@ -1340,9 +1373,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } @Override - protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { + protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { mContext.enforceCallingOrSelfPermission(DUMP, TAG); + final IndentingPrintWriter fout = new IndentingPrintWriter(writer, " "); + final HashSet<String> argSet = new HashSet<String>(); for (String arg : args) { argSet.add(arg); @@ -1365,31 +1400,36 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { fout.print("Restrict background: "); fout.println(mRestrictBackground); fout.println("Network policies:"); + fout.increaseIndent(); for (NetworkPolicy policy : mNetworkPolicy.values()) { - fout.print(" "); fout.println(policy.toString()); + fout.println(policy.toString()); } + fout.decreaseIndent(); fout.println("Policy for apps:"); + fout.increaseIndent(); int size = mAppPolicy.size(); for (int i = 0; i < size; i++) { final int appId = mAppPolicy.keyAt(i); final int policy = mAppPolicy.valueAt(i); - fout.print(" appId="); + fout.print("appId="); fout.print(appId); fout.print(" policy="); dumpPolicy(fout, policy); fout.println(); } + fout.decreaseIndent(); final SparseBooleanArray knownUids = new SparseBooleanArray(); collectKeys(mUidForeground, knownUids); collectKeys(mUidRules, knownUids); fout.println("Status for known UIDs:"); + fout.increaseIndent(); size = knownUids.size(); for (int i = 0; i < size; i++) { final int uid = knownUids.keyAt(i); - fout.print(" UID="); + fout.print("UID="); fout.print(uid); fout.print(" foreground="); @@ -1410,6 +1450,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { fout.println(); } + fout.decreaseIndent(); } } @@ -1547,7 +1588,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } private Handler.Callback mHandlerCallback = new Handler.Callback() { - /** {@inheritDoc} */ + @Override public boolean handleMessage(Message msg) { switch (msg.what) { case MSG_RULES_CHANGED: { @@ -1697,15 +1738,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } - private String getActiveSubscriberId() { - final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService( - Context.TELEPHONY_SERVICE); - return telephony.getSubscriberId(); - } - private long getTotalBytes(NetworkTemplate template, long start, long end) { try { - return mNetworkStats.getSummaryForNetwork(template, start, end).getTotalBytes(); + return mNetworkStats.getNetworkTotalBytes(template, start, end); } catch (RuntimeException e) { Slog.w(TAG, "problem reading network stats: " + e); return 0; diff --git a/services/java/com/android/server/net/NetworkStatsCollection.java b/services/java/com/android/server/net/NetworkStatsCollection.java index 70038d9..2892a74 100644 --- a/services/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/java/com/android/server/net/NetworkStatsCollection.java @@ -57,8 +57,6 @@ import libcore.io.IoUtils; * {@link NetworkIdentitySet}, UID, set, and tag. Knows how to persist itself. */ public class NetworkStatsCollection implements FileRotator.Reader { - private static final String TAG = "NetworkStatsCollection"; - /** File header magic number: "ANET" */ private static final int FILE_MAGIC = 0x414E4554; @@ -173,7 +171,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { } /** - * Record given {@link NetworkStats.Entry} into this collection. + * Record given {@link android.net.NetworkStats.Entry} into this collection. */ public void recordData(NetworkIdentitySet ident, int uid, int set, int tag, long start, long end, NetworkStats.Entry entry) { @@ -227,7 +225,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { } } - /** {@inheritDoc} */ + @Override public void read(InputStream in) throws IOException { read(new DataInputStream(in)); } @@ -502,7 +500,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { return false; } - /** {@inheritDoc} */ + @Override public int compareTo(Key another) { return Integer.compare(uid, another.uid); } diff --git a/services/java/com/android/server/net/NetworkStatsRecorder.java b/services/java/com/android/server/net/NetworkStatsRecorder.java index 290bd2c..57ad158 100644 --- a/services/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/java/com/android/server/net/NetworkStatsRecorder.java @@ -221,6 +221,11 @@ public class NetworkStatsRecorder { if (mLastSnapshot != null) { mLastSnapshot = mLastSnapshot.withoutUid(uid); } + + final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null; + if (complete != null) { + complete.removeUid(uid); + } } /** @@ -235,22 +240,22 @@ public class NetworkStatsRecorder { mCollection = checkNotNull(collection, "missing NetworkStatsCollection"); } - /** {@inheritDoc} */ + @Override public void reset() { // ignored } - /** {@inheritDoc} */ + @Override public void read(InputStream in) throws IOException { mCollection.read(in); } - /** {@inheritDoc} */ + @Override public boolean shouldWrite() { return true; } - /** {@inheritDoc} */ + @Override public void write(OutputStream out) throws IOException { mCollection.write(new DataOutputStream(out)); mCollection.reset(); @@ -270,24 +275,24 @@ public class NetworkStatsRecorder { mUid = uid; } - /** {@inheritDoc} */ + @Override public void reset() { mTemp.reset(); } - /** {@inheritDoc} */ + @Override public void read(InputStream in) throws IOException { mTemp.read(in); mTemp.clearDirty(); mTemp.removeUid(mUid); } - /** {@inheritDoc} */ + @Override public boolean shouldWrite() { return mTemp.isDirty(); } - /** {@inheritDoc} */ + @Override public void write(OutputStream out) throws IOException { mTemp.write(new DataOutputStream(out)); } diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index 8796afc..4382a03 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -34,7 +34,7 @@ import static android.net.NetworkStats.SET_FOREGROUND; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkTemplate.buildTemplateMobileAll; -import static android.net.NetworkTemplate.buildTemplateWifi; +import static android.net.NetworkTemplate.buildTemplateWifiWildcard; import static android.net.TrafficStats.MB_IN_BYTES; import static android.provider.Settings.Secure.NETSTATS_DEV_BUCKET_DURATION; import static android.provider.Settings.Secure.NETSTATS_DEV_DELETE_AGE; @@ -70,6 +70,7 @@ import android.content.IntentFilter; import android.net.IConnectivityManager; import android.net.INetworkManagementEventObserver; import android.net.INetworkStatsService; +import android.net.INetworkStatsSession; import android.net.LinkProperties; import android.net.NetworkIdentity; import android.net.NetworkInfo; @@ -412,40 +413,75 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) { - return mDevStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields); - } + public INetworkStatsSession openSession() { + mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); - @Override - public NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end) { - return mDevStatsCached.getSummary(template, start, end); - } + // return an IBinder which holds strong references to any loaded stats + // for its lifetime; when caller closes only weak references remain. - @Override - public NetworkStatsHistory getHistoryForUid( - NetworkTemplate template, int uid, int set, int tag, int fields) { - // TODO: transition to stats sessions to avoid WeakReferences - if (tag == TAG_NONE) { - return mUidRecorder.getOrLoadCompleteLocked().getHistory( - template, uid, set, tag, fields); - } else { - return mUidTagRecorder.getOrLoadCompleteLocked().getHistory( - template, uid, set, tag, fields); - } + return new INetworkStatsSession.Stub() { + private NetworkStatsCollection mUidComplete; + private NetworkStatsCollection mUidTagComplete; + + private NetworkStatsCollection getUidComplete() { + if (mUidComplete == null) { + mUidComplete = mUidRecorder.getOrLoadCompleteLocked(); + } + return mUidComplete; + } + + private NetworkStatsCollection getUidTagComplete() { + if (mUidTagComplete == null) { + mUidTagComplete = mUidTagRecorder.getOrLoadCompleteLocked(); + } + return mUidTagComplete; + } + + @Override + public NetworkStats getSummaryForNetwork( + NetworkTemplate template, long start, long end) { + return mDevStatsCached.getSummary(template, start, end); + } + + @Override + public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) { + return mDevStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields); + } + + @Override + public NetworkStats getSummaryForAllUid( + NetworkTemplate template, long start, long end, boolean includeTags) { + final NetworkStats stats = getUidComplete().getSummary(template, start, end); + if (includeTags) { + final NetworkStats tagStats = getUidTagComplete() + .getSummary(template, start, end); + stats.combineAllValues(tagStats); + } + return stats; + } + + @Override + public NetworkStatsHistory getHistoryForUid( + NetworkTemplate template, int uid, int set, int tag, int fields) { + if (tag == TAG_NONE) { + return getUidComplete().getHistory(template, uid, set, tag, fields); + } else { + return getUidTagComplete().getHistory(template, uid, set, tag, fields); + } + } + + @Override + public void close() { + mUidComplete = null; + mUidTagComplete = null; + } + }; } @Override - public NetworkStats getSummaryForAllUid( - NetworkTemplate template, long start, long end, boolean includeTags) { - // TODO: transition to stats sessions to avoid WeakReferences - final NetworkStats stats = mUidRecorder.getOrLoadCompleteLocked().getSummary( - template, start, end); - if (includeTags) { - final NetworkStats tagStats = mUidTagRecorder.getOrLoadCompleteLocked().getSummary( - template, start, end); - stats.combineAllValues(tagStats); - } - return stats; + public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { + mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); + return mDevStatsCached.getSummary(template, start, end).getTotalBytes(); } @Override @@ -464,6 +500,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Binder.restoreCallingIdentity(token); } + // splice in operation counts + networkLayer.spliceOperationsFrom(mUidOperations); + final NetworkStats dataLayer = new NetworkStats( networkLayer.getElapsedRealtime(), networkLayer.size()); @@ -474,8 +513,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { dataLayer.combineValues(entry); } - // splice in operation counts - dataLayer.spliceOperationsFrom(mUidOperations); return dataLayer; } @@ -836,7 +873,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { trustedTime); // collect wifi sample - template = buildTemplateWifi(); + template = buildTemplateWifiWildcard(); devTotal = mDevRecorder.getTotalSinceBootLocked(template); xtTotal = new NetworkStats.Entry(); uidTotal = mUidRecorder.getTotalSinceBootLocked(template); @@ -962,7 +999,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private Handler.Callback mHandlerCallback = new Handler.Callback() { - /** {@inheritDoc} */ + @Override public boolean handleMessage(Message msg) { switch (msg.what) { case MSG_PERFORM_POLL: { @@ -1001,7 +1038,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> { - /** {@inheritDoc} */ + @Override public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right, int rightIndex, String cookie) { Log.w(TAG, "found non-monotonic values; saving to dropbox"); @@ -1020,7 +1057,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** - * Default external settings that read from {@link Settings.Secure}. + * Default external settings that read from + * {@link android.provider.Settings.Secure}. */ private static class DefaultNetworkStatsSettings implements NetworkStatsSettings { private final ContentResolver mResolver; @@ -1038,19 +1076,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return Settings.Secure.getInt(mResolver, name, defInt) != 0; } + @Override public long getPollInterval() { return getSecureLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS); } + @Override public long getTimeCacheMaxAge() { return getSecureLong(NETSTATS_TIME_CACHE_MAX_AGE, DAY_IN_MILLIS); } + @Override public long getGlobalAlertBytes() { return getSecureLong(NETSTATS_GLOBAL_ALERT_BYTES, 2 * MB_IN_BYTES); } + @Override public boolean getSampleEnabled() { return getSecureBoolean(NETSTATS_SAMPLE_ENABLED, true); } + @Override public Config getDevConfig() { return new Config(getSecureLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS), getSecureLong(NETSTATS_DEV_PERSIST_BYTES, 2 * MB_IN_BYTES), @@ -1058,6 +1101,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { getSecureLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS)); } + @Override public Config getUidConfig() { return new Config(getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS), getSecureLong(NETSTATS_UID_PERSIST_BYTES, 2 * MB_IN_BYTES), @@ -1065,6 +1109,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { getSecureLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS)); } + @Override public Config getUidTagConfig() { return new Config(getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS), getSecureLong(NETSTATS_UID_PERSIST_BYTES, 2 * MB_IN_BYTES), diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java index 4bea5e4..1bd15f6 100644 --- a/services/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/java/com/android/server/usb/UsbDeviceManager.java @@ -60,6 +60,7 @@ import java.util.LinkedList; import java.util.List; import java.util.HashMap; import java.util.Map; +import java.util.Scanner; /** * UsbDeviceManager manages USB state in device mode. @@ -81,6 +82,8 @@ public class UsbDeviceManager { "/sys/class/android_usb/android0/f_mass_storage/lun/file"; private static final String RNDIS_ETH_ADDR_PATH = "/sys/class/android_usb/android0/f_rndis/ethaddr"; + private static final String AUDIO_SOURCE_PCM_PATH = + "/sys/class/android_usb/android0/f_audio_source/pcm"; private static final int MSG_UPDATE_STATE = 0; private static final int MSG_ENABLE_ADB = 1; @@ -105,6 +108,7 @@ public class UsbDeviceManager { private final boolean mHasUsbAccessory; private boolean mUseUsbNotification; private boolean mAdbEnabled; + private boolean mAudioSourceEnabled; private Map<String, List<Pair<String, String>>> mOemModeMap; private class AdbSettingsObserver extends ContentObserver { @@ -291,6 +295,8 @@ public class UsbDeviceManager { String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim(); updateState(state); mAdbEnabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB); + mAudioSourceEnabled = containsFunction(mCurrentFunctions, + UsbManager.USB_FUNCTION_AUDIO_SOURCE); // Upgrade step for previous versions that used persist.service.adb.enable String value = SystemProperties.get("persist.service.adb.enable", ""); @@ -504,6 +510,28 @@ public class UsbDeviceManager { mContext.sendStickyBroadcast(intent); } + private void updateAudioSourceFunction(boolean enabled) { + // send a sticky broadcast containing current USB state + Intent intent = new Intent(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG); + intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + intent.putExtra("state", (enabled ? 1 : 0)); + if (enabled) { + try { + Scanner scanner = new Scanner(new File(AUDIO_SOURCE_PCM_PATH)); + int card = scanner.nextInt(); + int device = scanner.nextInt(); + intent.putExtra("card", card); + intent.putExtra("device", device); + } catch (FileNotFoundException e) { + Slog.e(TAG, "could not open audio source PCM file", e); + } + } + + mContext.sendStickyBroadcast(intent); + mAudioSourceEnabled = enabled; + } + @Override public void handleMessage(Message msg) { switch (msg.what) { @@ -523,6 +551,11 @@ public class UsbDeviceManager { } if (mBootCompleted) { updateUsbState(); + boolean audioSourceEnabled = containsFunction(mCurrentFunctions, + UsbManager.USB_FUNCTION_AUDIO_SOURCE); + if (audioSourceEnabled != mAudioSourceEnabled) { + updateAudioSourceFunction(audioSourceEnabled); + } } break; case MSG_ENABLE_ADB: @@ -543,6 +576,7 @@ public class UsbDeviceManager { if (mCurrentAccessory != null) { mSettingsManager.accessoryAttached(mCurrentAccessory); } + updateAudioSourceFunction(mAudioSourceEnabled); break; } } diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java new file mode 100644 index 0000000..c3b5465 --- /dev/null +++ b/services/java/com/android/server/wm/AppWindowAnimator.java @@ -0,0 +1,301 @@ +// Copyright 2012 Google Inc. All Rights Reserved. + +package com.android.server.wm; + +import android.graphics.Matrix; +import android.util.Slog; +import android.view.Surface; +import android.view.WindowManagerPolicy; +import android.view.animation.Animation; +import android.view.animation.Transformation; + +import java.io.PrintWriter; + +/** + * + */ +public class AppWindowAnimator { + + final AppWindowToken mAppToken; + final WindowManagerService mService; + final WindowAnimator mAnimator; + + boolean animating; + Animation animation; + boolean animInitialized; + boolean hasTransformation; + final Transformation transformation = new Transformation(); + + // Have we been asked to have this token keep the screen frozen? + // Protect with mAnimator. + boolean freezingScreen; + + // Offset to the window of all layers in the token, for use by + // AppWindowToken animations. + int animLayerAdjustment; + + // Special surface for thumbnail animation. + Surface thumbnail; + int thumbnailTransactionSeq; + int thumbnailX; + int thumbnailY; + int thumbnailLayer; + Animation thumbnailAnimation; + final Transformation thumbnailTransformation = new Transformation(); + + public AppWindowAnimator(final WindowManagerService service, final AppWindowToken atoken) { + mService = service; + mAppToken = atoken; + mAnimator = service.mAnimator; + } + + public void setAnimation(Animation anim, boolean initialized) { + if (WindowManagerService.localLOGV) Slog.v( + WindowManagerService.TAG, "Setting animation in " + this + ": " + anim); + animation = anim; + animating = false; + animInitialized = initialized; + anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION); + anim.scaleCurrentDuration(mService.mTransitionAnimationScale); + int zorder = anim.getZAdjustment(); + int adj = 0; + if (zorder == Animation.ZORDER_TOP) { + adj = WindowManagerService.TYPE_LAYER_OFFSET; + } else if (zorder == Animation.ZORDER_BOTTOM) { + adj = -WindowManagerService.TYPE_LAYER_OFFSET; + } + + if (animLayerAdjustment != adj) { + animLayerAdjustment = adj; + updateLayers(); + } + // Start out animation gone if window is gone, or visible if window is visible. + transformation.clear(); + transformation.setAlpha(mAppToken.reportedVisible ? 1 : 0); + hasTransformation = true; + } + + public void setDummyAnimation() { + if (animation == null) { + if (WindowManagerService.localLOGV) Slog.v( + WindowManagerService.TAG, "Setting dummy animation in " + this); + animation = WindowManagerService.sDummyAnimation; + animInitialized = false; + } + } + + public void clearAnimation() { + if (animation != null) { + animation = null; + animating = true; + animInitialized = false; + } + clearThumbnail(); + } + + public void clearThumbnail() { + if (thumbnail != null) { + thumbnail.destroy(); + thumbnail = null; + } + } + + void updateLayers() { + final int N = mAppToken.allAppWindows.size(); + final int adj = animLayerAdjustment; + thumbnailLayer = -1; + for (int i=0; i<N; i++) { + final WindowState w = mAppToken.allAppWindows.get(i); + final WindowStateAnimator winAnimator = w.mWinAnimator; + winAnimator.mAnimLayer = w.mLayer + adj; + if (winAnimator.mAnimLayer > thumbnailLayer) { + thumbnailLayer = winAnimator.mAnimLayer; + } + if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Updating layer " + w + ": " + + winAnimator.mAnimLayer); + if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) { + mService.setInputMethodAnimLayerAdjustment(adj); + } + if (w == mService.mWallpaperTarget && mService.mLowerWallpaperTarget == null) { + mService.setWallpaperAnimLayerAdjustmentLocked(adj); + } + } + } + + private void stepThumbnailAnimation(long currentTime) { + thumbnailTransformation.clear(); + thumbnailAnimation.getTransformation(currentTime, thumbnailTransformation); + thumbnailTransformation.getMatrix().preTranslate(thumbnailX, thumbnailY); + final boolean screenAnimation = mAnimator.mScreenRotationAnimation != null + && mAnimator.mScreenRotationAnimation.isAnimating(); + if (screenAnimation) { + thumbnailTransformation.postCompose( + mAnimator.mScreenRotationAnimation.getEnterTransformation()); + } + // cache often used attributes locally + final float tmpFloats[] = mService.mTmpFloats; + thumbnailTransformation.getMatrix().getValues(tmpFloats); + if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, + "thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X] + + ", " + tmpFloats[Matrix.MTRANS_Y], null); + thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]); + if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, + "thumbnail", "alpha=" + thumbnailTransformation.getAlpha() + + " layer=" + thumbnailLayer + + " matrix=[" + tmpFloats[Matrix.MSCALE_X] + + "," + tmpFloats[Matrix.MSKEW_Y] + + "][" + tmpFloats[Matrix.MSKEW_X] + + "," + tmpFloats[Matrix.MSCALE_Y] + "]", null); + thumbnail.setAlpha(thumbnailTransformation.getAlpha()); + // The thumbnail is layered below the window immediately above this + // token's anim layer. + thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER + - WindowManagerService.LAYER_OFFSET_THUMBNAIL); + thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y], + tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]); + } + + private boolean stepAnimation(long currentTime) { + if (animation == null) { + return false; + } + transformation.clear(); + final boolean more = animation.getTransformation(currentTime, transformation); + if (WindowManagerService.DEBUG_ANIM) Slog.v( + WindowManagerService.TAG, "Stepped animation in " + this + + ": more=" + more + ", xform=" + transformation); + if (!more) { + animation = null; + clearThumbnail(); + if (WindowManagerService.DEBUG_ANIM) Slog.v( + WindowManagerService.TAG, "Finished animation in " + this + + " @ " + currentTime); + } + hasTransformation = more; + return more; + } + + // This must be called while inside a transaction. + boolean stepAnimationLocked(long currentTime, int dw, int dh) { + if (mService.okToDisplay()) { + // We will run animations as long as the display isn't frozen. + + if (animation == WindowManagerService.sDummyAnimation) { + // This guy is going to animate, but not yet. For now count + // it as not animating for purposes of scheduling transactions; + // when it is really time to animate, this will be set to + // a real animation and the next call will execute normally. + return false; + } + + if ((mAppToken.allDrawn || animating || mAppToken.startingDisplayed) + && animation != null) { + if (!animating) { + if (WindowManagerService.DEBUG_ANIM) Slog.v( + WindowManagerService.TAG, "Starting animation in " + this + + " @ " + currentTime + ": dw=" + dw + " dh=" + dh + + " scale=" + mService.mTransitionAnimationScale + + " allDrawn=" + mAppToken.allDrawn + " animating=" + animating); + if (!animInitialized) { + animation.initialize(dw, dh, dw, dh); + } + animation.setStartTime(currentTime); + animating = true; + if (thumbnail != null) { + thumbnail.show(); + thumbnailAnimation.setStartTime(currentTime); + } + } + if (stepAnimation(currentTime)) { + // animation isn't over, step any thumbnail and that's + // it for now. + if (thumbnail != null) { + stepThumbnailAnimation(currentTime); + } + return true; + } + } + } else if (animation != null) { + // If the display is frozen, and there is a pending animation, + // clear it and make sure we run the cleanup code. + animating = true; + animation = null; + } + + hasTransformation = false; + + if (!animating && animation == null) { + return false; + } + + mAnimator.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; + if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { + mService.debugLayoutRepeats("AppWindowToken", mAnimator.mPendingLayoutChanges); + } + + clearAnimation(); + animating = false; + if (animLayerAdjustment != 0) { + animLayerAdjustment = 0; + updateLayers(); + } + if (mService.mInputMethodTarget != null + && mService.mInputMethodTarget.mAppToken == mAppToken) { + mService.moveInputMethodWindowsIfNeededLocked(true); + } + + if (WindowManagerService.DEBUG_ANIM) Slog.v( + WindowManagerService.TAG, "Animation done in " + this + + ": reportedVisible=" + mAppToken.reportedVisible); + + transformation.clear(); + + final int N = mAppToken.windows.size(); + for (int i=0; i<N; i++) { + mAppToken.windows.get(i).mWinAnimator.finishExit(); + } + mAppToken.updateReportedVisibilityLocked(); + + return false; + } + + boolean showAllWindowsLocked() { + boolean isAnimating = false; + final int NW = mAppToken.allAppWindows.size(); + for (int i=0; i<NW; i++) { + WindowStateAnimator winAnimator = mAppToken.allAppWindows.get(i).mWinAnimator; + if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, + "performing show on: " + winAnimator); + winAnimator.performShowLocked(); + isAnimating |= winAnimator.isAnimating(); + } + return isAnimating; + } + + void dump(PrintWriter pw, String prefix) { + if (freezingScreen) { + pw.print(prefix); pw.print(" freezingScreen="); pw.println(freezingScreen); + } + if (animating || animation != null) { + pw.print(prefix); pw.print("animating="); pw.print(animating); + pw.print(" animation="); pw.println(animation); + } + if (hasTransformation) { + pw.print(prefix); pw.print("XForm: "); + transformation.printShortString(pw); + pw.println(); + } + if (animLayerAdjustment != 0) { + pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment); + } + if (thumbnail != null) { + pw.print(prefix); pw.print("thumbnail="); pw.print(thumbnail); + pw.print(" x="); pw.print(thumbnailX); + pw.print(" y="); pw.print(thumbnailY); + pw.print(" layer="); pw.println(thumbnailLayer); + pw.print(prefix); pw.print("thumbnailAnimation="); pw.println(thumbnailAnimation); + pw.print(prefix); pw.print("thumbnailTransformation="); + pw.println(thumbnailTransformation.toShortString()); + } + } +} diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java index 3069b74..bf35154 100644 --- a/services/java/com/android/server/wm/AppWindowToken.java +++ b/services/java/com/android/server/wm/AppWindowToken.java @@ -18,20 +18,16 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; +import com.android.server.input.InputApplicationHandle; import com.android.server.wm.WindowManagerService.H; import android.content.pm.ActivityInfo; -import android.graphics.Matrix; import android.os.Message; import android.os.RemoteException; import android.util.Slog; import android.view.IApplicationToken; -import android.view.Surface; import android.view.View; import android.view.WindowManager; -import android.view.WindowManagerPolicy; -import android.view.animation.Animation; -import android.view.animation.Transformation; import java.io.PrintWriter; import java.util.ArrayList; @@ -47,6 +43,9 @@ class AppWindowToken extends WindowToken { // All of the windows and child windows that are included in this // application token. Note this list is NOT sorted! final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>(); + final AppWindowAnimator mAppAnimator; + + final WindowAnimator mAnimator; int groupId = -1; boolean appFullscreen; @@ -87,19 +86,6 @@ class AppWindowToken extends WindowToken { // Set to true when the token has been removed from the window mgr. boolean removed; - // Have we been asked to have this token keep the screen frozen? - boolean freezingScreen; - - boolean animating; - Animation animation; - boolean animInitialized; - boolean hasTransformation; - final Transformation transformation = new Transformation(); - - // Offset to the window of all layers in the token, for use by - // AppWindowToken animations. - int animLayerAdjustment; - // Information about an application starting window if displayed. StartingData startingData; WindowState startingWindow; @@ -108,15 +94,6 @@ class AppWindowToken extends WindowToken { boolean startingMoved; boolean firstWindowDrawn; - // Special surface for thumbnail animation. - Surface thumbnail; - int thumbnailTransactionSeq; - int thumbnailX; - int thumbnailY; - int thumbnailLayer; - Animation thumbnailAnimation; - final Transformation thumbnailTransformation = new Transformation(); - // Input application handle used by the input dispatcher. final InputApplicationHandle mInputApplicationHandle; @@ -126,79 +103,8 @@ class AppWindowToken extends WindowToken { appWindowToken = this; appToken = _token; mInputApplicationHandle = new InputApplicationHandle(this); - } - - public void setAnimation(Animation anim, boolean initialized) { - if (WindowManagerService.localLOGV) Slog.v( - WindowManagerService.TAG, "Setting animation in " + this + ": " + anim); - animation = anim; - animating = false; - animInitialized = initialized; - anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION); - anim.scaleCurrentDuration(service.mTransitionAnimationScale); - int zorder = anim.getZAdjustment(); - int adj = 0; - if (zorder == Animation.ZORDER_TOP) { - adj = WindowManagerService.TYPE_LAYER_OFFSET; - } else if (zorder == Animation.ZORDER_BOTTOM) { - adj = -WindowManagerService.TYPE_LAYER_OFFSET; - } - - if (animLayerAdjustment != adj) { - animLayerAdjustment = adj; - updateLayers(); - } - // Start out animation gone if window is gone, or visible if window is visible. - transformation.clear(); - transformation.setAlpha(reportedVisible ? 1 : 0); - hasTransformation = true; - } - - public void setDummyAnimation() { - if (animation == null) { - if (WindowManagerService.localLOGV) Slog.v( - WindowManagerService.TAG, "Setting dummy animation in " + this); - animation = WindowManagerService.sDummyAnimation; - animInitialized = false; - } - } - - public void clearAnimation() { - if (animation != null) { - animation = null; - animating = true; - animInitialized = false; - } - clearThumbnail(); - } - - public void clearThumbnail() { - if (thumbnail != null) { - thumbnail.destroy(); - thumbnail = null; - } - } - - void updateLayers() { - final int N = allAppWindows.size(); - final int adj = animLayerAdjustment; - thumbnailLayer = -1; - for (int i=0; i<N; i++) { - final WindowState w = allAppWindows.get(i); - final WindowStateAnimator winAnimator = w.mWinAnimator; - winAnimator.mAnimLayer = w.mLayer + adj; - if (winAnimator.mAnimLayer > thumbnailLayer) { - thumbnailLayer = winAnimator.mAnimLayer; - } - if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Updating layer " + w + ": " - + winAnimator.mAnimLayer); - if (w == service.mInputMethodTarget && !service.mInputMethodTargetWaitingAnim) { - service.setInputMethodAnimLayerAdjustment(adj); - } - if (w == service.mWallpaperTarget && service.mLowerWallpaperTarget == null) { - service.setWallpaperAnimLayerAdjustmentLocked(adj); - } - } + mAnimator = service.mAnimator; + mAppAnimator = new AppWindowAnimator(_service, this); } void sendAppVisibilityToClients() { @@ -218,154 +124,6 @@ class AppWindowToken extends WindowToken { } } - boolean showAllWindowsLocked() { - boolean isAnimating = false; - final int NW = allAppWindows.size(); - for (int i=0; i<NW; i++) { - WindowStateAnimator winAnimator = allAppWindows.get(i).mWinAnimator; - if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, - "performing show on: " + winAnimator); - winAnimator.performShowLocked(); - isAnimating |= winAnimator.isAnimating(); - } - return isAnimating; - } - - private void stepThumbnailAnimation(long currentTime) { - thumbnailTransformation.clear(); - thumbnailAnimation.getTransformation(currentTime, thumbnailTransformation); - thumbnailTransformation.getMatrix().preTranslate(thumbnailX, thumbnailY); - final boolean screenAnimation = service.mAnimator.mScreenRotationAnimation != null - && service.mAnimator.mScreenRotationAnimation.isAnimating(); - if (screenAnimation) { - thumbnailTransformation.postCompose( - service.mAnimator.mScreenRotationAnimation.getEnterTransformation()); - } - // cache often used attributes locally - final float tmpFloats[] = service.mTmpFloats; - thumbnailTransformation.getMatrix().getValues(tmpFloats); - if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, - "thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X] - + ", " + tmpFloats[Matrix.MTRANS_Y], null); - thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]); - if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, - "thumbnail", "alpha=" + thumbnailTransformation.getAlpha() - + " layer=" + thumbnailLayer - + " matrix=[" + tmpFloats[Matrix.MSCALE_X] - + "," + tmpFloats[Matrix.MSKEW_Y] - + "][" + tmpFloats[Matrix.MSKEW_X] - + "," + tmpFloats[Matrix.MSCALE_Y] + "]", null); - thumbnail.setAlpha(thumbnailTransformation.getAlpha()); - // The thumbnail is layered below the window immediately above this - // token's anim layer. - thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER - - WindowManagerService.LAYER_OFFSET_THUMBNAIL); - thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y], - tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]); - } - - private boolean stepAnimation(long currentTime) { - if (animation == null) { - return false; - } - transformation.clear(); - final boolean more = animation.getTransformation(currentTime, transformation); - if (WindowManagerService.DEBUG_ANIM) Slog.v( - WindowManagerService.TAG, "Stepped animation in " + this + - ": more=" + more + ", xform=" + transformation); - if (!more) { - animation = null; - clearThumbnail(); - if (WindowManagerService.DEBUG_ANIM) Slog.v( - WindowManagerService.TAG, "Finished animation in " + this + - " @ " + currentTime); - } - hasTransformation = more; - return more; - } - - // This must be called while inside a transaction. - boolean stepAnimationLocked(long currentTime, int dw, int dh) { - if (service.okToDisplay()) { - // We will run animations as long as the display isn't frozen. - - if (animation == WindowManagerService.sDummyAnimation) { - // This guy is going to animate, but not yet. For now count - // it as not animating for purposes of scheduling transactions; - // when it is really time to animate, this will be set to - // a real animation and the next call will execute normally. - return false; - } - - if ((allDrawn || animating || startingDisplayed) && animation != null) { - if (!animating) { - if (WindowManagerService.DEBUG_ANIM) Slog.v( - WindowManagerService.TAG, "Starting animation in " + this + - " @ " + currentTime + ": dw=" + dw + " dh=" + dh - + " scale=" + service.mTransitionAnimationScale - + " allDrawn=" + allDrawn + " animating=" + animating); - if (!animInitialized) { - animation.initialize(dw, dh, dw, dh); - } - animation.setStartTime(currentTime); - animating = true; - if (thumbnail != null) { - thumbnail.show(); - thumbnailAnimation.setStartTime(currentTime); - } - } - if (stepAnimation(currentTime)) { - // animation isn't over, step any thumbnail and that's - // it for now. - if (thumbnail != null) { - stepThumbnailAnimation(currentTime); - } - return true; - } - } - } else if (animation != null) { - // If the display is frozen, and there is a pending animation, - // clear it and make sure we run the cleanup code. - animating = true; - animation = null; - } - - hasTransformation = false; - - if (!animating) { - return false; - } - - service.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; - if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - service.debugLayoutRepeats("AppWindowToken"); - } - - clearAnimation(); - animating = false; - if (animLayerAdjustment != 0) { - animLayerAdjustment = 0; - updateLayers(); - } - if (service.mInputMethodTarget != null && service.mInputMethodTarget.mAppToken == this) { - service.moveInputMethodWindowsIfNeededLocked(true); - } - - if (WindowManagerService.DEBUG_ANIM) Slog.v( - WindowManagerService.TAG, "Animation done in " + this - + ": reportedVisible=" + reportedVisible); - - transformation.clear(); - - final int N = windows.size(); - for (int i=0; i<N; i++) { - windows.get(i).mWinAnimator.finishExit(); - } - updateReportedVisibilityLocked(); - - return false; - } - void updateReportedVisibilityLocked() { if (appToken == null) { return; @@ -479,9 +237,8 @@ class AppWindowToken extends WindowToken { pw.print(" willBeHidden="); pw.print(willBeHidden); pw.print(" reportedDrawn="); pw.print(reportedDrawn); pw.print(" reportedVisible="); pw.println(reportedVisible); - if (paused || freezingScreen) { - pw.print(prefix); pw.print("paused="); pw.print(paused); - pw.print(" freezingScreen="); pw.println(freezingScreen); + if (paused) { + pw.print(prefix); pw.print("paused="); pw.println(paused); } if (numInterestingWindows != 0 || numDrawnWindows != 0 || inPendingTransaction || allDrawn) { @@ -491,18 +248,6 @@ class AppWindowToken extends WindowToken { pw.print(" inPendingTransaction="); pw.print(inPendingTransaction); pw.print(" allDrawn="); pw.println(allDrawn); } - if (animating || animation != null) { - pw.print(prefix); pw.print("animating="); pw.print(animating); - pw.print(" animation="); pw.println(animation); - } - if (hasTransformation) { - pw.print(prefix); pw.print("XForm: "); - transformation.printShortString(pw); - pw.println(); - } - if (animLayerAdjustment != 0) { - pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment); - } if (startingData != null || removed || firstWindowDrawn) { pw.print(prefix); pw.print("startingData="); pw.print(startingData); pw.print(" removed="); pw.print(removed); @@ -515,15 +260,6 @@ class AppWindowToken extends WindowToken { pw.print(" startingDisplayed="); pw.print(startingDisplayed); pw.print(" startingMoved"); pw.println(startingMoved); } - if (thumbnail != null) { - pw.print(prefix); pw.print("thumbnail="); pw.print(thumbnail); - pw.print(" x="); pw.print(thumbnailX); - pw.print(" y="); pw.print(thumbnailY); - pw.print(" layer="); pw.println(thumbnailLayer); - pw.print(prefix); pw.print("thumbnailAnimation="); pw.println(thumbnailAnimation); - pw.print(prefix); pw.print("thumbnailTransformation="); - pw.println(thumbnailTransformation.toShortString()); - } } @Override @@ -537,4 +273,4 @@ class AppWindowToken extends WindowToken { } return stringName; } -}
\ No newline at end of file +} diff --git a/services/java/com/android/server/wm/DimAnimator.java b/services/java/com/android/server/wm/DimAnimator.java index 0051d98..b08c864 100644 --- a/services/java/com/android/server/wm/DimAnimator.java +++ b/services/java/com/android/server/wm/DimAnimator.java @@ -41,14 +41,14 @@ class DimAnimator { DimAnimator (SurfaceSession session) { if (mDimSurface == null) { - if (WindowManagerService.SHOW_TRANSACTIONS || - WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG, - " DIM " + mDimSurface + ": CREATE"); try { mDimSurface = new Surface(session, 0, "DimAnimator", -1, 16, 16, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM); + if (WindowManagerService.SHOW_TRANSACTIONS || + WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG, + " DIM " + mDimSurface + ": CREATE"); mDimSurface.setAlpha(0.0f); } catch (Exception e) { Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e); @@ -57,12 +57,17 @@ class DimAnimator { } /** - * Show the dim surface. + * Set's the dim surface's layer and update dim parameters that will be used in + * {@link #updateSurface} after all windows are examined. */ - void show(int dw, int dh) { + void updateParameters(final Resources res, final Parameters params, final long currentTime) { + final int dw = params.mDimWidth; + final int dh = params.mDimHeight; + final WindowStateAnimator winAnimator = params.mDimWinAnimator; + final float target = params.mDimTarget; if (!mDimShown) { - if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" + - dw + "x" + dh + ")"); + if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, + " DIM " + mDimSurface + ": SHOW pos=(0,0) (" + dw + "x" + dh + ")"); mDimShown = true; try { mLastDimWidth = dw; @@ -78,17 +83,9 @@ class DimAnimator { mLastDimHeight = dh; mDimSurface.setSize(dw, dh); } - } - /** - * Set's the dim surface's layer and update dim parameters that will be used in - * {@link #updateSurface} after all windows are examined. - */ - void updateParameters(Resources res, WindowState w, long currentTime) { - final WindowStateAnimator winAnimator = w.mWinAnimator; mDimSurface.setLayer(winAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM); - final float target = w.mExiting ? 0 : w.mAttrs.dimAmount; if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " + mDimSurface + ": layer=" + (winAnimator.mAnimLayer-1) + " target=" + target); if (mDimTargetAlpha != target) { @@ -189,4 +186,18 @@ class DimAnimator { pw.print(" delta="); pw.print(mDimDeltaPerMs); pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime); } + + static class Parameters { + final WindowStateAnimator mDimWinAnimator; + final int mDimWidth; + final int mDimHeight; + final float mDimTarget; + Parameters(final WindowStateAnimator dimWinAnimator, final int dimWidth, + final int dimHeight, final float dimTarget) { + mDimWinAnimator = dimWinAnimator; + mDimWidth = dimWidth; + mDimHeight = dimHeight; + mDimTarget = dimTarget; + } + } }
\ No newline at end of file diff --git a/services/java/com/android/server/wm/DimSurface.java b/services/java/com/android/server/wm/DimSurface.java index dc6cc0d..c1dbb36 100644 --- a/services/java/com/android/server/wm/DimSurface.java +++ b/services/java/com/android/server/wm/DimSurface.java @@ -32,14 +32,14 @@ class DimSurface { DimSurface(SurfaceSession session) { if (mDimSurface == null) { - if (WindowManagerService.SHOW_TRANSACTIONS || - WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG, - " DIM " + mDimSurface + ": CREATE"); try { mDimSurface = new Surface(session, 0, "DimSurface", -1, 16, 16, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM); + if (WindowManagerService.SHOW_TRANSACTIONS || + WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG, + " DIM " + mDimSurface + ": CREATE"); mDimSurface.setAlpha(0.0f); } catch (Exception e) { Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e); diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java index a19035a..b2cf3e0 100644 --- a/services/java/com/android/server/wm/DragState.java +++ b/services/java/com/android/server/wm/DragState.java @@ -16,6 +16,8 @@ package com.android.server.wm; +import com.android.server.input.InputApplicationHandle; +import com.android.server.input.InputWindowHandle; import com.android.server.wm.WindowManagerService.DragInputEventReceiver; import com.android.server.wm.WindowManagerService.H; diff --git a/services/java/com/android/server/wm/FakeWindowImpl.java b/services/java/com/android/server/wm/FakeWindowImpl.java index 121ce18..2527f46 100644 --- a/services/java/com/android/server/wm/FakeWindowImpl.java +++ b/services/java/com/android/server/wm/FakeWindowImpl.java @@ -16,6 +16,9 @@ package com.android.server.wm; +import com.android.server.input.InputApplicationHandle; +import com.android.server.input.InputWindowHandle; + import android.os.Looper; import android.os.Process; import android.util.Slog; diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java index fb74d27..c28cfa2 100644 --- a/services/java/com/android/server/wm/InputMonitor.java +++ b/services/java/com/android/server/wm/InputMonitor.java @@ -16,6 +16,10 @@ package com.android.server.wm; +import com.android.server.input.InputManagerService; +import com.android.server.input.InputApplicationHandle; +import com.android.server.input.InputWindowHandle; + import android.graphics.Rect; import android.os.RemoteException; import android.util.Log; @@ -27,7 +31,7 @@ import android.view.WindowManager; import java.util.ArrayList; import java.util.Arrays; -final class InputMonitor { +final class InputMonitor implements InputManagerService.Callbacks { private final WindowManagerService mService; // Current window with input focus for keys and other non-touch events. May be null. @@ -93,7 +97,7 @@ final class InputMonitor { } if (appWindowToken == null && inputApplicationHandle != null) { - appWindowToken = inputApplicationHandle.appWindowToken; + appWindowToken = (AppWindowToken)inputApplicationHandle.appWindowToken; if (appWindowToken != null) { Slog.i(WindowManagerService.TAG, "Input event dispatching timed out sending to application " @@ -301,7 +305,14 @@ final class InputMonitor { WindowState windowState = focus != null ? (WindowState) focus.windowState : null; return mService.mPolicy.dispatchUnhandledKey(windowState, event, policyFlags); } - + + /* Callback to get pointer layer. */ + public int getPointerLayer() { + return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_POINTER) + * WindowManagerService.TYPE_LAYER_MULTIPLIER + + WindowManagerService.TYPE_LAYER_OFFSET; + } + /* Called when the current input focus changes. * Layer assignment is assumed to be complete by the time this is called. */ diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java index 5a104b2..0d64b68 100644 --- a/services/java/com/android/server/wm/WindowAnimator.java +++ b/services/java/com/android/server/wm/WindowAnimator.java @@ -6,6 +6,9 @@ import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION; import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE; +import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED; + +import static com.android.server.wm.WindowManagerService.H.SET_DIM_PARAMETERS; import android.content.Context; import android.os.SystemClock; @@ -19,9 +22,9 @@ import android.view.animation.Animation; import com.android.internal.policy.impl.PhoneWindowManager; import java.io.PrintWriter; +import java.util.HashSet; /** - * @author cmautner@google.com (Craig Mautner) * Singleton class that carries out the animations and Surface operations in a separate task * on behalf of WindowManagerService. */ @@ -32,6 +35,9 @@ public class WindowAnimator { final Context mContext; final WindowManagerPolicy mPolicy; + HashSet<WindowStateAnimator> mWinAnimators = new HashSet<WindowStateAnimator>(); + HashSet<WindowStateAnimator> mFinished = new HashSet<WindowStateAnimator>(); + boolean mAnimating; boolean mTokenMayBeDrawn; boolean mForceHiding; @@ -67,6 +73,9 @@ public class WindowAnimator { int mBulkUpdateParams = 0; + DimAnimator mDimAnimator = null; + DimAnimator.Parameters mDimParams = null; + WindowAnimator(final WindowManagerService service, final Context context, final WindowManagerPolicy policy) { mService = service; @@ -91,7 +100,8 @@ public class WindowAnimator { if (mService.mWallpaperTarget == target || mService.mLowerWallpaperTarget == target || mService.mUpperWallpaperTarget == target) { - for (int i=0; i<mService.mWindows.size(); i++) { + final int N = mService.mWindows.size(); + for (int i = 0; i < N; i++) { WindowState w = mService.mWindows.get(i); if (w.mIsWallpaper) { target = w; @@ -116,32 +126,34 @@ public class WindowAnimator { int i; final int NAT = mService.mAppTokens.size(); for (i=0; i<NAT; i++) { - final AppWindowToken appToken = mService.mAppTokens.get(i); - final boolean wasAnimating = appToken.animation != null - && appToken.animation != WindowManagerService.sDummyAnimation; - if (appToken.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) { + final AppWindowAnimator appAnimator = mService.mAppTokens.get(i).mAppAnimator; + final boolean wasAnimating = appAnimator.animation != null + && appAnimator.animation != WindowManagerService.sDummyAnimation; + if (appAnimator.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) { mAnimating = true; } else if (wasAnimating) { // stopped animating, do one more pass through the layout mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.debugLayoutRepeats("appToken " + appToken + " done"); + mService.debugLayoutRepeats("appToken " + appAnimator.mAppToken + " done", + mPendingLayoutChanges); } } } final int NEAT = mService.mExitingAppTokens.size(); for (i=0; i<NEAT; i++) { - final AppWindowToken appToken = mService.mExitingAppTokens.get(i); - final boolean wasAnimating = appToken.animation != null - && appToken.animation != WindowManagerService.sDummyAnimation; - if (appToken.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) { + final AppWindowAnimator appAnimator = mService.mExitingAppTokens.get(i).mAppAnimator; + final boolean wasAnimating = appAnimator.animation != null + && appAnimator.animation != WindowManagerService.sDummyAnimation; + if (appAnimator.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) { mAnimating = true; } else if (wasAnimating) { // stopped animating, do one more pass through the layout mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.debugLayoutRepeats("exiting appToken " + appToken + " done"); + mService.debugLayoutRepeats("exiting appToken " + appAnimator.mAppToken + + " done", mPendingLayoutChanges); } } } @@ -163,16 +175,16 @@ public class WindowAnimator { ++mTransactionSequence; for (int i = mService.mWindows.size() - 1; i >= 0; i--) { - WindowState w = mService.mWindows.get(i); - WindowStateAnimator winAnimator = w.mWinAnimator; - final WindowManager.LayoutParams attrs = w.mAttrs; + WindowState win = mService.mWindows.get(i); + WindowStateAnimator winAnimator = win.mWinAnimator; + final int flags = winAnimator.mAttrFlags; if (winAnimator.mSurface != null) { final boolean wasAnimating = winAnimator.mWasAnimating; final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime); if (WindowManagerService.DEBUG_WALLPAPER) { - Slog.v(TAG, w + ": wasAnimating=" + wasAnimating + + Slog.v(TAG, win + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating); } @@ -181,17 +193,17 @@ public class WindowAnimator { // a detached wallpaper animation. if (nowAnimating) { if (winAnimator.mAnimation != null) { - if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0 + if ((flags & FLAG_SHOW_WALLPAPER) != 0 && winAnimator.mAnimation.getDetachWallpaper()) { - mDetachedWallpaper = w; + mDetachedWallpaper = win; } - if (winAnimator.mAnimation.getBackgroundColor() != 0) { + final int backgroundColor = winAnimator.mAnimation.getBackgroundColor(); + if (backgroundColor != 0) { if (mWindowAnimationBackground == null || (winAnimator.mAnimLayer < mWindowAnimationBackground.mWinAnimator.mAnimLayer)) { - mWindowAnimationBackground = w; - mWindowAnimationBackgroundColor = - winAnimator.mAnimation.getBackgroundColor(); + mWindowAnimationBackground = win; + mWindowAnimationBackgroundColor = backgroundColor; } } } @@ -201,58 +213,62 @@ public class WindowAnimator { // If this window's app token is running a detached wallpaper // animation, make a note so we can ensure the wallpaper is // displayed behind it. - if (w.mAppToken != null && w.mAppToken.animation != null - && w.mAppToken.animating) { - if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0 - && w.mAppToken.animation.getDetachWallpaper()) { - mDetachedWallpaper = w; + final AppWindowAnimator appAnimator = + win.mAppToken == null ? null : win.mAppToken.mAppAnimator; + if (appAnimator != null && appAnimator.animation != null + && appAnimator.animating) { + if ((flags & FLAG_SHOW_WALLPAPER) != 0 + && appAnimator.animation.getDetachWallpaper()) { + mDetachedWallpaper = win; } - if (w.mAppToken.animation.getBackgroundColor() != 0) { + final int backgroundColor = appAnimator.animation.getBackgroundColor(); + if (backgroundColor != 0) { if (mWindowAnimationBackground == null || (winAnimator.mAnimLayer < mWindowAnimationBackground.mWinAnimator.mAnimLayer)) { - mWindowAnimationBackground = w; - mWindowAnimationBackgroundColor = - w.mAppToken.animation.getBackgroundColor(); + mWindowAnimationBackground = win; + mWindowAnimationBackgroundColor = backgroundColor; } } } - if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == w) { + if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) { mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2"); + mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2", + mPendingLayoutChanges); } } - if (mPolicy.doesForceHide(w, attrs)) { + if (mPolicy.doesForceHide(win, win.mAttrs)) { if (!wasAnimating && nowAnimating) { if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, "Animation started that could impact force hide: " - + w); - mService.mInnerFields.mWallpaperForceHidingChanged = true; + + win); + mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED; mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3"); + mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3", + mPendingLayoutChanges); } mService.mFocusMayChange = true; - } else if (w.isReadyForDisplay() && winAnimator.mAnimation == null) { + } else if (win.isReadyForDisplay() && winAnimator.mAnimation == null) { mForceHiding = true; } - } else if (mPolicy.canBeForceHidden(w, attrs)) { - boolean changed; + } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) { + final boolean changed; if (mForceHiding) { - changed = w.hideLw(false, false); + changed = win.hideLw(false, false); if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG, - "Now policy hidden: " + w); + "Now policy hidden: " + win); } else { - changed = w.showLw(false, false); + changed = win.showLw(false, false); if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG, - "Now policy shown: " + w); + "Now policy shown: " + win); if (changed) { - if (mService.mInnerFields.mWallpaperForceHidingChanged - && w.isVisibleNow() /*w.isReadyForDisplay()*/) { + if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0 + && win.isVisibleNow() /*w.isReadyForDisplay()*/) { // Assume we will need to animate. If // we don't (because the wallpaper will // stay with the lock screen), then we will @@ -262,7 +278,7 @@ public class WindowAnimator { winAnimator.setAnimation(a); } } - if (mCurrentFocus == null || mCurrentFocus.mLayer < w.mLayer) { + if (mCurrentFocus == null || mCurrentFocus.mLayer < win.mLayer) { // We are showing on to of the current // focus, so re-evaluate focus to make // sure it is correct. @@ -270,55 +286,54 @@ public class WindowAnimator { } } } - if (changed && (attrs.flags - & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { + if (changed && (flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4"); + mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4", + mPendingLayoutChanges); } } } } - final AppWindowToken atoken = w.mAppToken; - if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) { + final AppWindowToken atoken = win.mAppToken; + if (atoken != null && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { if (atoken.lastTransactionSequence != mTransactionSequence) { atoken.lastTransactionSequence = mTransactionSequence; atoken.numInterestingWindows = atoken.numDrawnWindows = 0; atoken.startingDisplayed = false; } - if ((w.isOnScreen() || w.mAttrs.type + if ((win.isOnScreen() || winAnimator.mAttrType == WindowManager.LayoutParams.TYPE_BASE_APPLICATION) - && !w.mExiting && !w.mDestroying) { + && !win.mExiting && !win.mDestroying) { if (WindowManagerService.DEBUG_VISIBILITY || WindowManagerService.DEBUG_ORIENTATION) { - Slog.v(TAG, "Eval win " + w + ": isDrawn=" - + w.isDrawnLw() + Slog.v(TAG, "Eval win " + win + ": isDrawn=" + win.isDrawnLw() + ", isAnimating=" + winAnimator.isAnimating()); - if (!w.isDrawnLw()) { + if (!win.isDrawnLw()) { Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurface - + " pv=" + w.mPolicyVisibility + + " pv=" + win.mPolicyVisibility + " mDrawState=" + winAnimator.mDrawState - + " ah=" + w.mAttachedHidden + + " ah=" + win.mAttachedHidden + " th=" + atoken.hiddenRequested + " a=" + winAnimator.mAnimating); } } - if (w != atoken.startingWindow) { - if (!atoken.freezingScreen || !w.mAppFreezing) { + if (win != atoken.startingWindow) { + if (!atoken.mAppAnimator.freezingScreen || !win.mAppFreezing) { atoken.numInterestingWindows++; - if (w.isDrawnLw()) { + if (win.isDrawnLw()) { atoken.numDrawnWindows++; if (WindowManagerService.DEBUG_VISIBILITY || WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: " + atoken - + " freezingScreen=" + atoken.freezingScreen - + " mAppFreezing=" + w.mAppFreezing); + + " freezingScreen=" + atoken.mAppAnimator.freezingScreen + + " mAppFreezing=" + win.mAppFreezing); mTokenMayBeDrawn = true; } } - } else if (w.isDrawnLw()) { + } else if (win.isDrawnLw()) { atoken.startingDisplayed = true; } } @@ -326,17 +341,20 @@ public class WindowAnimator { if (winAnimator.performShowLocked()) { mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5"); + mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5", + mPendingLayoutChanges); } } } - if (atoken != null && atoken.thumbnail != null) { - if (atoken.thumbnailTransactionSeq != mTransactionSequence) { - atoken.thumbnailTransactionSeq = mTransactionSequence; - atoken.thumbnailLayer = 0; + final AppWindowAnimator appAnimator = + atoken == null ? null : atoken.mAppAnimator; + if (appAnimator != null && appAnimator.thumbnail != null) { + if (appAnimator.thumbnailTransactionSeq != mTransactionSequence) { + appAnimator.thumbnailTransactionSeq = mTransactionSequence; + appAnimator.thumbnailLayer = 0; } - if (atoken.thumbnailLayer < winAnimator.mAnimLayer) { - atoken.thumbnailLayer = winAnimator.mAnimLayer; + if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) { + appAnimator.thumbnailLayer = winAnimator.mAnimLayer; } } } // end forall windows @@ -348,20 +366,19 @@ public class WindowAnimator { final int NT = mService.mAppTokens.size(); for (int i=0; i<NT; i++) { AppWindowToken wtoken = mService.mAppTokens.get(i); - if (wtoken.freezingScreen) { + if (wtoken.mAppAnimator.freezingScreen) { int numInteresting = wtoken.numInterestingWindows; if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + wtoken + " interesting=" + numInteresting + " drawn=" + wtoken.numDrawnWindows); - wtoken.showAllWindowsLocked(); + wtoken.mAppAnimator.showAllWindowsLocked(); mService.unsetAppFreezingScreenLocked(wtoken, false, true); if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG, "Setting mOrientationChangeComplete=true because wtoken " + wtoken + " numInteresting=" + numInteresting + " numDrawn=" + wtoken.numDrawnWindows); - mService.mInnerFields.mOrientationChangeComplete = true; } } else if (!wtoken.allDrawn) { int numInteresting = wtoken.numInterestingWindows; @@ -373,12 +390,13 @@ public class WindowAnimator { wtoken.allDrawn = true; mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.debugLayoutRepeats("testTokenMayBeDrawnLocked"); + mService.debugLayoutRepeats("testTokenMayBeDrawnLocked", + mPendingLayoutChanges); } // We can now show all of the drawn windows! if (!mService.mOpeningApps.contains(wtoken)) { - mAnimating |= wtoken.showAllWindowsLocked(); + mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked(); } } } @@ -419,15 +437,24 @@ public class WindowAnimator { mScreenRotationAnimation.updateSurfaces(); } - final int N = mService.mWindows.size(); - for (int i=N-1; i>=0; i--) { - WindowState w = mService.mWindows.get(i); - w.mWinAnimator.prepareSurfaceLocked(true); + mFinished.clear(); + for (final WindowStateAnimator winAnimator : mWinAnimators) { + if (winAnimator.mSurface == null) { + mFinished.add(winAnimator); + } else { + winAnimator.prepareSurfaceLocked(true); + } + } + for (final WindowStateAnimator winAnimator : mFinished) { + mWinAnimators.remove(winAnimator); } - if (mService.mDimAnimator != null && mService.mDimAnimator.mDimShown) { - mAnimating |= mService.mDimAnimator.updateSurface(mService.mInnerFields.mDimming, - mCurrentTime, !mService.okToDisplay()); + if (mDimParams != null) { + mDimAnimator.updateParameters(mContext.getResources(), mDimParams, mCurrentTime); + } + if (mDimAnimator != null && mDimAnimator.mDimShown) { + mAnimating |= mDimAnimator.updateSurface(mDimParams != null, mCurrentTime, + !mService.okToDisplay()); } if (mService.mBlackFrame != null) { @@ -450,7 +477,7 @@ public class WindowAnimator { } WindowState mCurrentFocus; - void setCurrentFocus(WindowState currentFocus) { + void setCurrentFocus(final WindowState currentFocus) { mCurrentFocus = currentFocus; } @@ -462,6 +489,20 @@ public class WindowAnimator { mInnerDh = appHeight; } + void startDimming(final WindowStateAnimator winAnimator, final float target, + final int width, final int height) { + if (mDimAnimator == null) { + mDimAnimator = new DimAnimator(mService.mFxSession); + } + mService.mH.sendMessage(mService.mH.obtainMessage(SET_DIM_PARAMETERS, + new DimAnimator.Parameters(winAnimator, width, height, target))); + } + + // TODO(cmautner): Move into Handler + void stopDimming() { + mService.mH.sendMessage(mService.mH.obtainMessage(SET_DIM_PARAMETERS, null)); + } + public void dump(PrintWriter pw, String prefix, boolean dumpAll) { if (mWindowDetachedWallpaper != null) { pw.print(" mWindowDetachedWallpaper="); pw.println(mWindowDetachedWallpaper); @@ -470,5 +511,25 @@ public class WindowAnimator { pw.println(" mWindowAnimationBackgroundSurface:"); mWindowAnimationBackgroundSurface.printTo(" ", pw); } + if (mDimAnimator != null) { + pw.println(" mDimAnimator:"); + mDimAnimator.printTo(" ", pw); + } else { + pw.println( " no DimAnimator "); + } + } + + static class SetAnimationParams { + final WindowStateAnimator mWinAnimator; + final Animation mAnimation; + final int mAnimDw; + final int mAnimDh; + public SetAnimationParams(final WindowStateAnimator winAnimator, + final Animation animation, final int animDw, final int animDh) { + mWinAnimator = winAnimator; + mAnimation = animation; + mAnimDw = animDw; + mAnimDh = animDh; + } } } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index afbc348..a7af8fb 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -44,6 +44,8 @@ import com.android.server.EventLogTags; import com.android.server.PowerManagerService; import com.android.server.Watchdog; import com.android.server.am.BatteryStatsService; +import com.android.server.input.InputFilter; +import com.android.server.input.InputManagerService; import android.Manifest; import android.app.ActivityManagerNative; @@ -149,7 +151,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { static final String TAG = "WindowManager"; static final boolean DEBUG = false; - static final boolean DEBUG_ADD_REMOVE = true; + static final boolean DEBUG_ADD_REMOVE = false; static final boolean DEBUG_FOCUS = false; static final boolean DEBUG_ANIM = false; static final boolean DEBUG_LAYOUT = false; @@ -158,7 +160,7 @@ public class WindowManagerService extends IWindowManager.Stub static final boolean DEBUG_INPUT = false; static final boolean DEBUG_INPUT_METHOD = false; static final boolean DEBUG_VISIBILITY = false; - static final boolean DEBUG_WINDOW_MOVEMENT = true; + static final boolean DEBUG_WINDOW_MOVEMENT = false; static final boolean DEBUG_TOKEN_MOVEMENT = false; static final boolean DEBUG_ORIENTATION = false; static final boolean DEBUG_APP_ORIENTATION = false; @@ -171,7 +173,7 @@ public class WindowManagerService extends IWindowManager.Stub static final boolean DEBUG_SCREEN_ON = false; static final boolean DEBUG_SCREENSHOT = false; static final boolean DEBUG_BOOT = false; - static final boolean DEBUG_LAYOUT_REPEATS = false; + static final boolean DEBUG_LAYOUT_REPEATS = true; static final boolean SHOW_SURFACE_ALLOC = false; static final boolean SHOW_TRANSACTIONS = false; static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS; @@ -243,10 +245,6 @@ public class WindowManagerService extends IWindowManager.Stub */ static final boolean CUSTOM_SCREEN_ROTATION = true; - // Maximum number of milliseconds to wait for input event injection. - // FIXME is this value reasonable? - private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000; - // Maximum number of milliseconds to wait for input devices to be enumerated before // proceding with safe mode detection. private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000; @@ -427,7 +425,6 @@ public class WindowManagerService extends IWindowManager.Stub IInputMethodManager mInputMethodManager; SurfaceSession mFxSession; - DimAnimator mDimAnimator = null; Watermark mWatermark; StrictModeFlash mStrictModeFlash; @@ -577,7 +574,7 @@ public class WindowManagerService extends IWindowManager.Stub float mTransitionAnimationScale = 1.0f; float mAnimatorDurationScale = 1.0f; - final InputManager mInputManager; + final InputManagerService mInputManager; // Who is holding the screen on. Session mHoldingScreenOn; @@ -590,8 +587,10 @@ public class WindowManagerService extends IWindowManager.Stub /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple * methods. */ class LayoutFields { - static final int SET_UPDATE_ROTATION = 1 << 0; - static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1; + static final int SET_UPDATE_ROTATION = 1 << 0; + static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1; + static final int SET_FORCE_HIDING_CHANGED = 1 << 2; + static final int CLEAR_ORIENTATION_CHANGE_COMPLETE = 1 << 3; boolean mWallpaperForceHidingChanged = false; boolean mWallpaperMayChange = false; @@ -843,7 +842,7 @@ public class WindowManagerService extends IWindowManager.Stub "KEEP_SCREEN_ON_FLAG"); mHoldingScreenWakeLock.setReferenceCounted(false); - mInputManager = new InputManager(context, this); + mInputManager = new InputManagerService(context, mInputMonitor); mAnimator = new WindowAnimator(this, context, mPolicy); PolicyThread thr = new PolicyThread(mPolicy, this, context, pm); @@ -864,6 +863,10 @@ public class WindowManagerService extends IWindowManager.Stub Watchdog.getInstance().addMonitor(this); } + public InputManagerService getInputManagerService() { + return mInputManager; + } + @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { @@ -1214,7 +1217,7 @@ public class WindowManagerService extends IWindowManager.Stub AppWindowToken token = curTarget.mAppToken; WindowState highestTarget = null; int highestPos = 0; - if (token.animating || token.animation != null) { + if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) { int pos = localmWindows.indexOf(curTarget); while (pos >= 0) { WindowState win = localmWindows.get(pos); @@ -1274,7 +1277,7 @@ public class WindowManagerService extends IWindowManager.Stub mInputMethodTarget = w; mInputMethodTargetWaitingAnim = false; if (w.mAppToken != null) { - setInputMethodAnimLayerAdjustment(w.mAppToken.animLayerAdjustment); + setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment); } else { setInputMethodAnimLayerAdjustment(0); } @@ -1537,12 +1540,12 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured=" + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??") + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null) - ? wallpaperTarget.mAppToken.animation : null) + ? wallpaperTarget.mAppToken.mAppAnimator.animation : null) + " upper=" + mUpperWallpaperTarget + " lower=" + mLowerWallpaperTarget); return (wallpaperTarget != null && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null - && wallpaperTarget.mAppToken.animation != null))) + && wallpaperTarget.mAppToken.mAppAnimator.animation != null))) || mUpperWallpaperTarget != null || mLowerWallpaperTarget != null; } @@ -1582,7 +1585,7 @@ public class WindowManagerService extends IWindowManager.Stub if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) { // If this window's app token is hidden and not animating, // it is of no interest to us. - if (w.mAppToken.hidden && w.mAppToken.animation == null) { + if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) { if (DEBUG_WALLPAPER) Slog.v(TAG, "Skipping not hidden or animating token: " + w); continue; @@ -1597,7 +1600,7 @@ public class WindowManagerService extends IWindowManager.Stub foundW = w; foundI = i; if (w == mWallpaperTarget && ((w.mAppToken != null - && w.mAppToken.animation != null) + && w.mAppToken.mAppAnimator.animation != null) || w.mWinAnimator.mAnimation != null)) { // The current wallpaper target is animating, so we'll // look behind it for another possible target and figure @@ -1656,9 +1659,11 @@ public class WindowManagerService extends IWindowManager.Stub // animating, then we are in our super special mode! if (foundW != null && oldW != null) { boolean oldAnim = oldW.mWinAnimator.mAnimation != null - || (oldW.mAppToken != null && oldW.mAppToken.animation != null); + || (oldW.mAppToken != null + && oldW.mAppToken.mAppAnimator.animation != null); boolean foundAnim = foundW.mWinAnimator.mAnimation != null - || (foundW.mAppToken != null && foundW.mAppToken.animation != null); + || (foundW.mAppToken != null && + foundW.mAppToken.mAppAnimator.animation != null); if (DEBUG_WALLPAPER) { Slog.v(TAG, "New animation: " + foundAnim + " old animation: " + oldAnim); @@ -1711,10 +1716,10 @@ public class WindowManagerService extends IWindowManager.Stub // Is it time to stop animating? boolean lowerAnimating = mLowerWallpaperTarget.mWinAnimator.mAnimation != null || (mLowerWallpaperTarget.mAppToken != null - && mLowerWallpaperTarget.mAppToken.animation != null); + && mLowerWallpaperTarget.mAppToken.mAppAnimator.animation != null); boolean upperAnimating = mUpperWallpaperTarget.mWinAnimator.mAnimation != null || (mUpperWallpaperTarget.mAppToken != null - && mUpperWallpaperTarget.mAppToken.animation != null); + && mUpperWallpaperTarget.mAppToken.mAppAnimator.animation != null); if (!lowerAnimating || !upperAnimating) { if (DEBUG_WALLPAPER) { Slog.v(TAG, "No longer animating wallpaper targets!"); @@ -1736,7 +1741,7 @@ public class WindowManagerService extends IWindowManager.Stub // between two wallpaper targets. mWallpaperAnimLayerAdjustment = (mLowerWallpaperTarget == null && foundW.mAppToken != null) - ? foundW.mAppToken.animLayerAdjustment : 0; + ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0; final int maxLayer = mPolicy.getMaxWallpaperLayer() * TYPE_LAYER_MULTIPLIER @@ -2007,6 +2012,7 @@ public class WindowManagerService extends IWindowManager.Stub winAnimator.computeShownFrameLocked(); // No need to lay out the windows - we can just set the wallpaper position // directly. + // TODO(cmautner): Don't move this from here, just lock the WindowAnimator. if (winAnimator.mSurfaceX != wallpaper.mShownFrame.left || winAnimator.mSurfaceY != wallpaper.mShownFrame.top) { Surface.openTransaction(); @@ -2306,7 +2312,7 @@ public class WindowManagerService extends IWindowManager.Stub + " mExiting=" + win.mExiting + " isAnimating=" + win.mWinAnimator.isAnimating() + " app-animation=" - + (win.mAppToken != null ? win.mAppToken.animation : null) + + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null) + " inPendingTransaction=" + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false) + " mDisplayFrozen=" + mDisplayFrozen); @@ -3174,13 +3180,13 @@ public class WindowManagerService extends IWindowManager.Stub } Slog.v(TAG, "Loaded animation " + a + " for " + wtoken, e); } - wtoken.setAnimation(a, initialized); + wtoken.mAppAnimator.setAnimation(a, initialized); } } else { - wtoken.clearAnimation(); + wtoken.mAppAnimator.clearAnimation(); } - return wtoken.animation != null; + return wtoken.mAppAnimator.animation != null; } // ------------------------------------------------------------- @@ -3325,7 +3331,7 @@ public class WindowManagerService extends IWindowManager.Stub "addAppToken()")) { throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); } - + // Get the dispatching timeout here while we are not holding any locks so that it // can be cached by the AppWindowToken. The timeout value is used later by the // input dispatcher in code that does hold locks. If we did not cache the value @@ -3828,14 +3834,16 @@ public class WindowManagerService extends IWindowManager.Stub wtoken.clientHidden = ttoken.clientHidden; wtoken.sendAppVisibilityToClients(); } - if (ttoken.animation != null) { - wtoken.animation = ttoken.animation; - wtoken.animating = ttoken.animating; - wtoken.animLayerAdjustment = ttoken.animLayerAdjustment; - ttoken.animation = null; - ttoken.animLayerAdjustment = 0; - wtoken.updateLayers(); - ttoken.updateLayers(); + final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; + final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; + if (tAppAnimator.animation != null) { + wAppAnimator.animation = tAppAnimator.animation; + wAppAnimator.animating = tAppAnimator.animating; + wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment; + tAppAnimator.animation = null; + tAppAnimator.animLayerAdjustment = 0; + wAppAnimator.updateLayers(); + tAppAnimator.updateLayers(); } updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, @@ -3860,18 +3868,20 @@ public class WindowManagerService extends IWindowManager.Stub mH.sendMessageAtFrontOfQueue(m); return; } - if (ttoken.thumbnail != null) { + final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; + final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; + if (tAppAnimator.thumbnail != null) { // The old token is animating with a thumbnail, transfer // that to the new token. - if (wtoken.thumbnail != null) { - wtoken.thumbnail.destroy(); + if (wAppAnimator.thumbnail != null) { + wAppAnimator.thumbnail.destroy(); } - wtoken.thumbnail = ttoken.thumbnail; - wtoken.thumbnailX = ttoken.thumbnailX; - wtoken.thumbnailY = ttoken.thumbnailY; - wtoken.thumbnailLayer = ttoken.thumbnailLayer; - wtoken.thumbnailAnimation = ttoken.thumbnailAnimation; - ttoken.thumbnail = null; + wAppAnimator.thumbnail = tAppAnimator.thumbnail; + wAppAnimator.thumbnailX = tAppAnimator.thumbnailX; + wAppAnimator.thumbnailY = tAppAnimator.thumbnailY; + wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer; + wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation; + tAppAnimator.thumbnail = null; } } } @@ -3961,12 +3971,12 @@ public class WindowManagerService extends IWindowManager.Stub boolean runningAppAnimation = false; if (transit != WindowManagerPolicy.TRANSIT_UNSET) { - if (wtoken.animation == sDummyAnimation) { - wtoken.animation = null; + if (wtoken.mAppAnimator.animation == sDummyAnimation) { + wtoken.mAppAnimator.animation = null; } applyAnimationLocked(wtoken, lp, transit, visible); changed = true; - if (wtoken.animation != null) { + if (wtoken.mAppAnimator.animation != null) { delayed = runningAppAnimation = true; } } @@ -4029,7 +4039,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - if (wtoken.animation != null) { + if (wtoken.mAppAnimator.animation != null) { delayed = true; } @@ -4074,7 +4084,7 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_APP_TRANSITIONS) Slog.v( TAG, "Setting dummy animation on: " + wtoken); - wtoken.setDummyAnimation(); + wtoken.mAppAnimator.setDummyAnimation(); mOpeningApps.remove(wtoken); mClosingApps.remove(wtoken); wtoken.waitingToShow = wtoken.waitingToHide = false; @@ -4124,7 +4134,7 @@ public class WindowManagerService extends IWindowManager.Stub void unsetAppFreezingScreenLocked(AppWindowToken wtoken, boolean unfreezeSurfaceNow, boolean force) { - if (wtoken.freezingScreen) { + if (wtoken.mAppAnimator.freezingScreen) { if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken + " force=" + force); final int N = wtoken.allAppWindows.size(); @@ -4142,7 +4152,7 @@ public class WindowManagerService extends IWindowManager.Stub } if (force || unfrozeWindows) { if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken); - wtoken.freezingScreen = false; + wtoken.mAppAnimator.freezingScreen = false; mAppsFreezingScreen--; } if (unfreezeSurfaceNow) { @@ -4165,11 +4175,11 @@ public class WindowManagerService extends IWindowManager.Stub } Slog.i(TAG, "Set freezing of " + wtoken.appToken + ": hidden=" + wtoken.hidden + " freezing=" - + wtoken.freezingScreen, e); + + wtoken.mAppAnimator.freezingScreen, e); } if (!wtoken.hiddenRequested) { - if (!wtoken.freezingScreen) { - wtoken.freezingScreen = true; + if (!wtoken.mAppAnimator.freezingScreen) { + wtoken.mAppAnimator.freezingScreen = true; mAppsFreezingScreen++; if (mAppsFreezingScreen == 1) { startFreezingDisplayLocked(false); @@ -4222,7 +4232,7 @@ public class WindowManagerService extends IWindowManager.Stub } final long origId = Binder.clearCallingIdentity(); if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token - + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.freezingScreen); + + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen); unsetAppFreezingScreenLocked(wtoken, true, force); Binder.restoreCallingIdentity(origId); } @@ -4257,8 +4267,8 @@ public class WindowManagerService extends IWindowManager.Stub } if (DEBUG_APP_TRANSITIONS) Slog.v( TAG, "Removing app " + wtoken + " delayed=" + delayed - + " animation=" + wtoken.animation - + " animating=" + wtoken.animating); + + " animation=" + wtoken.mAppAnimator.animation + + " animating=" + wtoken.mAppAnimator.animating); if (delayed) { // set the token aside because it has an active animation to be finished if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, @@ -4268,9 +4278,8 @@ public class WindowManagerService extends IWindowManager.Stub // Make sure there is no animation running on this token, // so any windows associated with it will be removed as // soon as their animations are complete - wtoken.clearAnimation(); - wtoken.animation = null; - wtoken.animating = false; + wtoken.mAppAnimator.clearAnimation(); + wtoken.mAppAnimator.animating = false; } if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: " + wtoken); @@ -4792,95 +4801,26 @@ public class WindowManagerService extends IWindowManager.Stub mAnimatorDurationScale }; } - public int getSwitchState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getSwitchState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, sw); - } - - public int getSwitchStateForDevice(int devid, int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getSwitchStateForDevice()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getSwitchState(devid, InputDevice.SOURCE_ANY, sw); - } - - public int getScancodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getScancodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_ANY, sw); - } - - public int getScancodeStateForDevice(int devid, int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getScancodeStateForDevice()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getScanCodeState(devid, InputDevice.SOURCE_ANY, sw); - } - - public int getTrackballScancodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getTrackballScancodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, sw); - } - - public int getDPadScancodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getDPadScancodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_DPAD, sw); - } - - public int getKeycodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getKeycodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, sw); - } - - public int getKeycodeStateForDevice(int devid, int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getKeycodeStateForDevice()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getKeyCodeState(devid, InputDevice.SOURCE_ANY, sw); - } - - public int getTrackballKeycodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getTrackballKeycodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); + // Called by window manager policy. Not exposed externally. + @Override + public int getLidState() { + final int SW_LID = 0x00; + int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_LID); + if (sw > 0) { + // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. + return LID_CLOSED; + } else if (sw == 0) { + // Switch state: AKEY_STATE_UP. + return LID_OPEN; + } else { + // Switch state: AKEY_STATE_UNKNOWN. + return LID_ABSENT; } - return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_TRACKBALL, sw); - } - - public int getDPadKeycodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getDPadKeycodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, sw); - } - - public boolean hasKeys(int[] keycodes, boolean[] keyExists) { - return mInputManager.hasKeys(-1, InputDevice.SOURCE_ANY, keycodes, keyExists); } + // Called by window manager policy. Not exposed externally. + @Override public InputChannel monitorInput(String inputChannelName) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "monitorInput()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } return mInputManager.monitorInput(inputChannelName); } @@ -4888,14 +4828,6 @@ public class WindowManagerService extends IWindowManager.Stub mInputManager.setInputFilter(filter); } - public InputDevice getInputDevice(int deviceId) { - return mInputManager.getInputDevice(deviceId); - } - - public int[] getInputDeviceIds() { - return mInputManager.getInputDeviceIds(); - } - public void enableScreenAfterBoot() { synchronized(mWindowMap) { if (DEBUG_BOOT) { @@ -5052,7 +4984,7 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.enableScreenAfterBoot(); // Make sure the last requested orientation has been applied. - updateRotationUnchecked(false); + updateRotationUnchecked(false, false); } public void showBootMessage(final CharSequence msg, final boolean always) { @@ -5326,7 +5258,7 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, rotation == -1 ? mRotation : rotation); - updateRotationUnchecked(false); + updateRotationUnchecked(false, false); } /** @@ -5342,7 +5274,7 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 777); // rot not used - updateRotationUnchecked(false); + updateRotationUnchecked(false, false); } /** @@ -5352,8 +5284,8 @@ public class WindowManagerService extends IWindowManager.Stub * such that the current rotation might need to be updated, such as when the * device is docked or rotated into a new posture. */ - public void updateRotation(boolean alwaysSendConfiguration) { - updateRotationUnchecked(alwaysSendConfiguration); + public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { + updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); } /** @@ -5383,8 +5315,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - public void updateRotationUnchecked( - boolean alwaysSendConfiguration) { + public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); @@ -5392,6 +5323,10 @@ public class WindowManagerService extends IWindowManager.Stub boolean changed; synchronized(mWindowMap) { changed = updateRotationUncheckedLocked(false); + if (!changed || forceRelayout) { + mLayoutNeeded = true; + performLayoutAndPlaceSurfacesLocked(); + } } if (changed || alwaysSendConfiguration) { @@ -6378,164 +6313,6 @@ public class WindowManagerService extends IWindowManager.Stub sendScreenStatusToClients(); } - /** - * Injects a keystroke event into the UI. - * Even when sync is false, this method may block while waiting for current - * input events to be dispatched. - * - * @param ev A motion event describing the keystroke action. (Be sure to use - * {@link SystemClock#uptimeMillis()} as the timebase.) - * @param sync If true, wait for the event to be completed before returning to the caller. - * @return Returns true if event was dispatched, false if it was dropped for any reason - */ - public boolean injectKeyEvent(KeyEvent ev, boolean sync) { - long downTime = ev.getDownTime(); - long eventTime = ev.getEventTime(); - - int action = ev.getAction(); - int code = ev.getKeyCode(); - int repeatCount = ev.getRepeatCount(); - int metaState = ev.getMetaState(); - int deviceId = ev.getDeviceId(); - int scancode = ev.getScanCode(); - int source = ev.getSource(); - int flags = ev.getFlags(); - - if (source == InputDevice.SOURCE_UNKNOWN) { - source = InputDevice.SOURCE_KEYBOARD; - } - - if (eventTime == 0) eventTime = SystemClock.uptimeMillis(); - if (downTime == 0) downTime = eventTime; - - KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState, - deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source); - - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - - final int result = mInputManager.injectInputEvent(newEvent, pid, uid, - sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH - : InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, - INJECTION_TIMEOUT_MILLIS); - - Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result, pid); - } - - /** - * Inject a pointer (touch) event into the UI. - * Even when sync is false, this method may block while waiting for current - * input events to be dispatched. - * - * @param ev A motion event describing the pointer (touch) action. (As noted in - * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use - * {@link SystemClock#uptimeMillis()} as the timebase.) - * @param sync If true, wait for the event to be completed before returning to the caller. - * @return Returns true if event was dispatched, false if it was dropped for any reason - */ - public boolean injectPointerEvent(MotionEvent ev, boolean sync) { - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - - MotionEvent newEvent = MotionEvent.obtain(ev); - if ((newEvent.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) { - newEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN); - } - - final int result = mInputManager.injectInputEvent(newEvent, pid, uid, - sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH - : InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, - INJECTION_TIMEOUT_MILLIS); - - Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result, pid); - } - - /** - * Inject a trackball (navigation device) event into the UI. - * Even when sync is false, this method may block while waiting for current - * input events to be dispatched. - * - * @param ev A motion event describing the trackball action. (As noted in - * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use - * {@link SystemClock#uptimeMillis()} as the timebase.) - * @param sync If true, wait for the event to be completed before returning to the caller. - * @return Returns true if event was dispatched, false if it was dropped for any reason - */ - public boolean injectTrackballEvent(MotionEvent ev, boolean sync) { - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - - MotionEvent newEvent = MotionEvent.obtain(ev); - if ((newEvent.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) { - newEvent.setSource(InputDevice.SOURCE_TRACKBALL); - } - - final int result = mInputManager.injectInputEvent(newEvent, pid, uid, - sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH - : InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, - INJECTION_TIMEOUT_MILLIS); - - Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result, pid); - } - - /** - * Inject an input event into the UI without waiting for dispatch to commence. - * This variant is useful for fire-and-forget input event injection. It does not - * block any longer than it takes to enqueue the input event. - * - * @param ev An input event. (Be sure to set the input source correctly.) - * @return Returns true if event was dispatched, false if it was dropped for any reason - */ - public boolean injectInputEventNoWait(InputEvent ev) { - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - - final int result = mInputManager.injectInputEvent(ev, pid, uid, - InputManager.INPUT_EVENT_INJECTION_SYNC_NONE, - INJECTION_TIMEOUT_MILLIS); - - Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result, pid); - } - - private boolean reportInjectionResult(int result, int pid) { - switch (result) { - case InputManager.INPUT_EVENT_INJECTION_PERMISSION_DENIED: - Slog.w(TAG, "Input event injection from pid " + pid + " permission denied."); - throw new SecurityException( - "Injecting to another application requires INJECT_EVENTS permission"); - case InputManager.INPUT_EVENT_INJECTION_SUCCEEDED: - return true; - case InputManager.INPUT_EVENT_INJECTION_TIMED_OUT: - Slog.w(TAG, "Input event injection from pid " + pid + " timed out."); - return false; - case InputManager.INPUT_EVENT_INJECTION_FAILED: - default: - Slog.w(TAG, "Input event injection from pid " + pid + " failed."); - return false; - } - } - - /** - * Temporarily set the pointer speed. Does not save the new setting. - * Used by the settings application. - */ - public void setPointerSpeed(int speed) { - if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED, - "setPointerSpeed()")) { - throw new SecurityException("Requires SET_POINTER_SPEED permission"); - } - - mInputManager.setPointerSpeed(speed); - } - private WindowState getFocusedWindow() { synchronized (mWindowMap) { return getFocusedWindowLocked(); @@ -6550,11 +6327,29 @@ public class WindowManagerService extends IWindowManager.Stub if (!mInputMonitor.waitForInputDevicesReady( INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { Slog.w(TAG, "Devices still not ready after waiting " - + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS - + " milliseconds before attempting to detect safe mode."); + + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS + + " milliseconds before attempting to detect safe mode."); + } + + final int BTN_MOUSE = 0x110; + int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, + KeyEvent.KEYCODE_MENU); + int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); + int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, + KeyEvent.KEYCODE_DPAD_CENTER); + int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, + BTN_MOUSE); + int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, + KeyEvent.KEYCODE_VOLUME_DOWN); + mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 + || volumeDownState > 0; + if (mSafeMode) { + Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState + + " dpad=" + dpadState + " trackball=" + trackballState + ")"); + } else { + Log.i(TAG, "SAFE MODE not enabled"); } - - mSafeMode = mPolicy.detectSafeMode(); + mPolicy.setSafeMode(mSafeMode); return mSafeMode; } @@ -6584,7 +6379,7 @@ public class WindowManagerService extends IWindowManager.Stub mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY, mDisplay.getRawWidth(), mDisplay.getRawHeight(), mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight()); - mPolicy.setInitialDisplaySize(mInitialDisplayWidth, mInitialDisplayHeight); + mPolicy.setInitialDisplaySize(mDisplay, mInitialDisplayWidth, mInitialDisplayHeight); } try { @@ -6657,6 +6452,8 @@ public class WindowManagerService extends IWindowManager.Stub public static final int ANIMATOR_WHAT_OFFSET = 100000; public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1; public static final int SET_WALLPAPER_OFFSET = ANIMATOR_WHAT_OFFSET + 2; + public static final int SET_DIM_PARAMETERS = ANIMATOR_WHAT_OFFSET + 3; + public static final int SET_MOVE_ANIMATION = ANIMATOR_WHAT_OFFSET + 4; private Session mLastReportedHold; @@ -6980,14 +6777,16 @@ public class WindowManagerService extends IWindowManager.Stub case APP_FREEZE_TIMEOUT: { synchronized (mWindowMap) { - Slog.w(TAG, "App freeze timeout expired."); - int i = mAppTokens.size(); - while (i > 0) { - i--; - AppWindowToken tok = mAppTokens.get(i); - if (tok.freezingScreen) { - Slog.w(TAG, "Force clearing freeze: " + tok); - unsetAppFreezingScreenLocked(tok, true, true); + synchronized (mAnimator) { + Slog.w(TAG, "App freeze timeout expired."); + int i = mAppTokens.size(); + while (i > 0) { + i--; + AppWindowToken tok = mAppTokens.get(i); + if (tok.mAppAnimator.freezingScreen) { + Slog.w(TAG, "Force clearing freeze: " + tok); + unsetAppFreezingScreenLocked(tok, true, true); + } } } } @@ -7069,6 +6868,7 @@ public class WindowManagerService extends IWindowManager.Stub } case BULK_UPDATE_PARAMETERS: { + // Used to send multiple changes from the animation side to the layout side. synchronized (mWindowMap) { // TODO(cmautner): As the number of bits grows, use masks of bit groups to // eliminate unnecessary tests. @@ -7078,6 +6878,12 @@ public class WindowManagerService extends IWindowManager.Stub if ((msg.arg1 & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { mInnerFields.mWallpaperMayChange = true; } + if ((msg.arg1 & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { + mInnerFields.mWallpaperForceHidingChanged = true; + } + if ((msg.arg1 & LayoutFields.CLEAR_ORIENTATION_CHANGE_COMPLETE) != 0) { + mInnerFields.mOrientationChangeComplete = false; + } requestTraversalLocked(); } @@ -7086,22 +6892,39 @@ public class WindowManagerService extends IWindowManager.Stub // Animation messages. Move to Window{State}Animator case SET_TRANSPARENT_REGION: { - // TODO(cmautner): Remove sync. - synchronized (mWindowMap) { - Pair<WindowStateAnimator, Region> pair = + Pair<WindowStateAnimator, Region> pair = (Pair<WindowStateAnimator, Region>) msg.obj; - final WindowStateAnimator winAnimator = pair.first; - winAnimator.setTransparentRegionHint(pair.second); - } + final WindowStateAnimator winAnimator = pair.first; + winAnimator.setTransparentRegionHint(pair.second); + + scheduleAnimationLocked(); break; } case SET_WALLPAPER_OFFSET: { - // TODO(cmautner): Remove sync. - synchronized (mWindowMap) { - final WindowStateAnimator winAnimator = (WindowStateAnimator) msg.obj; - winAnimator.setWallpaperOffset(msg.arg1, msg.arg2); - } + final WindowStateAnimator winAnimator = (WindowStateAnimator) msg.obj; + winAnimator.setWallpaperOffset(msg.arg1, msg.arg2); + + scheduleAnimationLocked(); + break; + } + + case SET_DIM_PARAMETERS: { + mAnimator.mDimParams = (DimAnimator.Parameters) msg.obj; + + scheduleAnimationLocked(); + break; + } + + case SET_MOVE_ANIMATION: { + WindowAnimator.SetAnimationParams params = + (WindowAnimator.SetAnimationParams) msg.obj; + WindowStateAnimator winAnimator = params.mWinAnimator; + winAnimator.setAnimation(params.mAnimation); + winAnimator.mAnimDw = params.mAnimDw; + winAnimator.mAnimDh = params.mAnimDh; + + scheduleAnimationLocked(); break; } } @@ -7281,7 +7104,7 @@ public class WindowManagerService extends IWindowManager.Stub mBaseDisplayWidth = width; mBaseDisplayHeight = height; } - mPolicy.setInitialDisplaySize(mBaseDisplayWidth, mBaseDisplayHeight); + mPolicy.setInitialDisplaySize(mDisplay, mBaseDisplayWidth, mBaseDisplayHeight); mLayoutNeeded = true; @@ -7313,8 +7136,8 @@ public class WindowManagerService extends IWindowManager.Stub } } - public boolean canStatusBarHide() { - return mPolicy.canStatusBarHide(); + public boolean hasSystemNavBar() { + return mPolicy.hasSystemNavBar(); } // ------------------------------------------------------------- @@ -7450,9 +7273,11 @@ public class WindowManagerService extends IWindowManager.Stub w.mLayer = curLayer; } if (w.mTargetAppToken != null) { - w.mWinAnimator.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment; + w.mWinAnimator.mAnimLayer = + w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; } else if (w.mAppToken != null) { - w.mWinAnimator.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment; + w.mWinAnimator.mAnimLayer = + w.mLayer + w.mAppToken.mAppAnimator.animLayerAdjustment; } else { w.mWinAnimator.mAnimLayer = w.mLayer; } @@ -7881,20 +7706,19 @@ public class WindowManagerService extends IWindowManager.Stub AppWindowToken topOpeningApp = null; int topOpeningLayer = 0; + // TODO(cmautner): Move to animation side. NN = mOpeningApps.size(); for (i=0; i<NN; i++) { AppWindowToken wtoken = mOpeningApps.get(i); - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, - "Now opening app" + wtoken); - wtoken.clearThumbnail(); + if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); + wtoken.mAppAnimator.clearThumbnail(); wtoken.reportedVisible = false; wtoken.inPendingTransaction = false; - wtoken.animation = null; - setTokenVisibilityLocked(wtoken, animLp, true, - transit, false); + wtoken.mAppAnimator.animation = null; + setTokenVisibilityLocked(wtoken, animLp, true, transit, false); wtoken.updateReportedVisibilityLocked(); wtoken.waitingToShow = false; - mAnimator.mAnimating |= wtoken.showAllWindowsLocked(); + mAnimator.mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked(); if (animLp != null) { int layer = -1; for (int j=0; j<wtoken.windows.size(); j++) { @@ -7914,9 +7738,9 @@ public class WindowManagerService extends IWindowManager.Stub AppWindowToken wtoken = mClosingApps.get(i); if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app" + wtoken); - wtoken.clearThumbnail(); + wtoken.mAppAnimator.clearThumbnail(); wtoken.inPendingTransaction = false; - wtoken.animation = null; + wtoken.mAppAnimator.animation = null; setTokenVisibilityLocked(wtoken, animLp, false, transit, false); wtoken.updateReportedVisibilityLocked(); @@ -7928,7 +7752,7 @@ public class WindowManagerService extends IWindowManager.Stub } if (mNextAppTransitionThumbnail != null && topOpeningApp != null - && topOpeningApp.animation != null) { + && topOpeningApp.mAppAnimator.animation != null) { // This thumbnail animation is very special, we need to have // an extra surface with the thumbnail included with the animation. Rect dirty = new Rect(0, 0, mNextAppTransitionThumbnail.getWidth(), @@ -7937,7 +7761,7 @@ public class WindowManagerService extends IWindowManager.Stub Surface surface = new Surface(mFxSession, Process.myPid(), "thumbnail anim", 0, dirty.width(), dirty.height(), PixelFormat.TRANSLUCENT, Surface.HIDDEN); - topOpeningApp.thumbnail = surface; + topOpeningApp.mAppAnimator.thumbnail = surface; if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surface + ": CREATE"); Surface drawSurface = new Surface(); @@ -7946,17 +7770,17 @@ public class WindowManagerService extends IWindowManager.Stub c.drawBitmap(mNextAppTransitionThumbnail, 0, 0, null); drawSurface.unlockCanvasAndPost(c); drawSurface.release(); - topOpeningApp.thumbnailLayer = topOpeningLayer; + topOpeningApp.mAppAnimator.thumbnailLayer = topOpeningLayer; Animation anim = createThumbnailAnimationLocked(transit, true, true); - topOpeningApp.thumbnailAnimation = anim; + topOpeningApp.mAppAnimator.thumbnailAnimation = anim; anim.restrictDuration(MAX_ANIMATION_DURATION); anim.scaleCurrentDuration(mTransitionAnimationScale); - topOpeningApp.thumbnailX = mNextAppTransitionStartX; - topOpeningApp.thumbnailY = mNextAppTransitionStartY; + topOpeningApp.mAppAnimator.thumbnailX = mNextAppTransitionStartX; + topOpeningApp.mAppAnimator.thumbnailY = mNextAppTransitionStartY; } catch (Surface.OutOfResourcesException e) { Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width() + " h=" + dirty.height(), e); - topOpeningApp.clearThumbnail(); + topOpeningApp.mAppAnimator.clearThumbnail(); } } @@ -8038,7 +7862,6 @@ public class WindowManagerService extends IWindowManager.Stub } } mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked(); - mInnerFields.mWallpaperForceHidingChanged = false; if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper + " NEW: " + mWallpaperTarget + " LOWER: " + mLowerWallpaperTarget); @@ -8177,16 +8000,16 @@ public class WindowManagerService extends IWindowManager.Stub if (!mInnerFields.mDimming) { //Slog.i(TAG, "DIM BEHIND: " + w); mInnerFields.mDimming = true; - if (mDimAnimator == null) { - mDimAnimator = new DimAnimator(mFxSession); - } + final int width, height; if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) { - mDimAnimator.show(mCurDisplayWidth, mCurDisplayHeight); + width = mCurDisplayWidth; + height = mCurDisplayHeight; } else { - mDimAnimator.show(innerDw, innerDh); + width = innerDw; + height = innerDh; } - mDimAnimator.updateParameters(mContext.getResources(), - w, currentTime); + mAnimator.startDimming(w.mWinAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, + width, height); } } } @@ -8223,7 +8046,6 @@ public class WindowManagerService extends IWindowManager.Stub mExitingAppTokens.get(i).hasVisible = false; } - mInnerFields.mOrientationChangeComplete = true; mInnerFields.mHoldScreen = null; mInnerFields.mScreenBrightness = -1; mInnerFields.mButtonBrightness = -1; @@ -8252,7 +8074,6 @@ public class WindowManagerService extends IWindowManager.Stub } try { - mInnerFields.mWallpaperForceHidingChanged = false; int repeats = 0; do { @@ -8263,7 +8084,8 @@ public class WindowManagerService extends IWindowManager.Stub break; } - if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner"); + if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", + mPendingLayoutChanges); if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) { if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { @@ -8294,7 +8116,8 @@ public class WindowManagerService extends IWindowManager.Stub // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think // it is animating. mPendingLayoutChanges = 0; - if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " + mLayoutRepeatCount); + if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " + mLayoutRepeatCount, + mPendingLayoutChanges); mPolicy.beginAnimationLw(dw, dh); for (i = mWindows.size() - 1; i >= 0; i--) { WindowState w = mWindows.get(i); @@ -8303,7 +8126,8 @@ public class WindowManagerService extends IWindowManager.Stub } } mPendingLayoutChanges |= mPolicy.finishAnimationLw(); - if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishAnimationLw"); + if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishAnimationLw", + mPendingLayoutChanges); } while (mPendingLayoutChanges != 0); final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); @@ -8315,8 +8139,6 @@ public class WindowManagerService extends IWindowManager.Stub final int N = mWindows.size(); for (i=N-1; i>=0; i--) { WindowState w = mWindows.get(i); - //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); - w.mContentChanged = false; if (someoneLosingFocus && w == mCurrentFocus && w.isDisplayedLw()) { focusDisplayed = true; @@ -8337,6 +8159,9 @@ public class WindowManagerService extends IWindowManager.Stub updateWallpaperVisibilityLocked(); } } + if (!mInnerFields.mDimming && mAnimator.mDimParams != null) { + mAnimator.stopDimming(); + } } catch (RuntimeException e) { Log.wtf(TAG, "Unhandled exception in Window Manager", e); } finally { @@ -8348,7 +8173,8 @@ public class WindowManagerService extends IWindowManager.Stub // to go. if (mAppTransitionReady) { mPendingLayoutChanges |= handleAppTransitionReadyLocked(); - if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked"); + if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", + mPendingLayoutChanges); } mInnerFields.mAdjResult = 0; @@ -8361,7 +8187,8 @@ public class WindowManagerService extends IWindowManager.Stub // be out of sync with it. So here we will just rebuild the // entire app window list. Fun! mPendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); - if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock"); + if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", + mPendingLayoutChanges); } if (mInnerFields.mWallpaperForceHidingChanged && mPendingLayoutChanges == 0 && @@ -8373,9 +8200,10 @@ public class WindowManagerService extends IWindowManager.Stub // hard -- the wallpaper now needs to be shown behind // something that was hidden. mPendingLayoutChanges |= animateAwayWallpaperLocked(); - if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked"); + if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", + mPendingLayoutChanges); } - + mInnerFields.mWallpaperForceHidingChanged = false; if (mInnerFields.mWallpaperMayChange) { if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, @@ -8405,13 +8233,34 @@ public class WindowManagerService extends IWindowManager.Stub if (mLayoutNeeded) { mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; - if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded"); + if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", mPendingLayoutChanges); } final int N = mWindows.size(); for (i=N-1; i>=0; i--) { final WindowState w = mWindows.get(i); final WindowStateAnimator winAnimator = w.mWinAnimator; + + // If the window has moved due to its containing + // content frame changing, then we'd like to animate + // it. + if (w.mHasSurface && w.shouldAnimateMove()) { + // Frame has moved, containing content frame + // has also moved, and we're not currently animating... + // let's do something. + Animation a = AnimationUtils.loadAnimation(mContext, + com.android.internal.R.anim.window_move_from_decor); + winAnimator.setAnimation(a); + winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; + winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; + } else { + winAnimator.mAnimDw = innerDw; + winAnimator.mAnimDh = innerDh; + } + + //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); + w.mContentChanged = false; + // TODO(cmautner): Can this move up to the loop at the end of try/catch above? updateResizingWindows(w); @@ -8426,28 +8275,11 @@ public class WindowManagerService extends IWindowManager.Stub mInnerFields.mWallpaperMayChange = true; mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - debugLayoutRepeats("updateWindowsAndWallpaperLocked 1"); + debugLayoutRepeats("updateWindowsAndWallpaperLocked 1", + mPendingLayoutChanges); } } } - - // If the window has moved due to its containing - // content frame changing, then we'd like to animate - // it. The checks here are ordered by what is least - // likely to be true first. - if (w.shouldAnimateMove()) { - // Frame has moved, containing content frame - // has also moved, and we're not currently animating... - // let's do something. - Animation a = AnimationUtils.loadAnimation(mContext, - com.android.internal.R.anim.window_move_from_decor); - winAnimator.setAnimation(a); - winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; - winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; - } else { - winAnimator.mAnimDw = innerDw; - winAnimator.mAnimDh = innerDh; - } } } @@ -8455,7 +8287,7 @@ public class WindowManagerService extends IWindowManager.Stub // associated with exiting/removed apps mAnimator.animate(); mPendingLayoutChanges |= mAnimator.mPendingLayoutChanges; - if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animate()"); + if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animate()", mPendingLayoutChanges); if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); @@ -8550,9 +8382,8 @@ public class WindowManagerService extends IWindowManager.Stub // Make sure there is no animation running on this token, // so any windows associated with it will be removed as // soon as their animations are complete - token.clearAnimation(); - token.animation = null; - token.animating = false; + token.mAppAnimator.clearAnimation(); + token.mAppAnimator.animating = false; if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "performLayout: App token exiting now removed" + token); mAppTokens.remove(token); @@ -8629,6 +8460,7 @@ public class WindowManagerService extends IWindowManager.Stub !mInnerFields.mUpdateRotation) { checkDrawnWindowsLocked(); } + mInnerFields.mOrientationChangeComplete = true; // Check to see if we are now in a state where the screen should // be enabled, because the window obscured flags have changed. @@ -8745,6 +8577,7 @@ public class WindowManagerService extends IWindowManager.Stub wsa.mSurfaceShown = false; wsa.mSurface = null; ws.mHasSurface = false; + mAnimator.mWinAnimators.remove(wsa); mForceRemoves.add(ws); i--; N--; @@ -8758,6 +8591,7 @@ public class WindowManagerService extends IWindowManager.Stub wsa.mSurfaceShown = false; wsa.mSurface = null; ws.mHasSurface = false; + mAnimator.mWinAnimators.remove(wsa); leakedSurface = true; } } @@ -8797,6 +8631,7 @@ public class WindowManagerService extends IWindowManager.Stub winAnimator.mSurfaceShown = false; winAnimator.mSurface = null; winAnimator.mWin.mHasSurface = false; + mAnimator.mWinAnimators.remove(winAnimator); } try { @@ -8822,7 +8657,7 @@ public class WindowManagerService extends IWindowManager.Stub TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus); final WindowState oldFocus = mCurrentFocus; mCurrentFocus = newFocus; - mAnimator.setCurrentFocus(mCurrentFocus); + mAnimator.setCurrentFocus(newFocus); mLosingFocus.remove(newFocus); int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); @@ -8869,12 +8704,11 @@ public class WindowManagerService extends IWindowManager.Stub WindowState result = null; WindowState win; - int i = mWindows.size() - 1; int nextAppIndex = mAppTokens.size()-1; WindowToken nextApp = nextAppIndex >= 0 ? mAppTokens.get(nextAppIndex) : null; - while (i >= 0) { + for (int i = mWindows.size() - 1; i >= 0; i--) { win = mWindows.get(i); if (localLOGV || DEBUG_FOCUS) Slog.v( @@ -8887,7 +8721,6 @@ public class WindowManagerService extends IWindowManager.Stub // If this window's application has been removed, just skip it. if (thisApp != null && thisApp.removed) { - i--; continue; } @@ -8927,8 +8760,6 @@ public class WindowManagerService extends IWindowManager.Stub result = win; break; } - - i--; } return result; @@ -9192,11 +9023,6 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.lockNow(); } - void dumpInput(FileDescriptor fd, PrintWriter pw, boolean dumpAll) { - pw.println("WINDOW MANAGER INPUT (dumpsys window input)"); - mInputManager.dump(pw); - } - void dumpPolicyLocked(FileDescriptor fd, PrintWriter pw, String[] args, boolean dumpAll) { pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); mPolicy.dump(" ", fd, pw, args); @@ -9476,12 +9302,6 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(" mSystemBooted="); pw.print(mSystemBooted); pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); pw.print(" mLayoutNeeded="); pw.println(mLayoutNeeded); - if (mDimAnimator != null) { - pw.println(" mDimAnimator:"); - mDimAnimator.printTo(" ", pw); - } else { - pw.println( " no DimAnimator "); - } pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen); pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen); @@ -9592,7 +9412,6 @@ public class WindowManagerService extends IWindowManager.Stub pw.println("Window manager dump options:"); pw.println(" [-a] [-h] [cmd] ..."); pw.println(" cmd may be one of:"); - pw.println(" i[input]: input subsystem state"); pw.println(" p[policy]: policy state"); pw.println(" s[essions]: active sessions"); pw.println(" t[okens]: token list"); @@ -9613,10 +9432,7 @@ public class WindowManagerService extends IWindowManager.Stub if (opti < args.length) { String cmd = args[opti]; opti++; - if ("input".equals(cmd) || "i".equals(cmd)) { - dumpInput(fd, pw, true); - return; - } else if ("policy".equals(cmd) || "p".equals(cmd)) { + if ("policy".equals(cmd) || "p".equals(cmd)) { synchronized(mWindowMap) { dumpPolicyLocked(fd, pw, args, true); } @@ -9651,8 +9467,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - dumpInput(fd, pw, dumpAll); - synchronized(mWindowMap) { if (dumpAll) { pw.println("-------------------------------------------------------------------------------"); @@ -9691,10 +9505,10 @@ public class WindowManagerService extends IWindowManager.Stub requestTraversalLocked(); } - void debugLayoutRepeats(final String msg) { + void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { - Slog.v(TAG, "Layouts looping: " + msg); - Slog.v(TAG, "mPendingLayoutChanges = 0x" + Integer.toHexString(mPendingLayoutChanges)); + Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + + Integer.toHexString(pendingLayoutChanges)); } } diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java index b74aa61..4de6425 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/java/com/android/server/wm/WindowState.java @@ -23,6 +23,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; +import com.android.server.input.InputWindowHandle; + import android.content.Context; import android.content.res.Configuration; import android.graphics.Matrix; @@ -65,6 +67,9 @@ final class WindowState implements WindowManagerPolicy.WindowState { WindowToken mRootToken; AppWindowToken mAppToken; AppWindowToken mTargetAppToken; + + // mAttrs.flags is tested in animation without being locked. If the bits tested are ever + // modified they will need to be locked. final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams(); final DeathRecipient mDeathRecipient; final WindowState mAttachedWindow; @@ -621,7 +626,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { } final AppWindowToken atoken = mAppToken; final boolean animating = atoken != null - ? (atoken.animation != null) : false; + ? (atoken.mAppAnimator.animation != null) : false; return mHasSurface && !mDestroying && !mExiting && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested) && ((!mAttachedHidden && mViewVisibility == View.VISIBLE @@ -637,7 +642,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { public boolean isWinVisibleLw() { final AppWindowToken atoken = mAppToken; return mHasSurface && mPolicyVisibility && !mAttachedHidden - && (atoken == null || !atoken.hiddenRequested || atoken.animating) + && (atoken == null || !atoken.hiddenRequested || atoken.mAppAnimator.animating) && !mExiting && !mDestroying; } @@ -685,7 +690,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { final AppWindowToken atoken = mAppToken; if (atoken != null) { return ((!mAttachedHidden && !atoken.hiddenRequested) - || mWinAnimator.mAnimation != null || atoken.animation != null); + || mWinAnimator.mAnimation != null || atoken.mAppAnimator.animation != null); } return !mAttachedHidden || mWinAnimator.mAnimation != null; } @@ -703,7 +708,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { && ((!mAttachedHidden && mViewVisibility == View.VISIBLE && !mRootToken.hidden) || mWinAnimator.mAnimation != null - || ((mAppToken != null) && (mAppToken.animation != null))); + || ((mAppToken != null) && (mAppToken.mAppAnimator.animation != null))); } /** @@ -746,7 +751,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { return (mAttrs.format == PixelFormat.OPAQUE || mAttrs.type == TYPE_WALLPAPER) && isDrawnLw() && mWinAnimator.mAnimation == null - && (mAppToken == null || mAppToken.animation == null); + && (mAppToken == null || mAppToken.mAppAnimator.animation == null); } /** @@ -867,6 +872,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { return true; } + @Override public boolean hideLw(boolean doAnimation) { return hideLw(doAnimation, true); } @@ -909,6 +915,11 @@ final class WindowState implements WindowManagerPolicy.WindowState { return true; } + @Override + public boolean isAlive() { + return mClient.asBinder().isBinderAlive(); + } + private static void applyInsets(Region outRegion, Rect frame, Rect inset) { outRegion.set( frame.left + inset.left, frame.top + inset.top, @@ -962,8 +973,9 @@ final class WindowState implements WindowManagerPolicy.WindowState { pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer); pw.print(" mSubLayer="); pw.print(mSubLayer); pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+"); - pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment - : (mAppToken != null ? mAppToken.animLayerAdjustment : 0))); + pw.print((mTargetAppToken != null ? + mTargetAppToken.mAppAnimator.animLayerAdjustment + : (mAppToken != null ? mAppToken.mAppAnimator.animLayerAdjustment : 0))); pw.print("="); pw.print(mWinAnimator.mAnimLayer); pw.print(" mLastLayer="); pw.println(mWinAnimator.mLastLayer); } diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java index 4979a4c..220f5e0 100644 --- a/services/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/java/com/android/server/wm/WindowStateAnimator.java @@ -5,6 +5,8 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; +import static com.android.server.wm.WindowManagerService.LayoutFields.CLEAR_ORIENTATION_CHANGE_COMPLETE; + import android.content.Context; import android.graphics.Matrix; import android.graphics.PixelFormat; @@ -119,6 +121,9 @@ class WindowStateAnimator { /** Was this window last hidden? */ boolean mLastHidden; + int mAttrFlags; + int mAttrType; + public WindowStateAnimator(final WindowManagerService service, final WindowState win, final WindowState attachedWindow) { mService = service; @@ -128,11 +133,12 @@ class WindowStateAnimator { mSession = win.mSession; mPolicy = mService.mPolicy; mContext = mService.mContext; + mAttrFlags = win.mAttrs.flags; + mAttrType = win.mAttrs.type; } public void setAnimation(Animation anim) { - if (localLOGV) Slog.v( - TAG, "Setting animation in " + this + ": " + anim); + if (localLOGV) Slog.v(TAG, "Setting animation in " + this + ": " + anim); mAnimating = false; mLocalAnimating = false; mAnimation = anim; @@ -160,7 +166,7 @@ class WindowStateAnimator { return mAnimation != null || (attached != null && attached.mWinAnimator.mAnimation != null) || (atoken != null && - (atoken.animation != null + (atoken.mAppAnimator.animation != null || atoken.inPendingTransaction)); } @@ -226,7 +232,7 @@ class WindowStateAnimator { } mHasLocalTransformation = false; if ((!mLocalAnimating || mAnimationIsEntrance) && mWin.mAppToken != null - && mWin.mAppToken.animation != null) { + && mWin.mAppToken.mAppAnimator.animation != null) { // When our app token is animating, we kind-of pretend like // we are as well. Note the mLocalAnimating mAnimationIsEntrance // part of this check means that we will only do this if @@ -313,8 +319,9 @@ class WindowStateAnimator { } finishExit(); - mService.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; - if (WindowManagerService.DEBUG_LAYOUT_REPEATS) mService.debugLayoutRepeats("WindowState"); + mAnimator.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; + if (WindowManagerService.DEBUG_LAYOUT_REPEATS) mService.debugLayoutRepeats( + "WindowStateAnimator", mAnimator.mPendingLayoutChanges); if (mWin.mAppToken != null) { mWin.mAppToken.updateReportedVisibilityLocked(); @@ -450,6 +457,7 @@ class WindowStateAnimator { attrs.getTitle().toString(), 0, w, h, format, flags); mWin.mHasSurface = true; + mAnimator.mWinAnimators.add(this); if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG, " CREATE SURFACE " + mSurface + " IN SESSION " @@ -460,12 +468,14 @@ class WindowStateAnimator { + " / " + this); } catch (Surface.OutOfResourcesException e) { mWin.mHasSurface = false; + mAnimator.mWinAnimators.remove(this); Slog.w(TAG, "OutOfResourcesException creating surface"); mService.reclaimSomeSurfaceMemoryLocked(this, "create", true); mDrawState = NO_SURFACE; return null; } catch (Exception e) { mWin.mHasSurface = false; + mAnimator.mWinAnimators.remove(this); Slog.e(TAG, "Exception creating surface", e); mDrawState = NO_SURFACE; return null; @@ -583,6 +593,7 @@ class WindowStateAnimator { mSurfaceShown = false; mSurface = null; mWin.mHasSurface =false; + mAnimator.mWinAnimators.remove(this); } } @@ -613,9 +624,10 @@ class WindowStateAnimator { Transformation attachedTransformation = (mAttachedWindow != null && mAttachedWindow.mWinAnimator.mHasLocalTransformation) ? mAttachedWindow.mWinAnimator.mTransformation : null; - Transformation appTransformation = - (mWin.mAppToken != null && mWin.mAppToken.hasTransformation) - ? mWin.mAppToken.transformation : null; + final AppWindowAnimator appAnimator = + mWin.mAppToken == null ? null : mWin.mAppToken.mAppAnimator; + Transformation appTransformation = (appAnimator != null && appAnimator.hasTransformation) + ? appAnimator.transformation : null; // Wallpapers are animated based on the "real" window they // are currently targeting. @@ -629,11 +641,13 @@ class WindowStateAnimator { Slog.v(TAG, "WP target attached xform: " + attachedTransformation); } } - if (mService.mWallpaperTarget.mAppToken != null && - mService.mWallpaperTarget.mAppToken.hasTransformation && - mService.mWallpaperTarget.mAppToken.animation != null && - !mService.mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) { - appTransformation = mService.mWallpaperTarget.mAppToken.transformation; + final AppWindowAnimator wpAppAnimator = mService.mWallpaperTarget.mAppToken == null + ? null : mService.mWallpaperTarget.mAppToken.mAppAnimator; + if (wpAppAnimator != null && + wpAppAnimator.hasTransformation && + wpAppAnimator.animation != null && + !wpAppAnimator.animation.getDetachWallpaper()) { + appTransformation = wpAppAnimator.transformation; if (WindowManagerService.DEBUG_WALLPAPER && appTransformation != null) { Slog.v(TAG, "WP target app xform: " + appTransformation); } @@ -916,7 +930,7 @@ class WindowStateAnimator { if (displayed) { if (w.mOrientationChanging) { if (!w.isDrawnLw()) { - mService.mInnerFields.mOrientationChangeComplete = false; + mAnimator.mBulkUpdateParams |= CLEAR_ORIENTATION_CHANGE_COMPLETE; if (DEBUG_ORIENTATION) Slog.v(TAG, "Orientation continue waiting for draw in " + w); } else { @@ -981,7 +995,7 @@ class WindowStateAnimator { + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false) + " animating=" + mAnimating + " tok animating=" - + (mWin.mAppToken != null ? mWin.mAppToken.animating : false)); + + (mWin.mAppToken != null ? mWin.mAppToken.mAppAnimator.animating : false)); if (!showSurfaceRobustlyLocked()) { return false; } |
