1 /* 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 package org.appspot.apprtc.util; 12 13 import android.os.Handler; 14 import android.os.Looper; 15 import android.util.Log; 16 17 import java.util.concurrent.Executor; 18 19 /** 20 * Looper based executor class. 21 */ 22 public class LooperExecutor extends Thread implements Executor { 23 private static final String TAG = "LooperExecutor"; 24 // Object used to signal that looper thread has started and Handler instance 25 // associated with looper thread has been allocated. 26 private final Object looperStartedEvent = new Object(); 27 private Handler handler = null; 28 private boolean running = false; 29 private long threadId; 30 31 @Override run()32 public void run() { 33 Looper.prepare(); 34 synchronized (looperStartedEvent) { 35 Log.d(TAG, "Looper thread started."); 36 handler = new Handler(); 37 threadId = Thread.currentThread().getId(); 38 looperStartedEvent.notify(); 39 } 40 Looper.loop(); 41 } 42 requestStart()43 public synchronized void requestStart() { 44 if (running) { 45 return; 46 } 47 running = true; 48 handler = null; 49 start(); 50 // Wait for Hander allocation. 51 synchronized (looperStartedEvent) { 52 while (handler == null) { 53 try { 54 looperStartedEvent.wait(); 55 } catch (InterruptedException e) { 56 Log.e(TAG, "Can not start looper thread"); 57 running = false; 58 } 59 } 60 } 61 } 62 requestStop()63 public synchronized void requestStop() { 64 if (!running) { 65 return; 66 } 67 running = false; 68 handler.post(new Runnable() { 69 @Override 70 public void run() { 71 Looper.myLooper().quit(); 72 Log.d(TAG, "Looper thread finished."); 73 } 74 }); 75 } 76 77 // Checks if current thread is a looper thread. checkOnLooperThread()78 public boolean checkOnLooperThread() { 79 return (Thread.currentThread().getId() == threadId); 80 } 81 82 @Override execute(final Runnable runnable)83 public synchronized void execute(final Runnable runnable) { 84 if (!running) { 85 Log.w(TAG, "Running looper executor without calling requestStart()"); 86 return; 87 } 88 if (Thread.currentThread().getId() == threadId) { 89 runnable.run(); 90 } else { 91 handler.post(runnable); 92 } 93 } 94 95 } 96