Skip to content
Snippets Groups Projects
Commit b8add812 authored by Alexandre Lision's avatar Alexandre Lision
Browse files

* #32381: added proper screenlock (based on CSipSimple mechanism)

parent 2d740411
No related branches found
No related tags found
No related merge requests found
......@@ -51,6 +51,8 @@ as that of the covered work.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<application
android:name="org.sflphone.client.SFLphoneApplication"
......
......@@ -46,6 +46,8 @@ import org.sflphone.receivers.CallReceiver;
import org.sflphone.service.CallManagerCallBack;
import org.sflphone.service.ISipService;
import org.sflphone.service.SipService;
import org.sflphone.utils.CallProximityManager;
import org.sflphone.utils.CallProximityManager.ProximityDirector;
import org.sflphone.views.CallPaneLayout;
import android.app.Activity;
......@@ -68,7 +70,7 @@ import android.view.View;
import android.view.Window;
import android.widget.Toast;
public class CallActivity extends Activity implements CallInterface, CallFragment.Callbacks{
public class CallActivity extends Activity implements CallInterface, CallFragment.Callbacks, ProximityDirector{
static final String TAG = "CallActivity";
private ISipService service;
......@@ -82,6 +84,8 @@ public class CallActivity extends Activity implements CallInterface, CallFragmen
/* result code sent in case of call failure */
public static int RESULT_FAILURE = -10;
private CallProximityManager proximityManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
......@@ -90,9 +94,7 @@ public class CallActivity extends Activity implements CallInterface, CallFragmen
receiver = new CallReceiver(this);
// mCallsFragment = new CallListFragment();
// getFragmentManager().beginTransaction().replace(R.id.calllist_pane, mCallsFragment).commit();
proximityManager = new CallProximityManager(this, this);
slidingPaneLayout = (CallPaneLayout) findViewById(R.id.slidingpanelayout);
......@@ -121,6 +123,7 @@ public class CallActivity extends Activity implements CallInterface, CallFragmen
}
});
proximityManager.startTracking();
Intent intent = new Intent(this, SipService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
......@@ -182,6 +185,8 @@ public class CallActivity extends Activity implements CallInterface, CallFragmen
protected void onDestroy() {
unregisterReceiver(receiver);
unbindService(mConnection);
proximityManager.stopTracking();
proximityManager.release(0);
super.onDestroy();
}
......@@ -268,9 +273,10 @@ public class CallActivity extends Activity implements CallInterface, CallFragmen
if (mCurrentCallFragment != null) {
mCurrentCallFragment.changeCallState(callID, newState);
}
proximityManager.updateProximitySensorMode();
try {
HashMap<String, SipCall> callMap = (HashMap<String, SipCall>) service.getCallList();
HashMap<String, Conference> confMap = (HashMap<String, Conference>) service.getConferenceList();
......@@ -399,4 +405,15 @@ public class CallActivity extends Activity implements CallInterface, CallFragmen
public void slideChatScreen() {
slidingPaneLayout.openPane();
}
@Override
public boolean shouldActivateProximity() {
return true;
}
@Override
public void onProximityTrackingChanged(boolean acquired) {
// TODO Stub de la méthode généré automatiquement
}
}
......@@ -31,6 +31,8 @@
package org.sflphone.fragments;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Locale;
......@@ -45,6 +47,7 @@ import org.sflphone.model.CallContact;
import org.sflphone.model.Conference;
import org.sflphone.model.SipCall;
import org.sflphone.service.ISipService;
import org.sflphone.utils.CallProximityManager;
import android.app.Activity;
import android.app.Fragment;
......@@ -59,6 +62,7 @@ import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.RemoteException;
import android.util.Log;
import android.view.KeyEvent;
......@@ -71,12 +75,11 @@ import android.view.SurfaceHolder.Callback;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.ImageButton;
import android.widget.TextView;
public class CallFragment extends Fragment implements Callback, SensorEventListener {
public class CallFragment extends Fragment implements Callback{
static final String TAG = "CallFragment";
......@@ -88,6 +91,8 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
private Conference conf;
private TextView callStatusTxt;
private TextView codecNameTxt;
private BubblesView view;
private BubbleModel model;
......@@ -98,10 +103,19 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
private SensorManager mSensorManager;
private Sensor mSensor;
TransferDFragment editName;
private TextView codecNameTxt;
private PowerManager.WakeLock fullLock;
private PowerManager.WakeLock partialLock;
private PowerManager.WakeLock proximityLock;
private static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32;
private static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1;
private Method wakelockParameterizedRelease;
@Override
public void onCreate(Bundle savedBundle) {
......@@ -115,6 +129,22 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
this.setHasOptionsMenu(true);
// PowerManager pm = (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE);
// fullLock = pm.newWakeLock(PowerManager.ON_AFTER_RELEASE | PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG);
// partialLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
// proximityLock = pm.newWakeLock(PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
//
// Method maybeRelease = null;
// try {
// maybeRelease = proximityLock.getClass().getDeclaredMethod("release", Integer.TYPE);
// } catch (NoSuchMethodException e) {
// Log.d("LockManager", "Parameterized WakeLock release not available on this device.");
// }
// wakelockParameterizedRelease = maybeRelease;
}
/**
......@@ -122,7 +152,6 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
*/
private static Callbacks sDummyCallbacks = new Callbacks() {
@Override
public ISipService getService() {
return null;
......@@ -137,7 +166,7 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
}
@Override
public void slideChatScreen() {
public void slideChatScreen() {
}
};
......@@ -152,7 +181,7 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
public void startTimer();
public void slideChatScreen();
public void replaceCurrentCallDisplayed();
}
......@@ -167,10 +196,10 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
// rootView.requestDisallowInterceptTouchEvent(true);
mCallbacks = (Callbacks) activity;
// myself = SipCall.SipCallBuilder.buildMyselfCall(activity.getContentResolver(), "Me");
// myself = SipCall.SipCallBuilder.buildMyselfCall(activity.getContentResolver(), "Me");
}
@Override
public void onCreateOptionsMenu(Menu m, MenuInflater inf) {
super.onCreateOptionsMenu(m, inf);
......@@ -180,11 +209,11 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
// switch (item.getItemId()) {
// case R.id.menuitem_chat:
// mCallbacks.slideChatScreen();
// break;
// }
// switch (item.getItemId()) {
// case R.id.menuitem_chat:
// mCallbacks.slideChatScreen();
// break;
// }
return true;
}
......@@ -193,7 +222,7 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
public void onDetach() {
super.onDetach();
mCallbacks = sDummyCallbacks;
mSensorManager.unregisterListener(this);
// mSensorManager.unregisterListener(this);
}
@Override
......@@ -204,13 +233,13 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
@Override
public void onResume() {
super.onResume();
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
// mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
public void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
// mSensorManager.unregisterListener(this);
}
@Override
......@@ -361,7 +390,7 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
private Bubble getBubbleFor(SipCall call, float x, float y) {
Bubble contact_bubble = model.getBubble(call.getCallId());
if (contact_bubble != null) {
((BubbleContact)contact_bubble).setCall(call);
((BubbleContact) contact_bubble).setCall(call);
contact_bubble.attractor.set(x, y);
return contact_bubble;
}
......@@ -371,16 +400,17 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
model.addBubble(contact_bubble);
return contact_bubble;
}
private Bubble getBubbleForUser(Conference conf, float x, float y) {
Bubble contact_bubble = model.getBubble(conf.getId());
if (contact_bubble != null) {
contact_bubble.attractor.set(x, y);
((BubbleUser)contact_bubble).setConference(conf);
((BubbleUser) contact_bubble).setConference(conf);
return contact_bubble;
}
contact_bubble = new BubbleUser(getActivity(), CallContact.ContactBuilder.buildUserContact(getActivity().getContentResolver(), getResources().getString(R.string.me)), conf, x, y, BUBBLE_SIZE);
contact_bubble = new BubbleUser(getActivity(), CallContact.ContactBuilder.buildUserContact(getActivity().getContentResolver(), getResources()
.getString(R.string.me)), conf, x, y, BUBBLE_SIZE);
model.addBubble(contact_bubble);
return contact_bubble;
......@@ -390,9 +420,9 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
* Should be called when a bubble is removed from the model
*/
void bubbleRemoved(Bubble b) {
// if (b.associated_call == null) {
// return;
// }
// if (b.associated_call == null) {
// return;
// }
}
public void changeCallState(String callID, String newState) {
......@@ -468,7 +498,7 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
editName = TransferDFragment.newInstance();
Bundle b = new Bundle();
try {
b.putParcelableArrayList("calls", (ArrayList<Conference>)mCallbacks.getService().getConcurrentCalls());
b.putParcelableArrayList("calls", (ArrayList<Conference>) mCallbacks.getService().getConcurrentCalls());
b.putParcelable("call_selected", contact.associated_call);
editName.setArguments(b);
editName.setTargetFragment(this, REQUEST_TRANSFER);
......@@ -489,7 +519,7 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
// check that soft input is hidden
InputMethodManager lManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
lManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
if(editName != null && editName.isVisible()){
if (editName != null && editName.isVisible()) {
editName.dismiss();
}
}
......@@ -503,28 +533,46 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
callStatusTxt.setText(String.format("%d:%02d:%02d", duration / 3600, duration % 3600 / 60, duration % 60));
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.values[0] == 0) {
WindowManager.LayoutParams params = getActivity().getWindow().getAttributes();
params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
params.screenBrightness = 0.004f;
getActivity().getWindow().setAttributes(params);
} else {
WindowManager.LayoutParams params = getActivity().getWindow().getAttributes();
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
params.screenBrightness = 1.0f;
getActivity().getWindow().setAttributes(params);
}
}
// @Override
// public void onAccuracyChanged(Sensor sensor, int accuracy) {
//
// }
// @Override
// public void onSensorChanged(SensorEvent event) {
// if (event.values[0] == 0) {
// // WindowManager.LayoutParams params = getActivity().getWindow().getAttributes();
// // params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
// // params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
// // params.screenBrightness = -1f;
// // getActivity().getWindow().setAttributes(params);
//
// } else {
// // WindowManager.LayoutParams params = getActivity().getWindow().getAttributes();
// // getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
// // params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
// // params.screenBrightness = 1.0f;
// // getActivity().getWindow().setAttributes(params);
// }
// }
// private void releaseProximityLock() {
// boolean released = false;
// if (wakelockParameterizedRelease != null) {
// try {
// wakelockParameterizedRelease.invoke(proximityLock, new Integer(WAIT_FOR_PROXIMITY_NEGATIVE));
// released = true;
// } catch (IllegalAccessException e) {
// Log.d("LockManager", "Failed to invoke release method", e);
// } catch (InvocationTargetException e) {
// Log.d("LockManager", "Failed to invoke release method", e);
// }
// }
//
// if(!released) {
// proximityLock.release();
// }
// }
public Conference getConference() {
return conf;
......@@ -532,11 +580,10 @@ public class CallFragment extends Fragment implements Callback, SensorEventListe
public void onKeyUp(int keyCode, KeyEvent event) {
try {
if(event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP || event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN)
if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP || event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN)
return;
String toSend = Character.toString(event.getDisplayLabel());
toSend.toUpperCase(Locale.getDefault());
Log.d(TAG, "toSend " + toSend);
......
/*
* Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
* Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
*
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
package org.sflphone.utils;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Handler;
import android.os.Message;
import java.lang.ref.WeakReference;
/**
* This class is used to listen to the accelerometer to monitor the orientation of the phone. The client of this class is notified when the
* orientation changes between horizontal and vertical.
*/
public final class AccelerometerListener {
private static final String TAG = "AccelerometerListener";
private static final boolean DEBUG = true;
private static final boolean VDEBUG = false;
private SensorManager mSensorManager;
private Sensor mSensor;
// mOrientation is the orientation value most recently reported to the client.
private int mOrientation;
// mPendingOrientation is the latest orientation computed based on the sensor value.
// This is sent to the client after a rebounce delay, at which point it is copied to
// mOrientation.
private int mPendingOrientation;
private OrientationListener mListener;
// Device orientation
public static final int ORIENTATION_UNKNOWN = 0;
public static final int ORIENTATION_VERTICAL = 1;
public static final int ORIENTATION_HORIZONTAL = 2;
private static final int ORIENTATION_CHANGED = 1234;
private static final int VERTICAL_DEBOUNCE = 100;
private static final int HORIZONTAL_DEBOUNCE = 500;
private static final double VERTICAL_ANGLE = 50.0;
public interface OrientationListener {
public void orientationChanged(int orientation);
}
public AccelerometerListener(Context context, OrientationListener listener) {
mListener = listener;
mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
public void enable(boolean enable) {
// if (DEBUG)
// Log.d(TAG, "enable(" + enable + ")");
synchronized (this) {
if (enable) {
mOrientation = ORIENTATION_UNKNOWN;
mPendingOrientation = ORIENTATION_UNKNOWN;
mSensorManager.registerListener(mSensorListener, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
} else {
mSensorManager.unregisterListener(mSensorListener);
mHandler.removeMessages(ORIENTATION_CHANGED);
}
}
}
private void setOrientation(int orientation) {
synchronized (this) {
if (mPendingOrientation == orientation) {
// Pending orientation has not changed, so do nothing.
return;
}
// Cancel any pending messages.
// We will either start a new timer or cancel alltogether
// if the orientation has not changed.
mHandler.removeMessages(ORIENTATION_CHANGED);
if (mOrientation != orientation) {
// Set timer to send an event if the orientation has changed since its
// previously reported value.
mPendingOrientation = orientation;
Message m = mHandler.obtainMessage(ORIENTATION_CHANGED);
// set delay to our debounce timeout
int delay = (orientation == ORIENTATION_VERTICAL ? VERTICAL_DEBOUNCE : HORIZONTAL_DEBOUNCE);
mHandler.sendMessageDelayed(m, delay);
} else {
// no message is pending
mPendingOrientation = ORIENTATION_UNKNOWN;
}
}
}
private void onSensorEvent(double x, double y, double z) {
// if (VDEBUG)
// Log.d(TAG, "onSensorEvent(" + x + ", " + y + ", " + z + ")");
// If some values are exactly zero, then likely the sensor is not powered up yet.
// ignore these events to avoid false horizontal positives.
if (x == 0.0 || y == 0.0 || z == 0.0)
return;
// magnitude of the acceleration vector projected onto XY plane
double xy = Math.sqrt(x * x + y * y);
// compute the vertical angle
double angle = Math.atan2(xy, z);
// convert to degrees
angle = angle * 180.0 / Math.PI;
int orientation = (angle > VERTICAL_ANGLE ? ORIENTATION_VERTICAL : ORIENTATION_HORIZONTAL);
// if (VDEBUG)
// Log.d(TAG, "angle: " + angle + " orientation: " + orientation);
setOrientation(orientation);
}
SensorEventListener mSensorListener = new SensorEventListener() {
public void onSensorChanged(SensorEvent event) {
onSensorEvent(event.values[0], event.values[1], event.values[2]);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// ignore
}
};
Handler mHandler = new AccelerometerHandler(this);
private static class AccelerometerHandler extends Handler {
WeakReference<AccelerometerListener> l;
AccelerometerHandler(AccelerometerListener listener) {
l = new WeakReference<AccelerometerListener>(listener);
}
public void handleMessage(Message msg) {
AccelerometerListener listener = l.get();
if (listener == null) {
return;
}
switch (msg.what) {
case ORIENTATION_CHANGED:
synchronized (listener) {
listener.mOrientation = listener.mPendingOrientation;
// if (DEBUG) {
// Log.d(TAG, "orientation: "
// + (listener.mOrientation == ORIENTATION_HORIZONTAL ? "horizontal"
// : (listener.mOrientation == ORIENTATION_VERTICAL ? "vertical" : "unknown")));
// }
listener.mListener.orientationChanged(listener.mOrientation);
}
break;
}
}
};
}
\ No newline at end of file
/*
* Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
* Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
*
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
package org.sflphone.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.sflphone.utils.AccelerometerListener.OrientationListener;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.net.wifi.WifiManager;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
/**
* Class to manage proximity detection while in call.
*
*/
public class CallProximityManager implements SensorEventListener, OrientationListener {
private static final String THIS_FILE = "CallProximityManager";
private Context mContext;
private SensorManager sensorManager;
private PowerManager powerManager;
// Timeout management of screen locker ui
// private ScreenLocker mScreenLocker;
private Boolean useTimeoutOverlay = null;
// Self management of proximity sensor
private Sensor proximitySensor;
private static final float PROXIMITY_THRESHOLD = 5.0f;
private boolean invertProximitySensor = false;
private boolean proximitySensorTracked = false;
private boolean isFirstRun = true;
private ProximityDirector mDirector = null;
// The hidden api that uses a wake lock
private WakeLock proximityWakeLock;
// The accelerometer
private AccelerometerListener accelerometerManager;
private int mOrientation;
private boolean accelerometerEnabled = false;
private int WAIT_FOR_PROXIMITY_NEGATIVE = 1;
// private final static int SCREEN_LOCKER_ACQUIRE_DELAY = "google_sdk".equals(Build.PRODUCT) ? ScreenLocker.WAIT_BEFORE_LOCK_LONG
// : ScreenLocker.WAIT_BEFORE_LOCK_SHORT;
private static Method powerLockReleaseIntMethod;
public interface ProximityDirector {
public boolean shouldActivateProximity();
public void onProximityTrackingChanged(boolean acquired);
}
public CallProximityManager(Context context, ProximityDirector director) {
mContext = context;
mDirector = director;
// mScreenLocker = screenLocker;
sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
accelerometerManager = new AccelerometerListener(context, this);
// Try to detect the hidden api
if (powerManager != null) {
WifiManager wman = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
// Try to use powermanager proximity sensor
try {
boolean supportProximity = false;
Field f = PowerManager.class.getDeclaredField("PROXIMITY_SCREEN_OFF_WAKE_LOCK");
int proximityScreenOffWakeLock = (Integer) f.get(null);
if (Compatibility.isCompatible(17)) {
// Changes of the private API on android 4.2
Method method = powerManager.getClass().getDeclaredMethod("isWakeLockLevelSupported", int.class);
supportProximity = (Boolean) method.invoke(powerManager, proximityScreenOffWakeLock);
Log.d(THIS_FILE, "Use 4.2 detection way for proximity sensor detection. Result is " + supportProximity);
} else {
Method method = powerManager.getClass().getDeclaredMethod("getSupportedWakeLockFlags");
int supportedFlags = (Integer) method.invoke(powerManager);
Log.d(THIS_FILE, "Proxmity flags supported : " + supportedFlags);
supportProximity = ((supportedFlags & proximityScreenOffWakeLock) != 0x0);
}
if (supportProximity) {
Log.d(THIS_FILE, "We can use native screen locker !!");
proximityWakeLock = powerManager.newWakeLock(proximityScreenOffWakeLock, "com.csipsimple.CallProximity");
proximityWakeLock.setReferenceCounted(false);
}
} catch (Exception e) {
Log.d(THIS_FILE, "Impossible to get power manager supported wake lock flags ");
}
if (powerLockReleaseIntMethod == null) {
try {
powerLockReleaseIntMethod = proximityWakeLock.getClass().getDeclaredMethod("release", int.class);
} catch (Exception e) {
Log.d(THIS_FILE, "Impossible to get power manager release with it");
}
}
}
// Try to detect a proximity sensor as fallback
if (proximityWakeLock == null) {
proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
// invertProximitySensor = SipConfigManager.getPreferenceBooleanValue(context, SipConfigManager.INVERT_PROXIMITY_SENSOR);
}
}
public synchronized void startTracking() {
// If we should manage it ourselves
if (proximitySensor != null && !proximitySensorTracked) {
// Fall back to manual mode
isFirstRun = true;
Log.d(THIS_FILE, "Register sensor");
sensorManager.registerListener(this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
proximitySensorTracked = true;
}
if (!accelerometerEnabled) {
accelerometerManager.enable(true);
accelerometerEnabled = true;
}
}
public synchronized void stopTracking() {
if (proximitySensor != null && proximitySensorTracked) {
proximitySensorTracked = false;
sensorManager.unregisterListener(this);
Log.d(THIS_FILE, "Unregister to sensor is done !!!");
}
if (accelerometerEnabled) {
accelerometerManager.enable(false);
accelerometerEnabled = false;
}
// mScreenLocker.tearDown();
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
// Log.d(THIS_FILE, "Tracked : "+proximitySensorTracked);
if (proximitySensorTracked && !isFirstRun) {
float distance = event.values[0];
boolean active = (distance >= 0.0 && distance < PROXIMITY_THRESHOLD && distance < event.sensor.getMaximumRange());
if (invertProximitySensor) {
active = !active;
}
Log.d(THIS_FILE, "Distance is now " + distance);
boolean isValidCallState = false;
if (mDirector != null) {
isValidCallState = mDirector.shouldActivateProximity();
}
if (isValidCallState && active) {
// mScreenLocker.show();
if (mDirector != null) {
mDirector.onProximityTrackingChanged(true);
}
} else {
// mScreenLocker.hide();
if (mDirector != null) {
mDirector.onProximityTrackingChanged(false);
}
}
}
if (isFirstRun) {
isFirstRun = false;
}
}
private boolean isProximityWakeHeld = false;
/**
* Release any lock taken by the proximity sensor
*/
public synchronized void release(int flag) {
if (proximityWakeLock != null && isProximityWakeHeld) {
boolean usedNewRelease = false;
if (powerLockReleaseIntMethod != null) {
try {
powerLockReleaseIntMethod.invoke(proximityWakeLock, flag);
usedNewRelease = true;
// Log.d(THIS_FILE, "CALL NEW RELEASE WITH FLAG " + flag);
} catch (Exception e) {
Log.d(THIS_FILE, "Error calling new release method ", e);
}
}
if (!usedNewRelease) {
proximityWakeLock.release();
}
isProximityWakeHeld = false;
}
if (shouldUseTimeoutOverlay()) {
// mScreenLocker.hide();
}
// Notify
if (mDirector != null) {
mDirector.onProximityTrackingChanged(false);
}
}
public synchronized void acquire() {
if (proximityWakeLock != null && !isProximityWakeHeld) {
proximityWakeLock.acquire();
isProximityWakeHeld = true;
}
if (shouldUseTimeoutOverlay()) {
// mScreenLocker.delayedLock(SCREEN_LOCKER_ACQUIRE_DELAY);
}
// Notify
if (mDirector != null) {
mDirector.onProximityTrackingChanged(true);
}
}
/**
* Update proximity lock mode depending on current state
*/
public synchronized void updateProximitySensorMode() {
// We do not keep the screen off when the user is outside in-call screen and we are
// horizontal, but we do not force it on when we become horizontal until the
// proximity sensor goes negative.
boolean horizontal = (mOrientation == AccelerometerListener.ORIENTATION_HORIZONTAL);
boolean activeRegardingCalls = false;
if (mDirector != null) {
activeRegardingCalls = mDirector.shouldActivateProximity();
}
Log.d(THIS_FILE, "Horizontal : " + horizontal + " and activate for calls " + activeRegardingCalls);
if (activeRegardingCalls && !horizontal) {
// Phone is in use! Arrange for the screen to turn off
// automatically when the sensor detects a close object.
acquire();
} else {
// Phone is either idle, or ringing. We don't want any
// special proximity sensor behavior in either case.
int flags = (!horizontal ? 0 : WAIT_FOR_PROXIMITY_NEGATIVE);
release(flags);
}
}
/**
* Should the application display the overlay after a timeout.
*
* @return false if we are in table mode or if proximity sensor can be used
*/
private boolean shouldUseTimeoutOverlay() {
if (useTimeoutOverlay == null) {
useTimeoutOverlay = proximitySensor == null && proximityWakeLock == null && !Compatibility.isTabletScreen(mContext);
}
return useTimeoutOverlay;
}
public void restartTimer() {
if (shouldUseTimeoutOverlay()) {
// mScreenLocker.delayedLock(ScreenLocker.WAIT_BEFORE_LOCK_LONG);
}
}
@Override
public void orientationChanged(int orientation) {
mOrientation = orientation;
updateProximitySensorMode();
}
}
\ No newline at end of file
/*
* Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
* Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
*
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
package org.sflphone.utils;
import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.Field;
import java.util.regex.Pattern;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.media.AudioManager;
import android.media.MediaRecorder.AudioSource;
import android.net.Uri;
import android.os.Environment;
import android.provider.Contacts;
import android.util.Log;
@SuppressWarnings("deprecation")
public final class Compatibility {
private Compatibility() {
}
private static final String THIS_FILE = "Compat";
public static int getApiLevel() {
return android.os.Build.VERSION.SDK_INT;
}
public static boolean isCompatible(int apiLevel) {
return android.os.Build.VERSION.SDK_INT >= apiLevel;
}
/**
* Get the stream id for in call track. Can differ on some devices. Current
* device for which it's different :
*
* @return
*/
public static int getInCallStream(boolean requestBluetooth) {
/* Archos 5IT */
if (android.os.Build.BRAND.equalsIgnoreCase("archos")
&& android.os.Build.DEVICE.equalsIgnoreCase("g7a")) {
// Since archos has no voice call capabilities, voice call stream is
// not implemented
// So we have to choose the good stream tag, which is by default
// falled back to music
return AudioManager.STREAM_MUSIC;
}
if (requestBluetooth) {
return 6; /* STREAM_BLUETOOTH_SCO -- Thx @Stefan for the contrib */
}
// return AudioManager.STREAM_MUSIC;
return AudioManager.STREAM_VOICE_CALL;
}
public static boolean shouldUseRoutingApi() {
Log.d(THIS_FILE, "Current device " + android.os.Build.BRAND + " - "
+ android.os.Build.DEVICE);
// HTC evo 4G
if (android.os.Build.PRODUCT.equalsIgnoreCase("htc_supersonic")) {
return true;
}
// ZTE joe
if (android.os.Build.DEVICE.equalsIgnoreCase("joe")) {
return true;
}
// Samsung GT-S5830
if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-S")) {
return true;
}
if (!isCompatible(4)) {
// If android 1.5, force routing api use
return true;
} else {
return false;
}
}
public static boolean shouldUseModeApi() {
// ZTE blade et joe
if (android.os.Build.DEVICE.equalsIgnoreCase("blade")
|| android.os.Build.DEVICE.equalsIgnoreCase("joe")) {
return true;
}
// Samsung GT-S5360 GT-S5830 GT-S6102 ... probably all..
if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-") ||
android.os.Build.PRODUCT.toUpperCase().startsWith("GT-") ||
android.os.Build.DEVICE.toUpperCase().startsWith("YP-")) {
return true;
}
// HTC evo 4G
if (android.os.Build.PRODUCT.equalsIgnoreCase("htc_supersonic")) {
return true;
}
// LG P500, Optimus V
if (android.os.Build.DEVICE.toLowerCase().startsWith("thunder")) {
return true;
}
// LG-E720(b)
if (android.os.Build.MODEL.toUpperCase().startsWith("LG-E720")
&& !Compatibility.isCompatible(9)) {
return true;
}
// LG-LS840
if (android.os.Build.DEVICE.toLowerCase().startsWith("cayman")) {
return true;
}
// Huawei
if (android.os.Build.DEVICE.equalsIgnoreCase("U8150") ||
android.os.Build.DEVICE.equalsIgnoreCase("U8110") ||
android.os.Build.DEVICE.equalsIgnoreCase("U8120") ||
android.os.Build.DEVICE.equalsIgnoreCase("U8100") ||
android.os.Build.PRODUCT.equalsIgnoreCase("U8655")) {
return true;
}
// Moto defy mini
if (android.os.Build.MODEL.equalsIgnoreCase("XT320")) {
return true;
}
// Alcatel
if (android.os.Build.DEVICE.toUpperCase().startsWith("ONE_TOUCH_993D")) {
return true;
}
// N4
if (android.os.Build.DEVICE.toUpperCase().startsWith("MAKO")) {
return true;
}
return false;
}
public static String guessInCallMode() {
// New api for 2.3.3 is not available on galaxy S II :(
if (!isCompatible(11) && android.os.Build.DEVICE.toUpperCase().startsWith("GT-I9100")) {
return Integer.toString(AudioManager.MODE_NORMAL);
}
if (android.os.Build.BRAND.equalsIgnoreCase("sdg") || isCompatible(10)) {
// Note that in APIs this is only available from level 11.
return "3";
}
if (android.os.Build.DEVICE.equalsIgnoreCase("blade")) {
return Integer.toString(AudioManager.MODE_IN_CALL);
}
if (!isCompatible(5)) {
return Integer.toString(AudioManager.MODE_IN_CALL);
}
return Integer.toString(AudioManager.MODE_NORMAL);
}
public static String getDefaultMicroSource() {
// Except for galaxy S II :(
if (!isCompatible(11) && android.os.Build.DEVICE.toUpperCase().startsWith("GT-I9100")) {
return Integer.toString(AudioSource.MIC);
}
if (isCompatible(10)) {
// Note that in APIs this is only available from level 11.
// VOICE_COMMUNICATION
return Integer.toString(0x7);
}
/*
* Too risky in terms of regressions else if (isCompatible(4)) { //
* VOICE_CALL return 0x4; }
*/
/*
* if(android.os.Build.MODEL.equalsIgnoreCase("X10i")) { // VOICE_CALL
* return Integer.toString(0x4); }
*/
/*
* Not relevant anymore, atrix I tested sounds fine with that
* if(android.os.Build.DEVICE.equalsIgnoreCase("olympus")) { //Motorola
* atrix bug // CAMCORDER return Integer.toString(0x5); }
*/
return Integer.toString(AudioSource.DEFAULT);
}
public static String getDefaultFrequency() {
if (android.os.Build.DEVICE.equalsIgnoreCase("olympus")) {
// Atrix bug
return "32000";
}
if (android.os.Build.DEVICE.toUpperCase().equals("GT-P1010")) {
// Galaxy tab see issue 932
return "32000";
}
return isCompatible(4) ? "16000" : "8000";
}
public static String getCpuAbi() {
if (isCompatible(4)) {
Field field;
try {
field = android.os.Build.class.getField("CPU_ABI");
return field.get(null).toString();
} catch (Exception e) {
Log.w(THIS_FILE, "Announce to be android 1.6 but no CPU ABI field", e);
}
}
return "armeabi";
}
public final static int getNumCores() {
// Private Class to display only CPU devices in the directory listing
class CpuFilter implements FileFilter {
@Override
public boolean accept(File pathname) {
// Check if filename is "cpu", followed by a single digit number
if (Pattern.matches("cpu[0-9]", pathname.getName())) {
return true;
}
return false;
}
}
try {
// Get directory containing CPU info
File dir = new File("/sys/devices/system/cpu/");
// Filter to only list the devices we care about
File[] files = dir.listFiles(new CpuFilter());
// Return the number of cores (virtual CPU devices)
return files.length;
} catch (Exception e) {
return Runtime.getRuntime().availableProcessors();
}
}
private static boolean needPspWorkaround() {
// New api for 2.3 does not work on Incredible S
if (android.os.Build.DEVICE.equalsIgnoreCase("vivo")) {
return true;
}
// New API for android 2.3 should be able to manage this but do only for
// honeycomb cause seems not correctly supported by all yet
if (isCompatible(11)) {
return false;
}
// All htc except....
if (android.os.Build.PRODUCT.toLowerCase().startsWith("htc")
|| android.os.Build.BRAND.toLowerCase().startsWith("htc")
|| android.os.Build.PRODUCT.toLowerCase().equalsIgnoreCase("inc") /*
* For
* Incredible
*/
|| android.os.Build.DEVICE.equalsIgnoreCase("passion") /* N1 */) {
if (android.os.Build.DEVICE.equalsIgnoreCase("hero") /* HTC HERO */
|| android.os.Build.DEVICE.equalsIgnoreCase("magic") /*
* Magic
* Aka
* Dev
* G2
*/
|| android.os.Build.DEVICE.equalsIgnoreCase("tatoo") /* Tatoo */
|| android.os.Build.DEVICE.equalsIgnoreCase("dream") /*
* Dream
* Aka
* Dev
* G1
*/
|| android.os.Build.DEVICE.equalsIgnoreCase("legend") /* Legend */
) {
return false;
}
// Older than 2.3 has no chance to have the new full perf wifi mode
// working since does not exists
if (!isCompatible(9)) {
return true;
} else {
// N1 is fine with that
if (android.os.Build.DEVICE.equalsIgnoreCase("passion")) {
return false;
}
return true;
}
}
// Dell streak
if (android.os.Build.BRAND.toLowerCase().startsWith("dell") &&
android.os.Build.DEVICE.equalsIgnoreCase("streak")) {
return true;
}
// Motorola milestone 1 and 2 & motorola droid & defy not under 2.3
if ((android.os.Build.DEVICE.toLowerCase().contains("milestone2") ||
android.os.Build.BOARD.toLowerCase().contains("sholes") ||
android.os.Build.PRODUCT.toLowerCase().contains("sholes") ||
android.os.Build.DEVICE.equalsIgnoreCase("olympus") ||
android.os.Build.DEVICE.toLowerCase().contains("umts_jordan")) && !isCompatible(9)) {
return true;
}
// Moto defy mini
if (android.os.Build.MODEL.equalsIgnoreCase("XT320")) {
return true;
}
// Alcatel ONE touch
if (android.os.Build.DEVICE.startsWith("one_touch_990")) {
return true;
}
return false;
}
private static boolean needToneWorkaround() {
if (android.os.Build.PRODUCT.toLowerCase().startsWith("gt-i5800") ||
android.os.Build.PRODUCT.toLowerCase().startsWith("gt-i5801") ||
android.os.Build.PRODUCT.toLowerCase().startsWith("gt-i9003")) {
return true;
}
return false;
}
private static boolean needSGSWorkaround() {
if (isCompatible(9)) {
return false;
}
if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-I9000") ||
android.os.Build.DEVICE.toUpperCase().startsWith("GT-P1000")) {
return true;
}
return false;
}
private static boolean needWebRTCImplementation() {
if (android.os.Build.DEVICE.toLowerCase().contains("droid2")) {
return true;
}
if (android.os.Build.MODEL.toLowerCase().contains("droid bionic")) {
return true;
}
if (android.os.Build.DEVICE.toLowerCase().contains("sunfire")) {
return true;
}
// Huawei Y300
if (android.os.Build.DEVICE.equalsIgnoreCase("U8833")) {
return true;
}
return false;
}
public static boolean shouldSetupAudioBeforeInit() {
// Setup for GT / GS samsung devices.
if (android.os.Build.DEVICE.toLowerCase().startsWith("gt-")
|| android.os.Build.PRODUCT.toLowerCase().startsWith("gt-")) {
return true;
}
return false;
}
private static boolean shouldFocusAudio() {
/* HTC One X */
if (android.os.Build.DEVICE.toLowerCase().startsWith("endeavoru") ||
android.os.Build.DEVICE.toLowerCase().startsWith("evita")) {
return false;
}
if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-P7510") && isCompatible(15)) {
return false;
}
return true;
}
// private static int getDefaultAudioImplementation() {
// // Acer A510
// if (android.os.Build.DEVICE.toLowerCase().startsWith("picasso")) {
// return SipConfigManager.AUDIO_IMPLEMENTATION_JAVA;
// }
// if (Compatibility.isCompatible(11)) {
// return SipConfigManager.AUDIO_IMPLEMENTATION_OPENSLES;
// }
// if (android.os.Build.DEVICE.equalsIgnoreCase("ST25i") && Compatibility.isCompatible(10)) {
// return SipConfigManager.AUDIO_IMPLEMENTATION_OPENSLES;
// }
// if (android.os.Build.DEVICE.equalsIgnoreCase("u8510") && Compatibility.isCompatible(10)) {
// return SipConfigManager.AUDIO_IMPLEMENTATION_OPENSLES;
// }
// return SipConfigManager.AUDIO_IMPLEMENTATION_JAVA;
// }
public static boolean useFlipAnimation() {
if (android.os.Build.BRAND.equalsIgnoreCase("archos")
&& android.os.Build.DEVICE.equalsIgnoreCase("g7a")) {
return false;
}
return true;
}
public static Intent getContactPhoneIntent() {
Intent intent = new Intent(Intent.ACTION_PICK);
/*
* intent.setAction(Intent.ACTION_GET_CONTENT);
* intent.setType(Contacts.Phones.CONTENT_ITEM_TYPE);
*/
if (isCompatible(5)) {
// Don't use constant to allow backward compat simply
intent.setData(Uri.parse("content://com.android.contacts/contacts"));
} else {
// Fallback for android 4
intent.setData(Contacts.People.CONTENT_URI);
}
return intent;
}
public static boolean isTabletScreen(Context ctxt) {
boolean isTablet = false;
if (!isCompatible(4)) {
return false;
}
Configuration cfg = ctxt.getResources().getConfiguration();
int screenLayoutVal = 0;
try {
Field f = Configuration.class.getDeclaredField("screenLayout");
screenLayoutVal = (Integer) f.get(cfg);
} catch (Exception e) {
return false;
}
int screenLayout = (screenLayoutVal & 0xF);
// 0xF = SCREENLAYOUT_SIZE_MASK but avoid 1.5 incompat doing that
if (screenLayout == 0x3 || screenLayout == 0x4) {
// 0x3 = SCREENLAYOUT_SIZE_LARGE but avoid 1.5 incompat doing that
// 0x4 = SCREENLAYOUT_SIZE_XLARGE but avoid 1.5 incompat doing that
isTablet = true;
}
return isTablet;
}
public static int getHomeMenuId() {
return 0x0102002c;
// return android.R.id.home;
}
public static boolean isInstalledOnSdCard(Context context) {
// check for API level 8 and higher
if (Compatibility.isCompatible(8)) {
PackageManager pm = context.getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
ApplicationInfo ai = pi.applicationInfo;
return (ai.flags & 0x00040000 /*
* ApplicationInfo.
* FLAG_EXTERNAL_STORAGE
*/) == 0x00040000 /*
* ApplicationInfo.
* FLAG_EXTERNAL_STORAGE
*/;
} catch (NameNotFoundException e) {
// ignore
}
}
// check for API level 7 - check files dir
try {
String filesDir = context.getFilesDir().getAbsolutePath();
if (filesDir.startsWith("/data/")) {
return false;
} else if (filesDir.contains(Environment.getExternalStorageDirectory().getPath())) {
return true;
}
} catch (Throwable e) {
// ignore
}
return false;
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment