Home | History | Annotate | Download | only in telecom
      1 /*
      2  * Copyright 2014, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.telecom;
     18 
     19 import android.content.Context;
     20 import android.content.Intent;
     21 import android.media.AudioAttributes;
     22 import android.media.session.MediaSession;
     23 import android.os.Handler;
     24 import android.os.Looper;
     25 import android.os.Message;
     26 import android.view.KeyEvent;
     27 
     28 /**
     29  * Static class to handle listening to the headset media buttons.
     30  */
     31 public class HeadsetMediaButton extends CallsManagerListenerBase {
     32 
     33     // Types of media button presses
     34     static final int SHORT_PRESS = 1;
     35     static final int LONG_PRESS = 2;
     36 
     37     private static final AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
     38             .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
     39             .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION).build();
     40 
     41     private static final int MSG_MEDIA_SESSION_INITIALIZE = 0;
     42     private static final int MSG_MEDIA_SESSION_SET_ACTIVE = 1;
     43 
     44     private final MediaSession.Callback mSessionCallback = new MediaSession.Callback() {
     45         @Override
     46         public boolean onMediaButtonEvent(Intent intent) {
     47             KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
     48             Log.v(this, "SessionCallback.onMediaButton()...  event = %s.", event);
     49             if ((event != null) && (event.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK)) {
     50                 synchronized (mLock) {
     51                     Log.v(this, "SessionCallback: HEADSETHOOK");
     52                     boolean consumed = handleHeadsetHook(event);
     53                     Log.v(this, "==> handleHeadsetHook(): consumed = %b.", consumed);
     54                     return consumed;
     55                 }
     56             }
     57             return true;
     58         }
     59     };
     60 
     61     private final Handler mMediaSessionHandler = new Handler(Looper.getMainLooper()) {
     62         @Override
     63         public void handleMessage(Message msg) {
     64             switch (msg.what) {
     65                 case MSG_MEDIA_SESSION_INITIALIZE: {
     66                     MediaSession session = new MediaSession(
     67                             mContext,
     68                             HeadsetMediaButton.class.getSimpleName());
     69                     session.setCallback(mSessionCallback);
     70                     session.setFlags(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY
     71                             | MediaSession.FLAG_HANDLES_MEDIA_BUTTONS);
     72                     session.setPlaybackToLocal(AUDIO_ATTRIBUTES);
     73                     mSession = session;
     74                     break;
     75                 }
     76                 case MSG_MEDIA_SESSION_SET_ACTIVE: {
     77                     if (mSession != null) {
     78                         boolean activate = msg.arg1 != 0;
     79                         if (activate != mSession.isActive()) {
     80                             mSession.setActive(activate);
     81                         }
     82                     }
     83                     break;
     84                 }
     85                 default:
     86                     break;
     87             }
     88         }
     89     };
     90 
     91     private final Context mContext;
     92     private final CallsManager mCallsManager;
     93     private final TelecomSystem.SyncRoot mLock;
     94     private MediaSession mSession;
     95 
     96     public HeadsetMediaButton(
     97             Context context,
     98             CallsManager callsManager,
     99             TelecomSystem.SyncRoot lock) {
    100         mContext = context;
    101         mCallsManager = callsManager;
    102         mLock = lock;
    103 
    104         // Create a MediaSession but don't enable it yet. This is a
    105         // replacement for MediaButtonReceiver
    106         mMediaSessionHandler.obtainMessage(MSG_MEDIA_SESSION_INITIALIZE).sendToTarget();
    107     }
    108 
    109     /**
    110      * Handles the wired headset button while in-call.
    111      *
    112      * @return true if we consumed the event.
    113      */
    114     private boolean handleHeadsetHook(KeyEvent event) {
    115         Log.d(this, "handleHeadsetHook()...%s %s", event.getAction(), event.getRepeatCount());
    116 
    117         if (event.isLongPress()) {
    118             return mCallsManager.onMediaButton(LONG_PRESS);
    119         } else if (event.getAction() == KeyEvent.ACTION_UP && event.getRepeatCount() == 0) {
    120             return mCallsManager.onMediaButton(SHORT_PRESS);
    121         }
    122 
    123         return true;
    124     }
    125 
    126     /** ${inheritDoc} */
    127     @Override
    128     public void onCallAdded(Call call) {
    129         mMediaSessionHandler.obtainMessage(MSG_MEDIA_SESSION_SET_ACTIVE, 1, 0).sendToTarget();
    130     }
    131 
    132     /** ${inheritDoc} */
    133     @Override
    134     public void onCallRemoved(Call call) {
    135         if (!mCallsManager.hasAnyCalls()) {
    136             mMediaSessionHandler.obtainMessage(MSG_MEDIA_SESSION_SET_ACTIVE, 0, 0).sendToTarget();
    137         }
    138     }
    139 }
    140