@Override
 public boolean sendKeyEvent(KeyEvent event) {
   // BaseInputConnection.sendKeyEvent() dispatches the key event to the main thread.
   // In order to ensure events are processed in the proper order, we must block the
   // IC thread until the main thread finishes processing the key event
   super.sendKeyEvent(event);
   final View v = getView();
   if (v == null) {
     return false;
   }
   final Handler icHandler = mEditableClient.getInputConnectionHandler();
   final Handler mainHandler = v.getRootView().getHandler();
   if (icHandler.getLooper() != mainHandler.getLooper()) {
     // We are on separate IC thread but the event is queued on the main thread;
     // wait on IC thread until the main thread processes our posted Runnable. At
     // that point the key event has already been processed.
     mainHandler.post(
         new Runnable() {
           @Override
           public void run() {
             InputThreadUtils.sInstance.endWaitForUiThread();
           }
         });
     InputThreadUtils.sInstance.waitForUiThread(icHandler);
   }
   return false; // seems to always return false
 }
 public void runOnIcThread(
     final Handler uiHandler, final GoannaEditableClient client, final Runnable runnable) {
   final Handler icHandler = client.getInputConnectionHandler();
   if (icHandler.getLooper() == uiHandler.getLooper()) {
     // IC thread is UI thread; safe to run directly
     runnable.run();
     return;
   }
   runOnIcThread(icHandler, runnable);
 }
예제 #3
0
  /**
   * Sends this message using one three methods:
   *
   * <ul>
   *   <li>If the current thread is the same thread as the message Handler's thread, it is
   *       dispatched immediately to the Handler
   *   <li>If this TiMessenger is currently blocking, it is pushed into the internal message queue
   *       to be processed by the next call to {@link #dispatchMessage()}
   *   <li>If this TiMessenger is <b>NOT</b> current blocking, it is queued to it's Handler normally
   *       by using msg.sendToTarget()
   * </ul>
   *
   * @param message The message to send
   */
  public void sendMessage(Message message) {
    Handler target = message.getTarget();
    long currentThreadId = Thread.currentThread().getId();
    long targetThreadId = -1;

    if (target != null) {
      targetThreadId = target.getLooper().getThread().getId();
    }

    if (target != null && currentThreadId == targetThreadId) {
      target.dispatchMessage(message);

    } else {
      if (isBlocking()) {
        try {
          messageQueue.put(message);

        } catch (InterruptedException e) {
          Log.w(TAG, "Interrupted trying to put new message, sending to handler", e);
          message.sendToTarget();
        }

      } else {
        message.sendToTarget();
      }
    }
  }
예제 #4
0
  /**
   * Runs runnable on handler and waits for it to finish. If the current thread is the handler
   * thread, just runs it.
   */
  public static void runOnHandlerSynchronously(Handler h, final Runnable runnable) {
    final boolean done[] = new boolean[1];

    if (h.getLooper().getThread() == Thread.currentThread()) {
      runnable.run();
    } else {
      h.postAtFrontOfQueue(
          new Runnable() {

            @Override
            public void run() {
              runnable.run();

              synchronized (done) {
                done[0] = true;
                done.notify();
              }
            }
          });

      synchronized (done) {
        while (!done[0]) {
          try {
            done.wait();
          } catch (InterruptedException e) {
            throw new IllegalStateException(e);
          }
        }
      }
    }
  }
  @Test
  public void shouldRemoveTaggedCallback() throws Exception {
    ShadowLooper.pauseMainLooper();
    Handler handler = new Handler();

    final int[] count = new int[1];
    Runnable r =
        new Runnable() {
          @Override
          public void run() {
            count[0]++;
          }
        };

    String tag1 = "tag1", tag2 = "tag2";

    handler.postAtTime(r, tag1, 100);
    handler.postAtTime(r, tag2, 105);

    handler.removeCallbacks(r, tag2);
    ShadowLooper.unPauseMainLooper();

    assertThat(count[0]).as("run count").isEqualTo(1);
    // This assertion proves that it was the first runnable that ran,
    // which proves that the correctly tagged runnable was removed.
    assertThat(shadowOf(handler.getLooper()).getScheduler().getCurrentTime())
        .as("currentTime")
        .isEqualTo(100);
  }
예제 #6
0
  /**
   * Make a best-effort determination of the current position, given the time constraint. I want to
   * use a Looper, so call me from an AsyncTask background thread or something.
   *
   * @param ctx a Context providing access to a LocationManager
   * @param timeout milliseconds
   * @return The last known location (or null) after acquiring at least four satellites or using the
   *     alloted time searching for them.
   */
  public static Location get(final Context ctx, final long timeout) {
    Looper.prepare();
    final Handler handler = new Handler();
    LocationManager lm = WRService.getSystemService(ctx, Context.LOCATION_SERVICE);
    Criteria c = new Criteria();
    c.setAccuracy(Criteria.ACCURACY_FINE);
    String p = lm.getBestProvider(c, true);
    if (p == null) return null;

    final LocationGetter getter = new LocationGetter(handler.getLooper());
    try {
      lm.requestLocationUpdates(p, 0, 0, getter);
      handler.postDelayed(
          new Runnable() {
            public void run() {
              handler.getLooper().quit();
            }
          },
          timeout);
      Looper.loop();
    } finally {
      lm.removeUpdates(getter);
    }

    return lm.getLastKnownLocation(p);
  }
 /** close dialog */
 public void closeDialog() {
   if (Looper.myLooper() == mHandler.getLooper()) {
     close();
   } else {
     mHandler.post(mCloseAction);
   }
 }
 /** dismiss dialog */
 public void dismissDialog() {
   if (Looper.myLooper() == mHandler.getLooper()) {
     dismiss();
   } else {
     mHandler.post(mDismissAction);
   }
 }
예제 #9
0
  /** Stops Face Unlock and unbinds from the service. Called on the UI thread. */
  public boolean stop() {
    if (DEBUG) Log.d(TAG, "stop()");
    if (mHandler.getLooper() != Looper.myLooper()) {
      Log.e(TAG, "stop() called off of the UI thread");
    }

    boolean mWasRunning = mIsRunning;
    stopUi();

    if (mBoundToService) {
      if (mService != null) {
        try {
          mService.unregisterCallback(mFaceUnlockCallback);
        } catch (RemoteException e) {
          // Not much we can do
        }
      }
      Log.d(TAG, "Unbinding from Face Unlock service");
      mContext.unbindService(mConnection);
      mBoundToService = false;
    } else {
      // This is usually not an error when this happens.  Sometimes we will tell it to
      // unbind multiple times because it's called from both onWindowFocusChanged and
      // onDetachedFromWindow.
      if (DEBUG) Log.d(TAG, "Attempt to unbind from Face Unlock when not bound");
    }
    mIsRunning = false;
    return mWasRunning;
  }
예제 #10
0
  /**
   * Binds to the Face Unlock service. Face Unlock will be started when the bind completes. The Face
   * Unlock view is displayed to hide the backup lock while the service is starting up. Called on
   * the UI thread.
   */
  public boolean start() {
    if (DEBUG) Log.d(TAG, "start()");
    if (mHandler.getLooper() != Looper.myLooper()) {
      Log.e(TAG, "start() called off of the UI thread");
    }

    if (mIsRunning) {
      Log.w(TAG, "start() called when already running");
    }

    // Show Face Unlock view, but only for a little bit so lockpattern will become visible if
    // Face Unlock fails to start or crashes
    // This must show before bind to guarantee that Face Unlock has a place to display
    show(SERVICE_STARTUP_VIEW_TIMEOUT);
    if (!mBoundToService) {
      Log.d(TAG, "Binding to Face Unlock service");
      mContext.bindService(
          new Intent(IFaceLockInterface.class.getName()),
          mConnection,
          Context.BIND_AUTO_CREATE,
          mLockPatternUtils.getCurrentUser());
      mBoundToService = true;
    } else {
      Log.w(TAG, "Attempt to bind to Face Unlock when already bound");
    }

    mIsRunning = true;
    return true;
  }
 public void waitForUiThread(Handler icHandler) {
   if (DEBUG) {
     ThreadUtils.assertOnThread(icHandler.getLooper().getThread(), AssertBehavior.THROW);
     Log.d(
         LOGTAG,
         "waitForUiThread() blocking on thread " + icHandler.getLooper().getThread().getName());
   }
   try {
     Runnable runnable = null;
     do {
       runnable = mIcRunnableSync.take();
       runnable.run();
     } while (runnable != mIcSignalRunnable);
   } catch (InterruptedException e) {
   }
 }
 private void runOnIcThread(Handler icHandler, final Runnable runnable) {
   if (DEBUG) {
     ThreadUtils.assertOnUiThread();
     Log.d(LOGTAG, "runOnIcThread() on thread " + icHandler.getLooper().getThread().getName());
   }
   Runnable runner =
       new Runnable() {
         @Override
         public void run() {
           try {
             Runnable queuedRunnable = mIcRunnableSync.take();
             if (DEBUG && queuedRunnable != runnable) {
               throw new IllegalThreadStateException("sync error");
             }
             queuedRunnable.run();
           } catch (InterruptedException e) {
           }
         }
       };
   try {
     // if we are not inside waitForUiThread(), runner will call the runnable
     icHandler.post(runner);
     // runnable will be called by either runner from above or waitForUiThread()
     mIcRunnableSync.put(runnable);
   } catch (InterruptedException e) {
   } finally {
     // if waitForUiThread() already called runnable, runner should not call it again
     icHandler.removeCallbacks(runner);
   }
 }
