mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-24 05:44:10 +00:00
Bug 679966, part 1: Add vibrator support for android. r=blassey,cjones
This commit is contained in:
parent
5dec9d83e1
commit
dc33fffa65
@ -64,6 +64,7 @@ EXPORTS = \
|
||||
nsStubMutationObserver.h \
|
||||
nsTextFragment.h \
|
||||
mozAutoDocUpdate.h \
|
||||
nsFrameMessageManager.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_NAMESPACES = mozilla/dom
|
||||
|
@ -49,6 +49,7 @@ LIBXUL_LIBRARY = 1
|
||||
EXPORTS = \
|
||||
nsEventStateManager.h \
|
||||
nsEventListenerManager.h \
|
||||
nsDOMEventTargetHelper.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
|
@ -233,6 +233,7 @@ ContentChild* ContentChild::sSingleton;
|
||||
ContentChild::ContentChild()
|
||||
#ifdef ANDROID
|
||||
: mScreenSize(0, 0)
|
||||
, mID(PRUint64(-1))
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@ -803,5 +804,15 @@ ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvSetID(const PRUint64 &id)
|
||||
{
|
||||
if (mID != PRUint64(-1)) {
|
||||
NS_WARNING("Setting content child's ID twice?");
|
||||
}
|
||||
mID = id;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -168,6 +168,7 @@ public:
|
||||
virtual bool RecvCycleCollect();
|
||||
|
||||
virtual bool RecvAppInfo(const nsCString& version, const nsCString& buildID);
|
||||
virtual bool RecvSetID(const PRUint64 &id);
|
||||
|
||||
#ifdef ANDROID
|
||||
gfxIntSize GetScreenSize() { return mScreenSize; }
|
||||
@ -177,6 +178,8 @@ public:
|
||||
// cache the value
|
||||
nsString &GetIndexedDBPath();
|
||||
|
||||
PRUint64 GetID() { return mID; }
|
||||
|
||||
private:
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
@ -198,6 +201,15 @@ private:
|
||||
|
||||
AppInfo mAppInfo;
|
||||
|
||||
/**
|
||||
* An ID unique to the process containing our corresponding
|
||||
* content parent.
|
||||
*
|
||||
* We expect our content parent to set this ID immediately after opening a
|
||||
* channel to us.
|
||||
*/
|
||||
PRUint64 mID;
|
||||
|
||||
static ContentChild* sSingleton;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(ContentChild);
|
||||
|
@ -162,6 +162,9 @@ MemoryReportRequestParent::~MemoryReportRequestParent()
|
||||
|
||||
nsTArray<ContentParent*>* ContentParent::gContentParents;
|
||||
|
||||
// The first content child has ID 1, so the chrome process can have ID 0.
|
||||
static PRUint64 gContentChildID = 1;
|
||||
|
||||
ContentParent*
|
||||
ContentParent::GetNewOrUsed()
|
||||
{
|
||||
@ -424,6 +427,7 @@ ContentParent::ContentParent()
|
||||
mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content);
|
||||
mSubprocess->AsyncLaunch();
|
||||
Open(mSubprocess->GetChannel(), mSubprocess->GetChildProcessHandle());
|
||||
unused << SendSetID(gContentChildID++);
|
||||
|
||||
nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
|
||||
nsChromeRegistryChrome* chromeRegistry =
|
||||
|
@ -147,6 +147,8 @@ child:
|
||||
|
||||
AppInfo(nsCString version, nsCString buildID);
|
||||
|
||||
SetID(PRUint64 id);
|
||||
|
||||
parent:
|
||||
PAudio(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat);
|
||||
|
||||
|
@ -303,6 +303,14 @@ GetTabChildFrom(nsIPresShell* aPresShell)
|
||||
return GetTabChildFrom(docShell);
|
||||
}
|
||||
|
||||
inline TabChild*
|
||||
GetTabChildFrom(nsIDOMWindow* aWindow)
|
||||
{
|
||||
nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(aWindow);
|
||||
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(webNav);
|
||||
return GetTabChildFrom(docShell);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,6 +91,7 @@ TabParent::TabParent()
|
||||
, mIMECompositionEnding(false)
|
||||
, mIMESeqno(0)
|
||||
, mDPI(0)
|
||||
, mActive(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -217,15 +218,23 @@ TabParent::UpdateDimensions(const nsRect& rect, const nsIntSize& size)
|
||||
void
|
||||
TabParent::Activate()
|
||||
{
|
||||
mActive = true;
|
||||
unused << SendActivate();
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::Deactivate()
|
||||
{
|
||||
mActive = false;
|
||||
unused << SendDeactivate();
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::Active()
|
||||
{
|
||||
return mActive;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabParent::Init(nsIDOMWindow *window)
|
||||
{
|
||||
|
@ -131,6 +131,13 @@ public:
|
||||
void UpdateDimensions(const nsRect& rect, const nsIntSize& size);
|
||||
void Activate();
|
||||
void Deactivate();
|
||||
|
||||
/**
|
||||
* Is this object active? That is, was Activate() called more recently than
|
||||
* Deactivate()?
|
||||
*/
|
||||
bool Active();
|
||||
|
||||
void SendMouseEvent(const nsAString& aType, float aX, float aY,
|
||||
PRInt32 aButton, PRInt32 aClickCount,
|
||||
PRInt32 aModifiers, bool aIgnoreRootScrollFrame);
|
||||
@ -221,6 +228,7 @@ protected:
|
||||
PRUint32 mIMESeqno;
|
||||
|
||||
float mDPI;
|
||||
bool mActive;
|
||||
|
||||
private:
|
||||
already_AddRefed<nsFrameLoader> GetFrameLoader() const;
|
||||
|
@ -22,6 +22,7 @@
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
|
||||
<uses-feature android:name="android.hardware.location" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.location.gps" android:required="false"/>
|
||||
|
@ -1043,6 +1043,22 @@ public class GeckoAppShell
|
||||
HapticFeedbackConstants.VIRTUAL_KEY);
|
||||
}
|
||||
|
||||
private static Vibrator vibrator() {
|
||||
return (Vibrator) GeckoApp.surfaceView.getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
||||
}
|
||||
|
||||
public static void vibrate(long milliseconds) {
|
||||
vibrator().vibrate(milliseconds);
|
||||
}
|
||||
|
||||
public static void vibrate(long[] pattern, int repeat) {
|
||||
vibrator().vibrate(pattern, repeat);
|
||||
}
|
||||
|
||||
public static void cancelVibrate() {
|
||||
vibrator().cancel();
|
||||
}
|
||||
|
||||
public static void showInputMethodPicker() {
|
||||
InputMethodManager imm = (InputMethodManager) GeckoApp.surfaceView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.showInputMethodPicker();
|
||||
|
218
hal/Hal.cpp
218
hal/Hal.cpp
@ -1,5 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: sw=2 ts=8 et ft=cpp : */
|
||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
@ -38,10 +38,24 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "Hal.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "mozilla/Observer.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsITabChild.h"
|
||||
#include "nsIDocShell.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::services;
|
||||
|
||||
#define PROXY_IF_SANDBOXED(_call) \
|
||||
do { \
|
||||
@ -55,25 +69,215 @@
|
||||
namespace mozilla {
|
||||
namespace hal {
|
||||
|
||||
static void
|
||||
PRLogModuleInfo *sHalLog = PR_LOG_DEFINE("hal");
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
AssertMainThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
static bool
|
||||
bool
|
||||
InSandbox()
|
||||
{
|
||||
return GeckoProcessType_Content == XRE_GetProcessType();
|
||||
}
|
||||
|
||||
void
|
||||
Vibrate(const nsTArray<uint32>& pattern)
|
||||
bool
|
||||
WindowIsActive(nsIDOMWindow *window)
|
||||
{
|
||||
AssertMainThread();
|
||||
PROXY_IF_SANDBOXED(Vibrate(pattern));
|
||||
NS_ENSURE_TRUE(window, false);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> doc;
|
||||
window->GetDocument(getter_AddRefs(doc));
|
||||
NS_ENSURE_TRUE(doc, false);
|
||||
|
||||
bool hidden = true;
|
||||
doc->GetMozHidden(&hidden);
|
||||
return !hidden;
|
||||
}
|
||||
|
||||
nsAutoPtr<WindowIdentifier::IDArrayType> gLastIDToVibrate;
|
||||
|
||||
// This observer makes sure we delete gLastIDToVibrate, so we don't
|
||||
// leak.
|
||||
class ShutdownObserver : public nsIObserver
|
||||
{
|
||||
public:
|
||||
ShutdownObserver() {}
|
||||
virtual ~ShutdownObserver() {}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Observe(nsISupports *subject, const char *aTopic,
|
||||
const PRUnichar *aData)
|
||||
{
|
||||
MOZ_ASSERT(strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0);
|
||||
gLastIDToVibrate = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(ShutdownObserver, nsIObserver);
|
||||
|
||||
void InitLastIDToVibrate()
|
||||
{
|
||||
gLastIDToVibrate = new WindowIdentifier::IDArrayType();
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService = GetObserverService();
|
||||
if (!observerService) {
|
||||
NS_WARNING("Could not get observer service!");
|
||||
return;
|
||||
}
|
||||
|
||||
ShutdownObserver *obs = new ShutdownObserver();
|
||||
observerService->AddObserver(obs, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
WindowIdentifier::WindowIdentifier()
|
||||
: mWindow(nsnull)
|
||||
, mIsEmpty(true)
|
||||
{
|
||||
}
|
||||
|
||||
WindowIdentifier::WindowIdentifier(nsIDOMWindow *window)
|
||||
: mWindow(window)
|
||||
, mIsEmpty(false)
|
||||
{
|
||||
mID.AppendElement(GetWindowID());
|
||||
}
|
||||
|
||||
WindowIdentifier::WindowIdentifier(nsCOMPtr<nsIDOMWindow> &window)
|
||||
: mWindow(window)
|
||||
, mIsEmpty(false)
|
||||
{
|
||||
mID.AppendElement(GetWindowID());
|
||||
}
|
||||
|
||||
WindowIdentifier::WindowIdentifier(const nsTArray<uint64> &id, nsIDOMWindow *window)
|
||||
: mID(id)
|
||||
, mWindow(window)
|
||||
, mIsEmpty(false)
|
||||
{
|
||||
mID.AppendElement(GetWindowID());
|
||||
}
|
||||
|
||||
WindowIdentifier::WindowIdentifier(const WindowIdentifier &other)
|
||||
: mID(other.mID)
|
||||
, mWindow(other.mWindow)
|
||||
, mIsEmpty(other.mIsEmpty)
|
||||
{
|
||||
}
|
||||
|
||||
const InfallibleTArray<uint64>&
|
||||
WindowIdentifier::AsArray() const
|
||||
{
|
||||
MOZ_ASSERT(!mIsEmpty);
|
||||
return mID;
|
||||
}
|
||||
|
||||
bool
|
||||
WindowIdentifier::HasTraveledThroughIPC() const
|
||||
{
|
||||
MOZ_ASSERT(!mIsEmpty);
|
||||
return mID.Length() >= 2;
|
||||
}
|
||||
|
||||
void
|
||||
WindowIdentifier::AppendProcessID()
|
||||
{
|
||||
MOZ_ASSERT(!mIsEmpty);
|
||||
mID.AppendElement(ContentChild::GetSingleton()->GetID());
|
||||
}
|
||||
|
||||
uint64
|
||||
WindowIdentifier::GetWindowID() const
|
||||
{
|
||||
MOZ_ASSERT(!mIsEmpty);
|
||||
nsCOMPtr<nsPIDOMWindow> pidomWindow = do_QueryInterface(mWindow);
|
||||
if (!pidomWindow) {
|
||||
return uint64(-1);
|
||||
}
|
||||
return pidomWindow->WindowID();
|
||||
}
|
||||
|
||||
nsIDOMWindow*
|
||||
WindowIdentifier::GetWindow() const
|
||||
{
|
||||
MOZ_ASSERT(!mIsEmpty);
|
||||
return mWindow;
|
||||
}
|
||||
|
||||
void
|
||||
Vibrate(const nsTArray<uint32>& pattern, const WindowIdentifier &id)
|
||||
{
|
||||
AssertMainThread();
|
||||
|
||||
// Only active windows may start vibrations. If |id| hasn't gone
|
||||
// through the IPC layer -- that is, if our caller is the outside
|
||||
// world, not hal_proxy -- check whether the window is active. If
|
||||
// |id| has gone through IPC, don't check the window's visibility;
|
||||
// only the window corresponding to the bottommost process has its
|
||||
// visibility state set correctly.
|
||||
if (!id.HasTraveledThroughIPC() && !WindowIsActive(id.GetWindow())) {
|
||||
HAL_LOG(("Vibrate: Window is inactive, dropping vibrate."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (InSandbox()) {
|
||||
hal_sandbox::Vibrate(pattern, id);
|
||||
}
|
||||
else {
|
||||
if (!gLastIDToVibrate)
|
||||
InitLastIDToVibrate();
|
||||
*gLastIDToVibrate = id.AsArray();
|
||||
|
||||
HAL_LOG(("Vibrate: Forwarding to hal_impl."));
|
||||
|
||||
// hal_impl doesn't need |id|. Send it an empty id, which will
|
||||
// assert if it's used.
|
||||
hal_impl::Vibrate(pattern, WindowIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CancelVibrate(const WindowIdentifier &id)
|
||||
{
|
||||
AssertMainThread();
|
||||
|
||||
// Although only active windows may start vibrations, a window may
|
||||
// cancel its own vibration even if it's no longer active.
|
||||
//
|
||||
// After a window is marked as inactive, it sends a CancelVibrate
|
||||
// request. We want this request to cancel a playing vibration
|
||||
// started by that window, so we certainly don't want to reject the
|
||||
// cancellation request because the window is now inactive.
|
||||
//
|
||||
// But it could be the case that, after this window became inactive,
|
||||
// some other window came along and started a vibration. We don't
|
||||
// want this window's cancellation request to cancel that window's
|
||||
// actively-playing vibration!
|
||||
//
|
||||
// To solve this problem, we keep track of the id of the last window
|
||||
// to start a vibration, and only accepts cancellation requests from
|
||||
// the same window. All other cancellation requests are ignored.
|
||||
|
||||
if (InSandbox()) {
|
||||
hal_sandbox::CancelVibrate(id);
|
||||
}
|
||||
else if (*gLastIDToVibrate == id.AsArray()) {
|
||||
// Don't forward our ID to hal_impl. It doesn't need it, and we
|
||||
// don't want it to be tempted to read it. The empty identifier
|
||||
// will assert if it's used.
|
||||
HAL_LOG(("CancelVibrate: Forwarding to hal_impl."));
|
||||
hal_impl::CancelVibrate(WindowIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
class BatteryObserversManager
|
||||
{
|
||||
public:
|
||||
|
143
hal/Hal.h
143
hal/Hal.h
@ -1,5 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: sw=2 ts=8 et ft=cpp : */
|
||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
@ -43,9 +43,120 @@
|
||||
#include "base/basictypes.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "prlog.h"
|
||||
#include "mozilla/dom/battery/Types.h"
|
||||
|
||||
#ifndef MOZ_HAL_NAMESPACE
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class TabChild;
|
||||
class PBrowserChild;
|
||||
}
|
||||
}
|
||||
|
||||
// Only include this hunk of code once, and include it before
|
||||
// HalImpl.h and HalSandbox.h.
|
||||
namespace mozilla {
|
||||
namespace hal {
|
||||
|
||||
extern PRLogModuleInfo *sHalLog;
|
||||
#define HAL_LOG(msg) PR_LOG(sHalLog, PR_LOG_DEBUG, msg)
|
||||
|
||||
/**
|
||||
* This class serves two purposes.
|
||||
*
|
||||
* First, this class wraps a pointer to a window.
|
||||
*
|
||||
* Second, WindowIdentifier lets us uniquely identify a window across
|
||||
* processes. A window exposes an ID which is unique only within its
|
||||
* process. Thus to identify a window, we need to know the ID of the
|
||||
* process which contains it. But the scope of a process's ID is its
|
||||
* parent; that is, two processes with different parents might have
|
||||
* the same ID.
|
||||
*
|
||||
* So to identify a window, we need its ID plus the IDs of all the
|
||||
* processes in the path from the window's process to the root
|
||||
* process. We throw in the IDs of the intermediate windows (a
|
||||
* content window is contained in a window at each level of the
|
||||
* process tree) for good measures.
|
||||
*
|
||||
* You can access this list of IDs by calling AsArray().
|
||||
*/
|
||||
class WindowIdentifier
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create an empty WindowIdentifier. Calls to any of this object's
|
||||
* public methods will assert -- an empty WindowIdentifier may be
|
||||
* used only as a placeholder to code which promises not to touch
|
||||
* the object.
|
||||
*/
|
||||
WindowIdentifier();
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*/
|
||||
WindowIdentifier(const WindowIdentifier& other);
|
||||
|
||||
/**
|
||||
* Wrap the given window in a WindowIdentifier. These two
|
||||
* constructors automatically grab the window's ID and append it to
|
||||
* the array of IDs.
|
||||
*
|
||||
* Note that these constructors allow an implicit conversion to a
|
||||
* WindowIdentifier.
|
||||
*/
|
||||
WindowIdentifier(nsIDOMWindow* window);
|
||||
WindowIdentifier(nsCOMPtr<nsIDOMWindow> &window);
|
||||
|
||||
/**
|
||||
* Create a new WindowIdentifier with the given id array and window.
|
||||
* This automatically grabs the window's ID and appends it to the
|
||||
* array.
|
||||
*/
|
||||
WindowIdentifier(const nsTArray<uint64>& id, nsIDOMWindow* window);
|
||||
|
||||
/**
|
||||
* Get the list of window and process IDs we contain.
|
||||
*/
|
||||
typedef InfallibleTArray<uint64> IDArrayType;
|
||||
const IDArrayType& AsArray() const;
|
||||
|
||||
/**
|
||||
* Append the ID of the ContentChild singleton to our array of
|
||||
* window/process IDs.
|
||||
*/
|
||||
void AppendProcessID();
|
||||
|
||||
/**
|
||||
* Does this WindowIdentifier identify both a window and the process
|
||||
* containing that window? If so, we say it has traveled through
|
||||
* IPC.
|
||||
*/
|
||||
bool HasTraveledThroughIPC() const;
|
||||
|
||||
/**
|
||||
* Get the window this object wraps.
|
||||
*/
|
||||
nsIDOMWindow* GetWindow() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Get the ID of the window object we wrap.
|
||||
*/
|
||||
uint64 GetWindowID() const;
|
||||
|
||||
AutoInfallibleTArray<uint64, 3> mID;
|
||||
nsCOMPtr<nsIDOMWindow> mWindow;
|
||||
bool mIsEmpty;
|
||||
};
|
||||
|
||||
} // namespace hal
|
||||
} // namespace mozilla
|
||||
|
||||
// This goop plays some cpp tricks to ensure a uniform API across the
|
||||
// API entry point, "sandbox" implementations (for content processes),
|
||||
// and "impl" backends where the real work happens. After this runs
|
||||
@ -78,8 +189,32 @@ namespace MOZ_HAL_NAMESPACE /*hal*/ {
|
||||
* |pattern| is an "on" element, the next is "off", and so on.
|
||||
*
|
||||
* If |pattern| is empty, any in-progress vibration is canceled.
|
||||
*
|
||||
* Only an active window within an active tab may call Vibrate; calls
|
||||
* from inactive windows and windows on inactive tabs do nothing.
|
||||
*
|
||||
* If you're calling hal::Vibrate from the outside world, pass an
|
||||
* nsIDOMWindow* or an nsCOMPtr<nsIDOMWindow>& in place of the
|
||||
* WindowIdentifier parameter. It'll be converted to a WindowIdentifier
|
||||
* automatically.
|
||||
*/
|
||||
void Vibrate(const nsTArray<uint32>& pattern);
|
||||
void Vibrate(const nsTArray<uint32>& pattern,
|
||||
const hal::WindowIdentifier &id);
|
||||
|
||||
/**
|
||||
* Cancel a vibration started by the content window identified by
|
||||
* WindowIdentifier.
|
||||
*
|
||||
* If the window was the last window to start a vibration, the
|
||||
* cancellation request will go through even if the window is not
|
||||
* active.
|
||||
*
|
||||
* As with hal::Vibrate(), if you're calling hal::CancelVibrate from
|
||||
* the outside world, pass an nsIDOMWindow* or an
|
||||
* nsCOMPtr<nsIDOMWindow>&. This will automatically be converted to a
|
||||
* WindowIdentifier object.
|
||||
*/
|
||||
void CancelVibrate(const hal::WindowIdentifier &id);
|
||||
|
||||
/**
|
||||
* Inform the battery backend there is a new battery observer.
|
||||
@ -122,8 +257,8 @@ void GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo);
|
||||
*/
|
||||
void NotifyBatteryChange(const hal::BatteryInformation& aBatteryInfo);
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace MOZ_HAL_NAMESPACE
|
||||
} // namespace mozilla
|
||||
|
||||
#ifdef MOZ_DEFINED_HAL_NAMESPACE
|
||||
# undef MOZ_DEFINED_HAL_NAMESPACE
|
||||
|
@ -38,12 +38,39 @@
|
||||
#include "Hal.h"
|
||||
#include "AndroidBridge.h"
|
||||
|
||||
using mozilla::hal::WindowIdentifier;
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal_impl {
|
||||
|
||||
void
|
||||
Vibrate(const nsTArray<uint32>& pattern)
|
||||
{}
|
||||
Vibrate(const nsTArray<uint32> &pattern, const WindowIdentifier &)
|
||||
{
|
||||
// Ignore the WindowIdentifier parameter; it's here only because hal::Vibrate,
|
||||
// hal_sandbox::Vibrate, and hal_impl::Vibrate all must have the same
|
||||
// signature.
|
||||
|
||||
AndroidBridge* b = AndroidBridge::Bridge();
|
||||
if (!b) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pattern.Length() == 0) {
|
||||
b->CancelVibrate();
|
||||
} else {
|
||||
b->Vibrate(pattern);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CancelVibrate(const WindowIdentifier &)
|
||||
{
|
||||
// Ignore WindowIdentifier parameter.
|
||||
|
||||
AndroidBridge* b = AndroidBridge::Bridge();
|
||||
if (b)
|
||||
b->CancelVibrate();
|
||||
}
|
||||
|
||||
void
|
||||
EnableBatteryNotifications()
|
||||
|
@ -40,11 +40,17 @@
|
||||
#include "Hal.h"
|
||||
#include "mozilla/dom/battery/Constants.h"
|
||||
|
||||
using mozilla::hal::WindowIdentifier;
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal_impl {
|
||||
|
||||
void
|
||||
Vibrate(const nsTArray<uint32>& pattern)
|
||||
Vibrate(const nsTArray<uint32>& pattern, const hal::WindowIdentifier &)
|
||||
{}
|
||||
|
||||
void
|
||||
CancelVibrate(const hal::WindowIdentifier &)
|
||||
{}
|
||||
|
||||
void
|
||||
|
@ -45,7 +45,11 @@ namespace mozilla {
|
||||
namespace hal_impl {
|
||||
|
||||
void
|
||||
Vibrate(const nsTArray<uint32>& pattern)
|
||||
Vibrate(const nsTArray<uint32>& pattern, const hal::WindowIdentifier &)
|
||||
{}
|
||||
|
||||
void
|
||||
CancelVibrate(const hal::WindowIdentifier &)
|
||||
{}
|
||||
|
||||
#ifndef MOZ_ENABLE_DBUS
|
||||
|
@ -38,6 +38,7 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
include protocol PContent;
|
||||
include protocol PBrowser;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -57,7 +58,8 @@ child:
|
||||
NotifyBatteryChange(BatteryInformation aBatteryInfo);
|
||||
|
||||
parent:
|
||||
Vibrate(uint32[] pattern);
|
||||
Vibrate(uint32[] pattern, uint64[] id, PBrowser browser);
|
||||
CancelVibrate(uint64[] id, PBrowser browser);
|
||||
|
||||
EnableBatteryNotifications();
|
||||
DisableBatteryNotifications();
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/hal_sandbox/PHalChild.h"
|
||||
#include "mozilla/hal_sandbox/PHalParent.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "mozilla/dom/battery/Types.h"
|
||||
#include "mozilla/Observer.h"
|
||||
#include "mozilla/unused.h"
|
||||
@ -63,10 +65,25 @@ Hal()
|
||||
}
|
||||
|
||||
void
|
||||
Vibrate(const nsTArray<uint32>& pattern)
|
||||
Vibrate(const nsTArray<uint32>& pattern, const WindowIdentifier &id)
|
||||
{
|
||||
HAL_LOG(("Vibrate: Sending to parent process."));
|
||||
|
||||
AutoInfallibleTArray<uint32, 8> p(pattern);
|
||||
Hal()->SendVibrate(p);
|
||||
|
||||
WindowIdentifier newID(id);
|
||||
newID.AppendProcessID();
|
||||
Hal()->SendVibrate(p, newID.AsArray(), GetTabChildFrom(newID.GetWindow()));
|
||||
}
|
||||
|
||||
void
|
||||
CancelVibrate(const WindowIdentifier &id)
|
||||
{
|
||||
HAL_LOG(("CancelVibrate: Sending to parent process."));
|
||||
|
||||
WindowIdentifier newID(id);
|
||||
newID.AppendProcessID();
|
||||
Hal()->SendCancelVibrate(newID.AsArray(), GetTabChildFrom(newID.GetWindow()));
|
||||
}
|
||||
|
||||
void
|
||||
@ -91,11 +108,41 @@ class HalParent : public PHalParent
|
||||
, public BatteryObserver {
|
||||
public:
|
||||
NS_OVERRIDE virtual bool
|
||||
RecvVibrate(const InfallibleTArray<unsigned int>& pattern) {
|
||||
RecvVibrate(const InfallibleTArray<unsigned int>& pattern,
|
||||
const InfallibleTArray<uint64> &id,
|
||||
PBrowserParent *browserParent)
|
||||
{
|
||||
// Check whether browserParent is active. We should have already
|
||||
// checked that the corresponding window is active, but this check
|
||||
// isn't redundant. A window may be inactive in an active
|
||||
// browser. And a window is not notified synchronously when it's
|
||||
// deactivated, so the window may think it's active when the tab
|
||||
// is actually inactive.
|
||||
TabParent *tabParent = static_cast<TabParent*>(browserParent);
|
||||
if (!tabParent->Active()) {
|
||||
HAL_LOG(("RecvVibrate: Tab is not active. Cancelling."));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Forward to hal::, not hal_impl::, because we might be a
|
||||
// subprocess of another sandboxed process. The hal:: entry point
|
||||
// will do the right thing.
|
||||
hal::Vibrate(pattern);
|
||||
nsCOMPtr<nsIDOMWindow> window =
|
||||
do_QueryInterface(tabParent->GetBrowserDOMWindow());
|
||||
WindowIdentifier newID(id, window);
|
||||
hal::Vibrate(pattern, newID);
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_OVERRIDE virtual bool
|
||||
RecvCancelVibrate(const InfallibleTArray<uint64> &id,
|
||||
PBrowserParent *browserParent)
|
||||
{
|
||||
TabParent *tabParent = static_cast<TabParent*>(browserParent);
|
||||
nsCOMPtr<nsIDOMWindow> window =
|
||||
do_QueryInterface(tabParent->GetBrowserDOMWindow());
|
||||
WindowIdentifier newID(id, window);
|
||||
hal::CancelVibrate(newID);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -141,6 +141,9 @@ AndroidBridge::Init(JNIEnv *jEnv,
|
||||
jShowInputMethodPicker = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showInputMethodPicker", "()V");
|
||||
jHideProgressDialog = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "hideProgressDialog", "()V");
|
||||
jPerformHapticFeedback = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "performHapticFeedback", "(Z)V");
|
||||
jVibrate1 = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "vibrate", "(J)V");
|
||||
jVibrateA = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "vibrate", "([JI)V");
|
||||
jCancelVibrate = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "cancelVibrate", "()V");
|
||||
jSetKeepScreenOn = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setKeepScreenOn", "(Z)V");
|
||||
jIsNetworkLinkUp = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "isNetworkLinkUp", "()Z");
|
||||
jIsNetworkLinkKnown = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "isNetworkLinkKnown", "()Z");
|
||||
@ -436,9 +439,9 @@ AndroidBridge::GetHandlersForMimeType(const char *aMimeType,
|
||||
|
||||
bool
|
||||
AndroidBridge::GetHandlersForURL(const char *aURL,
|
||||
nsIMutableArray* aHandlersArray,
|
||||
nsIHandlerApp **aDefaultApp,
|
||||
const nsAString& aAction)
|
||||
nsIMutableArray* aHandlersArray,
|
||||
nsIHandlerApp **aDefaultApp,
|
||||
const nsAString& aAction)
|
||||
{
|
||||
ALOG_BRIDGE("AndroidBridge::GetHandlersForURL");
|
||||
|
||||
@ -676,6 +679,62 @@ AndroidBridge::PerformHapticFeedback(bool aIsLongPress)
|
||||
jPerformHapticFeedback, aIsLongPress);
|
||||
}
|
||||
|
||||
void
|
||||
AndroidBridge::Vibrate(const nsTArray<PRUint32>& aPattern)
|
||||
{
|
||||
ALOG_BRIDGE("AndroidBridge::Vibrate");
|
||||
|
||||
PRUint32 len = aPattern.Length();
|
||||
if (!len) {
|
||||
ALOG_BRIDGE(" invalid 0-length array");
|
||||
return;
|
||||
}
|
||||
|
||||
// It's clear if this worth special-casing, but it creates less
|
||||
// java junk, so dodges the GC.
|
||||
if (len == 1) {
|
||||
jlong d = aPattern[0];
|
||||
if (d < 0) {
|
||||
ALOG_BRIDGE(" invalid vibration duration < 0");
|
||||
return;
|
||||
}
|
||||
mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jVibrate1, d);
|
||||
return;
|
||||
}
|
||||
|
||||
// First element of the array vibrate() expects is how long to wait
|
||||
// *before* vibrating. For us, this is always 0.
|
||||
|
||||
jlongArray array = mJNIEnv->NewLongArray(len + 1);
|
||||
if (!array) {
|
||||
ALOG_BRIDGE(" failed to allocate array");
|
||||
return;
|
||||
}
|
||||
|
||||
jlong* elts = mJNIEnv->GetLongArrayElements(array, nsnull);
|
||||
elts[0] = 0;
|
||||
for (PRUint32 i = 0; i < aPattern.Length(); ++i) {
|
||||
jlong d = aPattern[i];
|
||||
if (d < 0) {
|
||||
ALOG_BRIDGE(" invalid vibration duration < 0");
|
||||
mJNIEnv->ReleaseLongArrayElements(array, elts, JNI_ABORT);
|
||||
return;
|
||||
}
|
||||
elts[i + 1] = d;
|
||||
}
|
||||
mJNIEnv->ReleaseLongArrayElements(array, elts, 0);
|
||||
|
||||
mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jVibrateA,
|
||||
array, -1/*don't repeat*/);
|
||||
// GC owns |array| now?
|
||||
}
|
||||
|
||||
void
|
||||
AndroidBridge::CancelVibrate()
|
||||
{
|
||||
mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jCancelVibrate);
|
||||
}
|
||||
|
||||
bool
|
||||
AndroidBridge::IsNetworkLinkUp()
|
||||
{
|
||||
|
@ -199,6 +199,9 @@ public:
|
||||
|
||||
void PerformHapticFeedback(bool aIsLongPress);
|
||||
|
||||
void Vibrate(const nsTArray<PRUint32>& aPattern);
|
||||
void CancelVibrate();
|
||||
|
||||
void SetFullScreen(bool aFullScreen);
|
||||
|
||||
void ShowInputMethodPicker();
|
||||
@ -355,6 +358,9 @@ protected:
|
||||
jmethodID jShowInputMethodPicker;
|
||||
jmethodID jHideProgressDialog;
|
||||
jmethodID jPerformHapticFeedback;
|
||||
jmethodID jVibrate1;
|
||||
jmethodID jVibrateA;
|
||||
jmethodID jCancelVibrate;
|
||||
jmethodID jSetKeepScreenOn;
|
||||
jmethodID jIsNetworkLinkUp;
|
||||
jmethodID jIsNetworkLinkKnown;
|
||||
|
Loading…
x
Reference in New Issue
Block a user