1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef DEVICE_BLUETOOTH_BLUETOOTH_DISCOVERY_SESSION_H_
6 #define DEVICE_BLUETOOTH_BLUETOOTH_DISCOVERY_SESSION_H_
7 
8 #include <memory>
9 
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/macros.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/weak_ptr.h"
15 #include "device/bluetooth/bluetooth_adapter.h"
16 #include "device/bluetooth/bluetooth_discovery_filter.h"
17 #include "device/bluetooth/bluetooth_discovery_session_outcome.h"
18 #include "device/bluetooth/bluetooth_export.h"
19 
20 namespace device {
21 
22 // BluetoothDiscoverySession represents a current active or inactive device
23 // discovery session. Instances of this class are obtained by calling
24 // BluetoothAdapter::StartDiscoverySession. The Bluetooth adapter will be
25 // constantly searching for nearby devices, as long as at least one instance
26 // of an active BluetoothDiscoverySession exists. A BluetoothDiscoverySession is
27 // considered active, as long as the adapter is discovering AND the owner of the
28 // instance has not called BluetoothDiscoverySession::Stop. A
29 // BluetoothDiscoverySession might unexpectedly become inactive, if the adapter
30 // unexpectedly stops discovery. Users can implement the
31 // AdapterDiscoveringChanged method of the BluetoothAdapter::Observer interface
32 // to be notified of such a change and promptly request a new
33 // BluetoothDiscoverySession if their existing sessions have become inactive.
34 class DEVICE_BLUETOOTH_EXPORT BluetoothDiscoverySession {
35  public:
36   // The ErrorCallback is used by methods to asynchronously report errors.
37   typedef base::Closure ErrorCallback;
38 
39   enum SessionStatus {
40     // Just added to the adapter.
41     PENDING_START,
42     // Request sent to OS.
43     STARTING,
44     // Actively scanning.
45     SCANNING,
46     // Finished scanning, should be deleted soon.
47     INACTIVE
48   };
49 
50   // Destructor automatically terminates the discovery session. If this
51   // results in a call to the underlying system to stop device discovery
52   // (i.e. this instance represents the last active discovery session),
53   // the call may not always succeed. To be notified of such failures,
54   // users are highly encouraged to call BluetoothDiscoverySession::Stop,
55   // instead of relying on the destructor.
56   virtual ~BluetoothDiscoverySession();
57 
58   // Returns true if the session is active, false otherwise. If false, the
59   // adapter might still be discovering as there might still be other active
60   // sessions; this just means that this instance no longer has a say in
61   // whether or not discovery should continue. In this case, the application
62   // should request a new BluetoothDiscoverySession to make sure that device
63   // discovery continues.
64   virtual bool IsActive() const;
65 
66   // Requests this discovery session instance to stop. If this instance is
67   // active, the session will stop. On success, |callback| is called and
68   // on error |error_callback| is called. After a successful invocation, the
69   // adapter may or may not stop device discovery, depending on whether or not
70   // other active discovery sessions are present. Users are highly encouraged
71   // to call this method to end a discovery session, instead of relying on the
72   // destructor, so that they can be notified of the result via the callback
73   // arguments.
74   virtual void Stop(base::Closure callback = base::DoNothing(),
75                     ErrorCallback error_callback = base::DoNothing());
76 
77   virtual const BluetoothDiscoveryFilter* GetDiscoveryFilter() const;
78 
status()79   SessionStatus status() const { return status_; }
80 
81   // Updates the status from PENDING_START to STARTING.
82   void PendingSessionsStarting();
83 
84   // Updates the status from STARTING to SCANNING.
85   void StartingSessionsScanning();
86 
87   base::WeakPtr<BluetoothDiscoverySession> GetWeakPtr();
88 
89  protected:
90   explicit BluetoothDiscoverySession(
91       scoped_refptr<BluetoothAdapter> adapter,
92       std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter);
93 
94  private:
95   friend class BluetoothAdapter;
96 
97   // Internal callback invoked when a call to
98   // BluetoothAdapter::RemoveDiscoverySession has succeeded. Invokes
99   // |deactivate_discovery_session| if the session object still
100   // exists when this callback executes. Always invokes |success_callback|.
101   static void OnDiscoverySessionRemoved(
102       base::WeakPtr<BluetoothDiscoverySession> session,
103       const base::Closure& deactivate_discovery_session,
104       const base::Closure& success_callback);
105 
106   static void OnDiscoverySessionRemovalFailed(
107       base::WeakPtr<BluetoothDiscoverySession> session,
108       const base::Closure& error_callback,
109       UMABluetoothDiscoverySessionOutcome outcome);
110 
111   // Deactivate discovery session object after
112   // BluetoothAdapter::RemoveDiscoverySession completes.
113   void DeactivateDiscoverySession();
114 
115   // Marks this instance as inactive. Called by BluetoothAdapter to mark a
116   // session as inactive in the case of an unexpected change to the adapter
117   // discovery state.
118   void MarkAsInactive();
119 
120   // Indicates the state of this session.
121   SessionStatus status_;
122 
123   // Whether a Stop() operation is in progress for this session.
124   bool is_stop_in_progress_;
125 
126   // The adapter that created this instance.
127   scoped_refptr<BluetoothAdapter> adapter_;
128 
129   // Filter assigned to this session, if any
130   std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter_;
131 
132   // Note: This should remain the last member so it'll be destroyed and
133   // invalidate its weak pointers before any other members are destroyed.
134   base::WeakPtrFactory<BluetoothDiscoverySession> weak_ptr_factory_{this};
135 
136   DISALLOW_COPY_AND_ASSIGN(BluetoothDiscoverySession);
137 };
138 
139 }  // namespace device
140 
141 #endif  // DEVICE_BLUETOOTH_BLUETOOTH_DISCOVERY_SESSION_H_
142