예제 #13
0
 @VisibleForTesting
 public static void setUiThread(Looper looper) {
   synchronized (sLock) {
     if (sUiThreadHandler != null && sUiThreadHandler.getLooper() != looper) {
       throw new RuntimeException(
           "UI thread looper is already set to "
               + sUiThreadHandler.getLooper()
               + " (Main thread looper is "
               + Looper.getMainLooper()
               + "), cannot set to new looper "
               + looper);
     } else {
       sUiThreadHandler = new Handler(looper);
     }
   }
 }
 protected void checkThread() {
   if (!ALLOW_SIM_OP_IN_UI_THREAD) {
     // Make sure this isn't the UI thread, since it will block
     if (mBaseHandler.getLooper().equals(Looper.myLooper())) {
       loge("query() called on the main UI thread!");
       throw new IllegalStateException(
           "You cannot call query on this provder from the main UI thread.");
     }
   }
 }
예제 #15
0
    /**
     * Processes pending events on the Gecko thread before returning. Must be called on the input
     * connection thread during a test.
     */
    protected void processGeckoEvents(final InputConnection ic) {
      fAssertSame(
          "Should be called on input connection thread",
          Looper.myLooper(),
          inputConnectionHandler.getLooper());

      fAssertTrue(
          "Should be able to process Gecko events",
          ic.performPrivateCommand("process-gecko-events", null));
    }
예제 #16
0
 @Override
 public void postDelayed(Object event, long delayMillis) {
   if (event == null) {
     throw new NullPointerException("Event must not be null");
   }
   Handler handler = getMainHandlerNotNull();
   if (handler.getLooper().getThread().isAlive()) {
     mImpl.postDelayed(event, delayMillis, handler);
   } // otherwise the bus is already stopped
 }
  public DisplayManagerService(Context context, Handler mainHandler, Handler uiHandler) {
    mContext = context;
    mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");

    mHandler = new DisplayManagerHandler(mainHandler.getLooper());
    mUiHandler = uiHandler;
    mDisplayAdapterListener = new DisplayAdapterListener();
    mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);

    mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
  }
 /** Begin monitoring connectivity */
 public void startMonitoring(Context context, Handler target) {
   if (DBG) Log.d(TAG, "startMonitoring: target: " + target);
   mContext = context;
   mCsHandler = target;
   if (VDBG) Log.d(TAG, "startMonitoring: mCsHandler: " + mCsHandler);
   BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
   if (adapter != null) {
     adapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.PAN);
   }
   mBtdtHandler = new BtdtHandler(target.getLooper(), this);
 }
  public IntentFirewall(AMSInterface ams, Handler handler) {
    mAms = ams;
    mHandler = new FirewallHandler(handler.getLooper());
    File rulesDir = getRulesDir();
    rulesDir.mkdirs();

    readRulesDir(rulesDir);

    mObserver = new RuleObserver(rulesDir);
    mObserver.startWatching();
  }
  @Test
  public void testRemoveCallbacks() throws Exception {
    Handler handler = new Handler();
    ShadowLooper shadowLooper = shadowOf(handler.getLooper());
    shadowLooper.pause();
    handler.post(scratchRunnable);
    handler.removeCallbacks(scratchRunnable);

    shadowLooper.unPause();

    assertThat(scratchRunnable.wasRun).isFalse();
  }
