Loading packages/SystemUI/src/com/android/systemui/util/Assert.java +9 −4 Original line number Diff line number Diff line Loading @@ -25,16 +25,21 @@ import androidx.annotation.VisibleForTesting; */ public class Assert { private static final Looper sMainLooper = Looper.getMainLooper(); private static Looper sTestLooper = null; private static Thread sTestThread = null; @VisibleForTesting public static void setTestableLooper(Looper testLooper) { sTestLooper = testLooper; setTestThread(testLooper == null ? null : testLooper.getThread()); } @VisibleForTesting public static void setTestThread(Thread thread) { sTestThread = thread; } public static void isMainThread() { if (!sMainLooper.isCurrentThread() && (sTestLooper == null || !sTestLooper.isCurrentThread())) { && (sTestThread == null || sTestThread != Thread.currentThread())) { throw new IllegalStateException("should be called from the main thread." + " sMainLooper.threadName=" + sMainLooper.getThread().getName() + " Thread.currentThread()=" + Thread.currentThread().getName()); Loading @@ -43,7 +48,7 @@ public class Assert { public static void isNotMainThread() { if (sMainLooper.isCurrentThread() && (sTestLooper == null || sTestLooper.isCurrentThread())) { && (sTestThread == null || sTestThread == Thread.currentThread())) { throw new IllegalStateException("should not be called from the main thread."); } } Loading packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java +7 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import java.util.concurrent.Executors; import javax.inject.Singleton; import dagger.Binds; import dagger.Module; import dagger.Provides; Loading Loading @@ -199,4 +200,10 @@ public abstract class ConcurrencyModule { public static Executor provideUiBackgroundExecutor() { return Executors.newSingleThreadExecutor(); } /** * Binds {@link ThreadFactoryImpl} to {@link ThreadFactory}. */ @Binds public abstract ThreadFactory bindExecutorFactory(ThreadFactoryImpl impl); } packages/SystemUI/src/com/android/systemui/util/concurrency/ThreadFactory.java 0 → 100644 +44 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.util.concurrency; import java.util.concurrent.Executor; /** * Factory for building Executors running on a unique named thread. * * Use this when our generally available @Main, @Background, @UiBackground, @LongRunning, or * similar global qualifiers don't quite cut it. Note that the methods here create entirely new * threads; there are no singletons here. Use responsibly. */ public interface ThreadFactory { /** * Return an {@link java.util.concurrent.Executor} running on a named thread. * * The thread is implicitly started and may be left running indefinitely, depending on the * implementation. Assume this is the case and use responsibly. **/ Executor buildExecutorOnNewThread(String threadName); /** * Return an {@link DelayableExecutor} running on a named thread. * * The thread is implicitly started and may be left running indefinitely, depending on the * implementation. Assume this is the case and use responsibly. **/ DelayableExecutor buildDelayableExecutorOnNewThread(String threadName); } packages/SystemUI/src/com/android/systemui/util/concurrency/ThreadFactoryImpl.java 0 → 100644 +38 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.util.concurrency; import android.os.HandlerThread; import java.util.concurrent.Executor; import javax.inject.Inject; class ThreadFactoryImpl implements ThreadFactory { @Inject ThreadFactoryImpl() {} public Executor buildExecutorOnNewThread(String threadName) { return buildDelayableExecutorOnNewThread(threadName); } public DelayableExecutor buildDelayableExecutorOnNewThread(String threadName) { HandlerThread handlerThread = new HandlerThread(threadName); handlerThread.start(); return new ExecutorImpl(handlerThread.getLooper()); } } packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java +15 −26 Original line number Diff line number Diff line Loading @@ -25,18 +25,18 @@ import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.TriggerEventListener; import android.os.Handler; import android.os.HandlerThread; import android.os.MemoryFile; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import com.android.systemui.plugins.PluginListener; import com.android.systemui.plugins.SensorManagerPlugin; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.util.concurrency.ThreadFactory; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; import javax.inject.Inject; import javax.inject.Singleton; Loading @@ -56,25 +56,14 @@ public class AsyncSensorManager extends SensorManager private final SensorManager mInner; private final List<Sensor> mSensorCache; private final Handler mHandler; private final Executor mExecutor; private final List<SensorManagerPlugin> mPlugins; @Inject public AsyncSensorManager(SensorManager sensorManager, PluginManager pluginManager) { this(sensorManager, pluginManager, null); } @VisibleForTesting public AsyncSensorManager( SensorManager sensorManager, PluginManager pluginManager, Handler handler) { public AsyncSensorManager(SensorManager sensorManager, ThreadFactory threadFactory, PluginManager pluginManager) { mInner = sensorManager; if (handler == null) { HandlerThread handlerThread = new HandlerThread("async_sensor"); handlerThread.start(); mHandler = new Handler(handlerThread.getLooper()); } else { mHandler = handler; } mExecutor = threadFactory.buildExecutorOnNewThread("async_sensor"); mSensorCache = mInner.getSensorList(Sensor.TYPE_ALL); mPlugins = new ArrayList<>(); if (pluginManager != null) { Loading @@ -97,7 +86,7 @@ public class AsyncSensorManager extends SensorManager protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags) { mHandler.post(() -> { mExecutor.execute(() -> { if (!mInner.registerListener(listener, sensor, delayUs, maxReportLatencyUs, handler)) { Log.e(TAG, "Registering " + listener + " for " + sensor + " failed."); } Loading Loading @@ -129,12 +118,12 @@ public class AsyncSensorManager extends SensorManager @Override protected void registerDynamicSensorCallbackImpl(DynamicSensorCallback callback, Handler handler) { mHandler.post(() -> mInner.registerDynamicSensorCallback(callback, handler)); mExecutor.execute(() -> mInner.registerDynamicSensorCallback(callback, handler)); } @Override protected void unregisterDynamicSensorCallbackImpl(DynamicSensorCallback callback) { mHandler.post(() -> mInner.unregisterDynamicSensorCallback(callback)); mExecutor.execute(() -> mInner.unregisterDynamicSensorCallback(callback)); } @Override Loading @@ -145,7 +134,7 @@ public class AsyncSensorManager extends SensorManager if (sensor == null) { throw new IllegalArgumentException("sensor cannot be null"); } mHandler.post(() -> { mExecutor.execute(() -> { if (!mInner.requestTriggerSensor(listener, sensor)) { Log.e(TAG, "Requesting " + listener + " for " + sensor + " failed."); } Loading @@ -158,7 +147,7 @@ public class AsyncSensorManager extends SensorManager boolean disable) { Preconditions.checkArgument(disable); mHandler.post(() -> { mExecutor.execute(() -> { if (!mInner.cancelTriggerSensor(listener, sensor)) { Log.e(TAG, "Canceling " + listener + " for " + sensor + " failed."); } Loading @@ -178,7 +167,7 @@ public class AsyncSensorManager extends SensorManager Log.w(TAG, "No plugins registered"); return false; } mHandler.post(() -> { mExecutor.execute(() -> { for (int i = 0; i < mPlugins.size(); i++) { mPlugins.get(i).registerListener(sensor, listener); } Loading @@ -194,7 +183,7 @@ public class AsyncSensorManager extends SensorManager */ public void unregisterPluginListener(SensorManagerPlugin.Sensor sensor, SensorManagerPlugin.SensorEventListener listener) { mHandler.post(() -> { mExecutor.execute(() -> { for (int i = 0; i < mPlugins.size(); i++) { mPlugins.get(i).unregisterListener(sensor, listener); } Loading @@ -214,14 +203,14 @@ public class AsyncSensorManager extends SensorManager @Override protected boolean setOperationParameterImpl(SensorAdditionalInfo parameter) { mHandler.post(() -> mInner.setOperationParameter(parameter)); mExecutor.execute(() -> mInner.setOperationParameter(parameter)); return true; } @Override protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) { mHandler.post(() -> { mExecutor.execute(() -> { if (sensor == null) { mInner.unregisterListener(listener); } else { Loading Loading
packages/SystemUI/src/com/android/systemui/util/Assert.java +9 −4 Original line number Diff line number Diff line Loading @@ -25,16 +25,21 @@ import androidx.annotation.VisibleForTesting; */ public class Assert { private static final Looper sMainLooper = Looper.getMainLooper(); private static Looper sTestLooper = null; private static Thread sTestThread = null; @VisibleForTesting public static void setTestableLooper(Looper testLooper) { sTestLooper = testLooper; setTestThread(testLooper == null ? null : testLooper.getThread()); } @VisibleForTesting public static void setTestThread(Thread thread) { sTestThread = thread; } public static void isMainThread() { if (!sMainLooper.isCurrentThread() && (sTestLooper == null || !sTestLooper.isCurrentThread())) { && (sTestThread == null || sTestThread != Thread.currentThread())) { throw new IllegalStateException("should be called from the main thread." + " sMainLooper.threadName=" + sMainLooper.getThread().getName() + " Thread.currentThread()=" + Thread.currentThread().getName()); Loading @@ -43,7 +48,7 @@ public class Assert { public static void isNotMainThread() { if (sMainLooper.isCurrentThread() && (sTestLooper == null || sTestLooper.isCurrentThread())) { && (sTestThread == null || sTestThread == Thread.currentThread())) { throw new IllegalStateException("should not be called from the main thread."); } } Loading
packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java +7 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import java.util.concurrent.Executors; import javax.inject.Singleton; import dagger.Binds; import dagger.Module; import dagger.Provides; Loading Loading @@ -199,4 +200,10 @@ public abstract class ConcurrencyModule { public static Executor provideUiBackgroundExecutor() { return Executors.newSingleThreadExecutor(); } /** * Binds {@link ThreadFactoryImpl} to {@link ThreadFactory}. */ @Binds public abstract ThreadFactory bindExecutorFactory(ThreadFactoryImpl impl); }
packages/SystemUI/src/com/android/systemui/util/concurrency/ThreadFactory.java 0 → 100644 +44 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.util.concurrency; import java.util.concurrent.Executor; /** * Factory for building Executors running on a unique named thread. * * Use this when our generally available @Main, @Background, @UiBackground, @LongRunning, or * similar global qualifiers don't quite cut it. Note that the methods here create entirely new * threads; there are no singletons here. Use responsibly. */ public interface ThreadFactory { /** * Return an {@link java.util.concurrent.Executor} running on a named thread. * * The thread is implicitly started and may be left running indefinitely, depending on the * implementation. Assume this is the case and use responsibly. **/ Executor buildExecutorOnNewThread(String threadName); /** * Return an {@link DelayableExecutor} running on a named thread. * * The thread is implicitly started and may be left running indefinitely, depending on the * implementation. Assume this is the case and use responsibly. **/ DelayableExecutor buildDelayableExecutorOnNewThread(String threadName); }
packages/SystemUI/src/com/android/systemui/util/concurrency/ThreadFactoryImpl.java 0 → 100644 +38 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.util.concurrency; import android.os.HandlerThread; import java.util.concurrent.Executor; import javax.inject.Inject; class ThreadFactoryImpl implements ThreadFactory { @Inject ThreadFactoryImpl() {} public Executor buildExecutorOnNewThread(String threadName) { return buildDelayableExecutorOnNewThread(threadName); } public DelayableExecutor buildDelayableExecutorOnNewThread(String threadName) { HandlerThread handlerThread = new HandlerThread(threadName); handlerThread.start(); return new ExecutorImpl(handlerThread.getLooper()); } }
packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java +15 −26 Original line number Diff line number Diff line Loading @@ -25,18 +25,18 @@ import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.TriggerEventListener; import android.os.Handler; import android.os.HandlerThread; import android.os.MemoryFile; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import com.android.systemui.plugins.PluginListener; import com.android.systemui.plugins.SensorManagerPlugin; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.util.concurrency.ThreadFactory; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; import javax.inject.Inject; import javax.inject.Singleton; Loading @@ -56,25 +56,14 @@ public class AsyncSensorManager extends SensorManager private final SensorManager mInner; private final List<Sensor> mSensorCache; private final Handler mHandler; private final Executor mExecutor; private final List<SensorManagerPlugin> mPlugins; @Inject public AsyncSensorManager(SensorManager sensorManager, PluginManager pluginManager) { this(sensorManager, pluginManager, null); } @VisibleForTesting public AsyncSensorManager( SensorManager sensorManager, PluginManager pluginManager, Handler handler) { public AsyncSensorManager(SensorManager sensorManager, ThreadFactory threadFactory, PluginManager pluginManager) { mInner = sensorManager; if (handler == null) { HandlerThread handlerThread = new HandlerThread("async_sensor"); handlerThread.start(); mHandler = new Handler(handlerThread.getLooper()); } else { mHandler = handler; } mExecutor = threadFactory.buildExecutorOnNewThread("async_sensor"); mSensorCache = mInner.getSensorList(Sensor.TYPE_ALL); mPlugins = new ArrayList<>(); if (pluginManager != null) { Loading @@ -97,7 +86,7 @@ public class AsyncSensorManager extends SensorManager protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags) { mHandler.post(() -> { mExecutor.execute(() -> { if (!mInner.registerListener(listener, sensor, delayUs, maxReportLatencyUs, handler)) { Log.e(TAG, "Registering " + listener + " for " + sensor + " failed."); } Loading Loading @@ -129,12 +118,12 @@ public class AsyncSensorManager extends SensorManager @Override protected void registerDynamicSensorCallbackImpl(DynamicSensorCallback callback, Handler handler) { mHandler.post(() -> mInner.registerDynamicSensorCallback(callback, handler)); mExecutor.execute(() -> mInner.registerDynamicSensorCallback(callback, handler)); } @Override protected void unregisterDynamicSensorCallbackImpl(DynamicSensorCallback callback) { mHandler.post(() -> mInner.unregisterDynamicSensorCallback(callback)); mExecutor.execute(() -> mInner.unregisterDynamicSensorCallback(callback)); } @Override Loading @@ -145,7 +134,7 @@ public class AsyncSensorManager extends SensorManager if (sensor == null) { throw new IllegalArgumentException("sensor cannot be null"); } mHandler.post(() -> { mExecutor.execute(() -> { if (!mInner.requestTriggerSensor(listener, sensor)) { Log.e(TAG, "Requesting " + listener + " for " + sensor + " failed."); } Loading @@ -158,7 +147,7 @@ public class AsyncSensorManager extends SensorManager boolean disable) { Preconditions.checkArgument(disable); mHandler.post(() -> { mExecutor.execute(() -> { if (!mInner.cancelTriggerSensor(listener, sensor)) { Log.e(TAG, "Canceling " + listener + " for " + sensor + " failed."); } Loading @@ -178,7 +167,7 @@ public class AsyncSensorManager extends SensorManager Log.w(TAG, "No plugins registered"); return false; } mHandler.post(() -> { mExecutor.execute(() -> { for (int i = 0; i < mPlugins.size(); i++) { mPlugins.get(i).registerListener(sensor, listener); } Loading @@ -194,7 +183,7 @@ public class AsyncSensorManager extends SensorManager */ public void unregisterPluginListener(SensorManagerPlugin.Sensor sensor, SensorManagerPlugin.SensorEventListener listener) { mHandler.post(() -> { mExecutor.execute(() -> { for (int i = 0; i < mPlugins.size(); i++) { mPlugins.get(i).unregisterListener(sensor, listener); } Loading @@ -214,14 +203,14 @@ public class AsyncSensorManager extends SensorManager @Override protected boolean setOperationParameterImpl(SensorAdditionalInfo parameter) { mHandler.post(() -> mInner.setOperationParameter(parameter)); mExecutor.execute(() -> mInner.setOperationParameter(parameter)); return true; } @Override protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) { mHandler.post(() -> { mExecutor.execute(() -> { if (sensor == null) { mInner.unregisterListener(listener); } else { Loading