예제 #21
0
  /**
   * Sets the Face Unlock view to visible, hiding it after the specified amount of time. If
   * timeoutMillis is 0, no hide is performed. Called on the UI thread.
   */
  public void show(long timeoutMillis) {
    if (DEBUG) Log.d(TAG, "show()");
    if (mHandler.getLooper() != Looper.myLooper()) {
      Log.e(TAG, "show() called off of the UI thread");
    }

    removeDisplayMessages();
    if (mFaceUnlockView != null) {
      mFaceUnlockView.setVisibility(View.VISIBLE);
    }
    if (timeoutMillis > 0) {
      mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACE_UNLOCK_VIEW, timeoutMillis);
    }
  }
  /**
   * Begin monitoring data connectivity.
   *
   * @param context is the current Android context
   * @param target is the Hander to which to return the events.
   */
  public void startMonitoring(Context context, Handler target) {
    mTarget = target;
    mContext = context;

    mHandler = new MdstHandler(target.getLooper(), this);

    IntentFilter filter = new IntentFilter();
    filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
    filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
    filter.addAction(DataConnectionTracker.ACTION_DATA_CONNECTION_TRACKER_MESSENGER);

    mContext.registerReceiver(new MobileDataStateReceiver(), filter);
    mMobileDataState = Phone.DataState.DISCONNECTED;
  }
예제 #23
0
 public void destroy() {
   if (mHandler != null) {
     mHandler.getLooper().quit();
   }
   // 避免因为同步机制导致等待过久做成UI线程假死,因此使用异步线程来清除数据
   Thread thread =
       new Thread(
           new Runnable() {
             @Override
             public void run() {
               cleanup();
             }
           });
   thread.start();
 }
예제 #24
0
  /**
   * Sets the listener the AudioRecord notifies when a previously set marker is reached or for each
   * periodic record head position update. Use this method to receive AudioRecord events in the
   * Handler associated with another thread than the one in which you created the AudioTrack
   * instance.
   *
   * @param listener
   * @param handler the Handler that will receive the event notification messages.
   */
  public void setRecordPositionUpdateListener(
      OnRecordPositionUpdateListener listener, Handler handler) {
    synchronized (mPositionListenerLock) {
      mPositionListener = listener;

      if (listener != null) {
        if (handler != null) {
          mEventHandler = new NativeEventHandler(this, handler.getLooper());
        } else {
          // no given handler, use the looper the AudioRecord was created in
          mEventHandler = new NativeEventHandler(this, mInitializationLooper);
        }
      } else {
        mEventHandler = null;
      }
    }
  }
  /**
   * Begin monitoring data connectivity.
   *
   * @param context is the current Android context
   * @param target is the Hander to which to return the events.
   */
  public void startMonitoring(Context context, Handler target) {
    mTarget = target;
    mContext = context;

    mHandler = new MdstHandler(target.getLooper(), this);

    IntentFilter filter = new IntentFilter();
    filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
    filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN);
    filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);

    mContext.registerReceiver(new MobileDataStateReceiver(), filter);
    mMobileDataState = PhoneConstants.DataState.DISCONNECTED;

    TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
    tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
  }
 public static ParcelFileDescriptor open(
     File file, int mode, Handler handler, OnCloseListener listener) throws IOException {
   if (handler == null) {
     throw new IllegalArgumentException("Handler must not be null");
   } else if (listener == null) {
     throw new IllegalArgumentException("Listener must not be null");
   } else {
     FileDescriptor fd = openInternal(file, mode);
     if (fd == null) {
       return null;
     }
     FileDescriptor[] comm = createCommSocketPair();
     ParcelFileDescriptor pfd = new ParcelFileDescriptor(fd, comm[0]);
     IoUtils.setBlocking(comm[MODE_WORLD_READABLE], true);
     new ListenerBridge(comm[MODE_WORLD_READABLE], handler.getLooper(), listener).start();
     return pfd;
   }
 }
예제 #27
0
    /**
     * Processes pending events on the input connection thread before returning. Must be called on
     * the input connection thread during a test.
     */
    protected void processInputConnectionEvents() {
      fAssertSame(
          "Should be called on input connection thread",
          Looper.myLooper(),
          inputConnectionHandler.getLooper());

      // Adapted from GeckoThread.pumpMessageLoop.
      MessageQueue queue = Looper.myQueue();
      queue.addIdleHandler(
          new MessageQueue.IdleHandler() {
            @Override
            public boolean queueIdle() {
              final Message msg = Message.obtain(inputConnectionHandler);
              msg.obj = inputConnectionHandler;
              inputConnectionHandler.sendMessageAtFrontOfQueue(msg);
              return false; // Remove this idle handler.
            }
          });

      final Method getNextMessage;
      try {
        getNextMessage = queue.getClass().getDeclaredMethod("next");
      } catch (final NoSuchMethodException e) {
        throw new UnsupportedOperationException(e);
      }
      getNextMessage.setAccessible(true);

      while (true) {
        final Message msg;
        try {
          msg = (Message) getNextMessage.invoke(queue);
        } catch (final IllegalAccessException | InvocationTargetException e) {
          throw new UnsupportedOperationException(e);
        }
        if (msg.obj == inputConnectionHandler && msg.getTarget() == inputConnectionHandler) {
          // Our idle signal
          break;
        } else if (msg.getTarget() == null) {
          Looper.myLooper().quit();
          break;
        }
        msg.getTarget().dispatchMessage(msg);
      }
    }
    ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) {
      mSensorEventListener = listener;
      Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
      // currently we create one Handler instance per listener, but we could
      // have one per looper (we'd need to pass the ListenerDelegate
      // instance to handleMessage and keep track of them separately).
      mHandler =
          new Handler(looper) {
            @Override
            public void handleMessage(Message msg) {
              final SensorEvent t = (SensorEvent) msg.obj;
              final int handle = t.sensor.getHandle();

              switch (t.sensor.getType()) {
                  // Only report accuracy for sensors that support it.
                case Sensor.TYPE_MAGNETIC_FIELD:
                case Sensor.TYPE_ORIENTATION:
                  // call onAccuracyChanged() only if the value changes
                  final int accuracy = mSensorAccuracies.get(handle);
                  if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
                    mSensorAccuracies.put(handle, t.accuracy);
                    mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy);
                  }
                  break;
                default:
                  // For other sensors, just report the accuracy once
                  if (mFirstEvent.get(handle) == false) {
                    mFirstEvent.put(handle, true);
                    mSensorEventListener.onAccuracyChanged(t.sensor, SENSOR_STATUS_ACCURACY_HIGH);
                  }
                  break;
              }

              mSensorEventListener.onSensorChanged(t);
              sPool.returnToPool(t);
            }
          };
      addSensor(sensor);
    }
예제 #29
0
 private void stop() {
   synchronized (this) {
     while (mHandler == null) {
       try {
         wait(1000);
         if (mHandler == null) {
           // We timed out; just give up. The process is probably
           // quitting anyways, so we let the OS do the clean up
           Log.w(LOGTAG, "timed out waiting for handler");
           return;
         }
       } catch (InterruptedException e) {
       }
     }
   }
   Looper looper = mHandler.getLooper();
   looper.quit();
   try {
     looper.getThread().join();
   } catch (InterruptedException e) {
   }
 }
예제 #30
0
      @Override
      public void onTerminate(final EGLContext eglContext) {
        // Make sure we do this on the correct thread.
        if (mHandler.getLooper() != Looper.myLooper()) {
          mHandler.post(
              new Runnable() {
                @Override
                public void run() {
                  onTerminate(eglContext);
                }
              });
          return;
        }

        synchronized (sEglLock) {
          if (sEgl == null) return;

          if (EGLImpl.getInitCount(sEglDisplay) == 1) {
            usePbufferSurface(eglContext);
            GLES20Canvas.terminateCaches();

            sEgl.eglDestroyContext(sEglDisplay, eglContext);
            sEglContextStorage.set(null);
            sEglContextStorage.remove();

            sEgl.eglDestroySurface(sEglDisplay, sPbuffer);
            sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);

            sEgl.eglReleaseThread();
            sEgl.eglTerminate(sEglDisplay);

            sEgl = null;
            sEglDisplay = null;
            sEglConfig = null;
            sPbuffer = null;
          }
        }
      }