Merge "Remove one log message from the VPXDecoder"
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 94a20dc..dfc4f7b 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -276,6 +276,10 @@
<li><a href="<?cs var:toroot?>guide/topics/wireless/bluetooth.html">
<span class="en">Bluetooth</span>
</a></li>
+ <li><a href="<?cs var:toroot?>guide/topics/network/sip.html">
+ <span class="en">Session Initiation Protocol</span></a>
+ <span class="new">new!</span>
+ </li>
<li class="toggle-list">
<div><a href="<?cs var:toroot?>guide/topics/search/index.html">
<span class="en">Search</span>
diff --git a/docs/html/guide/index.jd b/docs/html/guide/index.jd
index cedf0f5..38f71c0 100644
--- a/docs/html/guide/index.jd
+++ b/docs/html/guide/index.jd
@@ -73,8 +73,8 @@
tutorial walks you through a standard "Hello, World" application to introduce some basics of an
Android application. The
<a href="{@docRoot}guide/topics/fundamentals.html">Application
-Fundamentals</a> documentation is a good place to start for an
-understanding of the application framework.
+Fundamentals</a> document is a good place to start learning the basics about the application
+framework.
</p>
diff --git a/docs/html/guide/topics/network/sip.jd b/docs/html/guide/topics/network/sip.jd
new file mode 100644
index 0000000..276adb6
--- /dev/null
+++ b/docs/html/guide/topics/network/sip.jd
@@ -0,0 +1,490 @@
+page.title=Session Initiation Protocol
+@jd:body
+<div id="qv-wrapper">
+<div id="qv">
+ <h2>In this document</h2>
+ <ol>
+
+ <li><a href="#requirements">Requirements and Limitations</a></li>
+ <li><a href="#classes">Classes and Interfaces</a></li>
+ <li><a href="#manifest">Creating the Manifest</a></li>
+ <li><a href="#manager">Creating a SIP Manager</a></li>
+ <li><a href="#profiles">Registering with a SIP Server</a></li>
+ <li><a href="#audio">Making an Audio Call</a></li>
+ <li><a href="#receiving">Receiving Calls</a></li>
+ <li><a href="#testing">Testing SIP Applications</a></li>
+ </ol>
+
+ <h2>Key classes</h2>
+ <ol>
+ <li>{@link android.net.sip.SipManager}</li>
+ <li>{@link android.net.sip.SipProfile}</li>
+ <li>{@link android.net.sip.SipAudioCall}</li>
+
+ </ol>
+
+ <h2>Related samples</h2>
+ <ol>
+ <li> <a href="{@docRoot}resources/samples/SipDemo/index.html"> SipDemo</a></li>
+ </ol>
+ </div>
+</div>
+
+<p>Android provides an API that supports the Session Initiation Protocol (SIP).
+This lets you add SIP-based internet telephony features to your applications.
+Android includes a full SIP protocol stack and integrated call management
+services that let applications easily set up outgoing and incoming voice calls,
+without having to manage sessions, transport-level communication, or audio
+record or playback directly.</p>
+
+<p>Here are examples of the types of applications that might use the SIP API:</p>
+<ul>
+ <li>Video conferencing.</li>
+ <li>Instant messaging.</li>
+</ul>
+<h2 id="requirements">Requirements and Limitations</h2>
+<p>Here are the requirements for developing a SIP application:</p>
+<ul>
+
+ <li>You must have a mobile device that is running Android 2.3 or higher. </li>
+
+ <li>SIP runs over a wireless data connection, so your device must have a data
+connection (with a mobile data service or Wi-Fi)</span>. This means that you
+can't test on AVD—you can only test on a physical device. For details, see
+<a href="#testing">Testing SIP Applications</a>.</li>
+
+ <li>Each participant in the application's communication session must have a
+SIP account. There are many different SIP providers that offer SIP accounts.</li>
+</ul>
+
+
+<h2 id="classes">SIP API Classes and Interfaces</h2>
+
+<p>Here is a summary of the classes and one interface
+(<code>SipRegistrationListener</code>) that are included in the Android SIP
+API:</p>
+
+<table>
+ <thead>
+ <tr>
+ <th>Class/Interface</th>
+ <th>Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>{@link android.net.sip.SipAudioCall}</td>
+ <td>Handles an Internet audio call over SIP.</td>
+ </tr>
+ <tr>
+ <td>{@link android.net.sip.SipAudioCall.Listener}</td>
+ <td>Listener for events relating to a SIP call, such as when a call is being
+received ("on ringing") or a call is outgoing ("on calling").</td>
+ </tr>
+ <tr>
+ <td>{@link android.net.sip.SipErrorCode}</td>
+ <td>Defines error codes returned during SIP actions.</td>
+ </tr>
+ <tr>
+ <td>{@link android.net.sip.SipManager}</td>
+ <td>Provides APIs for SIP tasks, such as initiating SIP connections, and provides access
+to related SIP services.</td>
+ </tr>
+ <tr>
+ <td>{@link android.net.sip.SipProfile}</td>
+ <td>Defines a SIP profile, including a SIP account, domain and server information.
+</td>
+ </tr>
+ <tr>
+ <td>{@link android.net.sip.SipProfile.Builder}</td>
+ <td>Helper class for creating a SipProfile.</td>
+ </tr>
+ <tr>
+ <td>{@link android.net.sip.SipSession}</td>
+ <td>Represents a SIP session that is associated with a SIP dialog or a standalone transaction
+not within a dialog.</td>
+ </tr>
+ <tr>
+ <td>{@link android.net.sip.SipSession.Listener}</td>
+ <td>Listener for events relating to a SIP session, such as when a session is being registered
+("on registering") or a call is outgoing ("on calling"). </td>
+ </tr>
+ <tr>
+ <td>{@link android.net.sip.SipSession.State}</td>
+ <td>Defines SIP session states, such as "registering", "outgoing call", and "in call". </td>
+ </tr>
+ <tr>
+ <td>{@link android.net.sip.SipRegistrationListener}</td>
+ <td>An interface that is a listener for SIP registration events.</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="manifest">Creating the Manifest</h2>
+
+<p>If you are developing an application that uses the SIP API, remember that the
+feature is supported only on Android 2.3 (API level 9) and higher versions of
+the platform. Also, among devices running Android 2.3 (API level 9) or higher,
+not all devices will offer SIP support.</p>
+
+<p>To use SIP, add the following permissions to your application's manifest:</p>
+<ul>
+ <li><code>android.permission.USE_SIP</code></li>
+ <li><code>android.permission.INTERNET</code></li>
+</ul>
+
+<p> To ensure that your application can only be installed on devices that are
+capable of supporting SIP, add the following to your application's
+manifest:</p>
+
+<ul>
+ <li><code><uses-sdk android:minSdkVersion="9" /></code>. This
+ indicates that your application requires Android 2.3 or higher. For more
+information, see <a href="{@docRoot}guide/appendix/api-levels.html">API
+Levels</a> and the documentation for the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><uses-sdk></a
+> element.</li>
+</ul>
+
+<p>To control how your application is filtered from devices that do not support
+SIP (for example, in Android Market), add the following to your application's
+manifest:</p>
+
+<ul>
+
+ <li><code><uses-feature android:name="android.hardware.sip.voip"
+/></code>. This states that your application uses the SIP API. The
+declaration should include an <code>android:required</code> attribute that
+indicates whether you want the application to be filtered from devices that do
+not offer SIP support. Other <code><uses-feature></code> declarations
+may also be needed, depending on your implementation. For more information,
+see the documentation for the <a
+href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses-
+feature></a> element.</li>
+
+</ul>
+<p>If your application is designed to receive calls, you must also define a receiver ({@link android.content.BroadcastReceiver} subclass) in the application's manifest: </p>
+
+<ul>
+ <li><code><receiver android:name=".IncomingCallReceiver" android:label="Call Receiver"/></code></li>
+</ul>
+<p>Here are excerpts from the <strong>SipDemo</strong> manifest:</p>
+
+
+
+<pre><?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.sip">
+ ...
+ <receiver android:name=".IncomingCallReceiver" android:label="Call Receiver"/>
+ ...
+ <uses-sdk android:minSdkVersion="9" />
+ <uses-permission android:name="android.permission.USE_SIP" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ ...
+ <uses-feature android:name="android.hardware.sip.voip" android:required="true" />
+ <uses-feature android:name="android.hardware.wifi" android:required="true" />
+ <uses-feature android:name="android.hardware.microphone" android:required="true" />
+</manifest>
+</pre>
+
+
+<h2 id="manager">Creating a SipManager</h2>
+
+<p>To use the SIP API, your application must create a {@link
+android.net.sip.SipManager} object. The {@link android.net.sip.SipManager} takes
+care of the following in your application:</p>
+
+<ul>
+ <li>Initiating SIP sessions.</li>
+ <li>Initiating and receiving calls.</li>
+ <li>Registering and unregistering with a SIP provider.</li>
+ <li>Verifying session connectivity.</li>
+</ul>
+<p>You instantiate a new {@link android.net.sip.SipManager} as follows:</p>
+<pre>public SipManager mSipManager = null;
+...
+if(mSipManager == null) {
+ mSipManager = SipManager.newInstance(this);
+}</pre>
+<h2 id="profiles">Registering with a SIP Server</h2>
+
+<p>A typical Android SIP application involves one or more users, each of whom
+has a SIP account. In an Android SIP application, each SIP account is
+represented by a {@link android.net.sip.SipProfile} object.</p>
+
+<p>A {@link android.net.sip.SipProfile} defines a SIP profile, including a SIP
+account, and domain and server information. The profile associated with the SIP
+account on the device running the application is called the <em>local
+profile</em>. The profile that the session is connected to is called the
+<em>peer profile</em>. When your SIP application logs into the SIP server with
+the local {@link android.net.sip.SipProfile}, this effectively registers the
+device as the location to send SIP calls to for your SIP address.</p>
+
+<p>This section shows how to create a {@link android.net.sip.SipProfile},
+register it with a SIP server, and track registration events.</p>
+
+<p>You create a {@link android.net.sip.SipProfile} object as follows:</p>
+<pre>
+public SipProfile mSipProfile = null;
+...
+
+SipProfile.Builder builder = new SipProfile.Builder(username, domain);
+builder.setPassword(password);
+mSipProfile = builder.build();</pre>
+
+<p>The following code excerpt opens the local profile for making calls and/or
+receiving generic SIP calls. The caller can make subsequent calls through
+<code>mSipManager.makeAudioCall</code>. This excerpt also sets the action
+<code>android.SipDemo.INCOMING_CALL</code>, which will be used by an intent
+filter when the device receives a call (see <a href="#intent_filter">Setting up
+an intent filter to receive calls</a>). This is the registration step:</p>
+
+<pre>Intent intent = new Intent();
+intent.setAction("android.SipDemo.INCOMING_CALL");
+PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA);
+mSipManager.open(mSipProfile, pendingIntent, null);</pre>
+
+<p>Finally, this code sets a <code>SipRegistrationListener</code> on the {@link
+android.net.sip.SipManager}. This tracks whether the {@link
+android.net.sip.SipProfile} was successfully registered with your SIP service
+provider:<br>
+</p>
+
+<pre>mSipManager.setRegistrationListener(mSipProfile.getUriString(), new SipRegistrationListener() {
+
+public void onRegistering(String localProfileUri) {
+ updateStatus("Registering with SIP Server...");
+}
+
+public void onRegistrationDone(String localProfileUri, long expiryTime) {
+ updateStatus("Ready");
+}
+
+public void onRegistrationFailed(String localProfileUri, int errorCode,
+ String errorMessage) {
+ updateStatus("Registration failed. Please check settings.");
+}</pre>
+
+
+<p>When your application is done using a profile, it should close it to free
+associated objects into memory and unregister the device from the server. For
+example:</p>
+
+<pre>public void closeLocalProfile() {
+ if (mSipManager == null) {
+ return;
+ }
+ try {
+ if (mSipProfile != null) {
+ mSipManager.close(mSipProfile.getUriString());
+ }
+ } catch (Exception ee) {
+ Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee);
+ }
+}</pre>
+
+<h2 id="audio">Making an Audio Call</h2>
+<p>To make an audio call, you must have the following in place:</p>
+<ul>
+
+ <li>A {@link android.net.sip.SipProfile} that is making the call (the
+"local profile"), and a valid SIP address to receive the call (the
+"peer profile").
+
+ <li>A {@link android.net.sip.SipManager} object. </li>
+</ul>
+
+<p>To make an audio call, you should set up a {@link
+android.net.sip.SipAudioCall.Listener}. Much of the client's interaction with
+the SIP stack happens through listeners. In this snippet, you see how the {@link
+android.net.sip.SipAudioCall.Listener} sets things up after the call is
+established:</p>
+
+<pre>
+SipAudioCall.Listener listener = new SipAudioCall.Listener() {
+
+ @Override
+ public void onCallEstablished(SipAudioCall call) {
+ call.startAudio();
+ call.setSpeakerMode(true);
+ call.toggleMute();
+ ...
+ }
+
+ @Override
+ public void onCallEnded(SipAudioCall call) {
+ // Do something.
+ }
+};</pre>
+
+<p>Once you've set up the {@link android.net.sip.SipAudioCall.Listener}, you can
+make the call. The {@link android.net.sip.SipManager} method
+<code>makeAudioCall</code> takes the following parameters:</p>
+
+<ul>
+ <li>A local SIP profile (the caller).</li>
+ <li>A peer SIP profile (the user being called).</li>
+
+ <li>A {@link android.net.sip.SipAudioCall.Listener} to listen to the call
+events from {@link android.net.sip.SipAudioCall}. This can be <code>null</code>,
+but as shown above, the listener is used to set things up once the call is
+established.</li>
+
+ <li>The timeout value, in seconds.</li>
+</ul>
+<p>For example:</p>
+<pre> call = mSipManager.makeAudioCall(mSipProfile.getUriString(), sipAddress, listener, 30);</pre>
+
+<h2 id="receiving">Receiving Calls</h2>
+
+<p>To receive calls, a SIP application must include a subclass of {@link
+android.content.BroadcastReceiver} that has the ability to respond to an intent
+indicating that there is an incoming call. Thus, you must do the following in
+your application:</p>
+
+<ul>
+ <li>In <code>AndroidManifest.xml</code>, declare a
+<code><receiver></code>. In <strong>SipDemo</strong>, this is
+<code><receiver android:name=".IncomingCallReceiver"
+android:label="Call Receiver"/></code>.</li>
+
+ <li>Implement the receiver, which is a subclass of {@link
+android.content.BroadcastReceiver}. In <strong>SipDemo</strong>, this is
+<code>IncomingCallReceiver</code>.</li>
+
+ <li>Initialize the local profile ({@link android.net.sip.SipProfile}) with a
+pending intent that fires your receiver when someone calls the local profile.
+</li>
+
+ <li>Set up an intent filter that filters by the action that represents an
+incoming call. In <strong>SipDemo</strong>, this action is
+<code>android.SipDemo.INCOMING_CALL</code>. </li>
+</ul>
+<h4 id="BroadcastReceiver">Subclassing BroadcastReceiver</h4>
+
+<p>To receive calls, your SIP application must subclass {@link
+android.content.BroadcastReceiver}. <span id="internal-source-marker_0.">The
+Android system handles incoming SIP calls and broadcasts an "incoming
+call"<code></code> intent (as defined by the application) when it receives
+a call.</span> Here is the subclassed {@link android.content.BroadcastReceiver}
+code from <strong>SipDemo</strong>. To see the full example, go to <a
+href="{@docRoot}resources/samples/SipDemo/index.html">SipDemo sample</a>, which
+is included in the SDK samples. For information on downloading and installing
+the SDK samples, see <a
+href="{@docRoot}resources/samples/get.html">
+Getting the Samples</a>. </p>
+
+<pre>/*** Listens for incoming SIP calls, intercepts and hands them off to WalkieTalkieActivity.
+ */
+public class IncomingCallReceiver extends BroadcastReceiver {
+ /**
+ * Processes the incoming call, answers it, and hands it over to the
+ * WalkieTalkieActivity.
+ * @param context The context under which the receiver is running.
+ * @param intent The intent being received.
+ */
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ SipAudioCall incomingCall = null;
+ try {
+ SipAudioCall.Listener listener = new SipAudioCall.Listener() {
+ @Override
+ public void onRinging(SipAudioCall call, SipProfile caller) {
+ try {
+ call.answerCall(30);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ WalkieTalkieActivity wtActivity = (WalkieTalkieActivity) context;
+ incomingCall = wtActivity.mSipManager.takeAudioCall(intent, listener);
+ incomingCall.answerCall(30);
+ incomingCall.startAudio();
+ incomingCall.setSpeakerMode(true);
+ if(incomingCall.isMuted()) {
+ incomingCall.toggleMute();
+ }
+ wtActivity.call = incomingCall;
+ wtActivity.updateStatus(incomingCall);
+ } catch (Exception e) {
+ if (incomingCall != null) {
+ incomingCall.close();
+ }
+ }
+ }
+}
+</pre>
+
+<h4 id="intent_filter">Setting up an intent filter to receive calls</h4>
+
+<p>When the SIP service receives a new call, it sends out an intent with the
+action string provided by the application. In SipDemo, this action string is
+<code>android.SipDemo.INCOMING_CALL</code>. </p>
+<p>This code excerpt from <strong>SipDemo</strong> shows how the {@link
+android.net.sip.SipProfile} object gets created with a pending intent based on
+the action string <code>android.SipDemo.INCOMING_CALL</code>. The
+<code>PendingIntent</code> object will perform a broadcast when the {@link
+android.net.sip.SipProfile} receives a call:</p>
+
+<pre>
+public SipManager mSipManager = null;
+public SipProfile mSipProfile = null;
+...
+
+Intent intent = new Intent();
+intent.setAction("android.SipDemo.INCOMING_CALL");
+PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA);
+mSipManager.open(mSipProfile, pendingIntent, null);</pre>
+
+<p>The broadcast will be intercepted by the intent filter, which will then fire
+the receiver (<code>IncomingCallReceiver</code>). You can specify an intent
+filter in your application's manifest file, or do it in code as in the <strong>SipDemo</strong>
+sample application's <code>onCreate()</code> method
+of the application's <code>Activity</code>:</p>
+
+<pre>
+public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {
+...
+ public IncomingCallReceiver callReceiver;
+ ...
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction("android.SipDemo.INCOMING_CALL");
+ callReceiver = new IncomingCallReceiver();
+ this.registerReceiver(callReceiver, filter);
+ ...
+ }
+ ...
+}
+</pre>
+
+
+<h2 id="testing">Testing SIP Applications</h2>
+
+<p>To test SIP applications, you need the following:</p>
+<ul>
+<li>A mobile device that is running Android 2.3 or higher. SIP runs over
+wireless, so you must test on an actual device. Testing on AVD won't work.</li>
+<li>A SIP account. There are many different SIP providers that offer SIP accounts.</li>
+<li>If you are placing a call, it must also be to a valid SIP account. </li>
+</ul>
+<p>To test a SIP application:</p>
+<ol>
+
+<li>On your device, connect to wireless (<strong>Settings > Wireless & networks
+> Wi-Fi > Wi-Fi settings</strong>)</li>
+<li>Set up your mobile device for testing, as described in <a
+href="{@docRoot}guide/developing/device.html">Developing on a Device</a>.</li>
+<li>Run your application on your mobile device, as described in <a
+href="{@docRoot}guide/developing/device.html">Developing on a Device</a>.</li>
+
+<li>If you are using Eclipse, you can view the application log output in Eclipse
+using LogCat (<strong>Window > Show View > Other > Android >
+LogCat</strong>).</li>
+</ol>
+
diff --git a/docs/html/sdk/1.6_r1/upgrading.jd b/docs/html/sdk/1.6_r1/upgrading.jd
index ebe6a95..49535c9 100644
--- a/docs/html/sdk/1.6_r1/upgrading.jd
+++ b/docs/html/sdk/1.6_r1/upgrading.jd
@@ -1,6 +1,5 @@
page.title=Upgrading the SDK
sdk.version=1.6
-sdk.preview=0
@jd:body
diff --git a/docs/html/sdk/android-3.0-highlights.jd b/docs/html/sdk/android-3.0-highlights.jd
index ed49307..0378c35 100644
--- a/docs/html/sdk/android-3.0-highlights.jd
+++ b/docs/html/sdk/android-3.0-highlights.jd
@@ -129,7 +129,7 @@
<p style="margin-top:1em;margin-bottom:.75em;"><strong>Camera and Gallery</strong></p>
-<p>The Camera application has been redesigned to take advantage of a larger screen for quick access to exposure, focus, flash, zoom, front-facing camera, and more. To let users capture scenes in new ways, it adds built-in support for time-lapse video recording. Gallery application lets users view albums and other collections in full-screen mode, with easy access to thumbnails for other photos in the collection. </p>
+<p>The Camera application has been redesigned to take advantage of a larger screen for quick access to exposure, focus, flash, zoom, front-facing camera, and more. To let users capture scenes in new ways, it adds built-in support for time-lapse video recording. The Gallery application lets users view albums and other collections in full-screen mode, with easy access to thumbnails for other photos in the collection. </p>
<p style="margin-top:1em;margin-bottom:.75em;"><strong>Contacts</strong></p>
diff --git a/docs/html/sdk/ndk/index.jd b/docs/html/sdk/ndk/index.jd
index 2c3fd6a..2f53305 100644
--- a/docs/html/sdk/ndk/index.jd
+++ b/docs/html/sdk/ndk/index.jd
@@ -1,16 +1,16 @@
ndk=true
-ndk.win_download=android-ndk-r5-windows.zip
-ndk.win_bytes=62217450
-ndk.win_checksum=59cbb02d91d74e9c5c7278d94c989e80
+ndk.win_download=android-ndk-r5b-windows.zip
+ndk.win_bytes=61299831
+ndk.win_checksum=87745ada305ab639399161ab4faf684c
-ndk.mac_download=android-ndk-r5-darwin-x86.tar.bz2
+ndk.mac_download=android-ndk-r5b-darwin-x86.tar.bz2
ndk.mac_bytes=50210863
-ndk.mac_checksum=9dee8e4cb529a5619e9b8d1707478c32
+ndk.mac_checksum=019a14622a377b3727ec789af6707037
-ndk.linux_download=android-ndk-r5-linux-x86.tar.bz2
-ndk.linux_bytes=44362746
-ndk.linux_checksum=49d5c35ec02bafc074842542c58b7eb3
+ndk.linux_download=android-ndk-r5b-linux-x86.tar.bz2
+ndk.linux_bytes=44138539
+ndk.linux_checksum=4c0045ddc2bfd657be9d5177d0e0b7e7
page.title=Android NDK
@jd:body
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index d4f1733..f95e56a 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -75,7 +75,7 @@
static void RegisterDefaultSniffers();
// for DRM
- virtual DecryptHandle* DrmInitialization(DrmManagerClient *client) {
+ virtual DecryptHandle* DrmInitialization() {
return NULL;
}
virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {};
diff --git a/include/media/stagefright/FileSource.h b/include/media/stagefright/FileSource.h
index 72a0403..51a4343 100644
--- a/include/media/stagefright/FileSource.h
+++ b/include/media/stagefright/FileSource.h
@@ -38,7 +38,7 @@
virtual status_t getSize(off64_t *size);
- virtual DecryptHandle* DrmInitialization(DrmManagerClient *client);
+ virtual DecryptHandle* DrmInitialization();
virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 99a047a..5a43c6a 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -392,7 +392,6 @@
if (mDecryptHandle != NULL) {
mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
Playback::STOP, 0);
- mDrmManagerClient->closeDecryptSession(mDecryptHandle);
mDecryptHandle = NULL;
mDrmManagerClient = NULL;
}
diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp
index 3c98932..4b83568 100644
--- a/media/libstagefright/DRMExtractor.cpp
+++ b/media/libstagefright/DRMExtractor.cpp
@@ -38,12 +38,12 @@
namespace android {
-DrmManagerClient* gDrmManagerClient = NULL;
-
class DRMSource : public MediaSource {
public:
DRMSource(const sp<MediaSource> &mediaSource,
- DecryptHandle* decryptHandle, int32_t trackId, DrmBuffer* ipmpBox);
+ DecryptHandle *decryptHandle,
+ DrmManagerClient *managerClient,
+ int32_t trackId, DrmBuffer *ipmpBox);
virtual status_t start(MetaData *params = NULL);
virtual status_t stop();
@@ -57,6 +57,7 @@
private:
sp<MediaSource> mOriginalMediaSource;
DecryptHandle* mDecryptHandle;
+ DrmManagerClient* mDrmManagerClient;
size_t mTrackId;
mutable Mutex mDRMLock;
size_t mNALLengthSize;
@@ -69,13 +70,16 @@
////////////////////////////////////////////////////////////////////////////////
DRMSource::DRMSource(const sp<MediaSource> &mediaSource,
- DecryptHandle* decryptHandle, int32_t trackId, DrmBuffer* ipmpBox)
+ DecryptHandle *decryptHandle,
+ DrmManagerClient *managerClient,
+ int32_t trackId, DrmBuffer *ipmpBox)
: mOriginalMediaSource(mediaSource),
mDecryptHandle(decryptHandle),
+ mDrmManagerClient(managerClient),
mTrackId(trackId),
mNALLengthSize(0),
mWantsNALFragments(false) {
- gDrmManagerClient->initializeDecryptUnit(
+ mDrmManagerClient->initializeDecryptUnit(
mDecryptHandle, trackId, ipmpBox);
const char *mime;
@@ -100,7 +104,7 @@
DRMSource::~DRMSource() {
Mutex::Autolock autoLock(mDRMLock);
- gDrmManagerClient->finalizeDecryptUnit(mDecryptHandle, mTrackId);
+ mDrmManagerClient->finalizeDecryptUnit(mDecryptHandle, mTrackId);
}
status_t DRMSource::start(MetaData *params) {
@@ -140,7 +144,7 @@
decryptedDrmBuffer.data = new char[len];
DrmBuffer *pDecryptedDrmBuffer = &decryptedDrmBuffer;
- if ((err = gDrmManagerClient->decrypt(mDecryptHandle, mTrackId,
+ if ((err = mDrmManagerClient->decrypt(mDecryptHandle, mTrackId,
&encryptedDrmBuffer, &pDecryptedDrmBuffer)) != DRM_NO_ERROR) {
if (decryptedDrmBuffer.data) {
@@ -234,12 +238,12 @@
DRMExtractor::DRMExtractor(const sp<DataSource> &source, const char* mime)
: mDataSource(source),
- mDecryptHandle(NULL) {
+ mDecryptHandle(NULL),
+ mDrmManagerClient(NULL) {
mOriginalExtractor = MediaExtractor::Create(source, mime);
mOriginalExtractor->setDrmFlag(true);
- DrmManagerClient *client;
- source->getDrmInfo(&mDecryptHandle, &client);
+ source->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
}
DRMExtractor::~DRMExtractor() {
@@ -260,7 +264,8 @@
ipmpBox.data = mOriginalExtractor->getDrmTrackInfo(trackID, &(ipmpBox.length));
CHECK(ipmpBox.length > 0);
- return new DRMSource(originalMediaSource, mDecryptHandle, trackID, &ipmpBox);
+ return new DRMSource(originalMediaSource, mDecryptHandle, mDrmManagerClient,
+ trackID, &ipmpBox);
}
sp<MetaData> DRMExtractor::getTrackMetaData(size_t index, uint32_t flags) {
@@ -271,22 +276,10 @@
return mOriginalExtractor->getMetaData();
}
-static Mutex gDRMSnifferMutex;
bool SniffDRM(
const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
- {
- Mutex::Autolock autoLock(gDRMSnifferMutex);
- if (gDrmManagerClient == NULL) {
- gDrmManagerClient = new DrmManagerClient();
- }
-
- if (gDrmManagerClient == NULL) {
- return false;
- }
- }
-
- DecryptHandle *decryptHandle = source->DrmInitialization(gDrmManagerClient);
+ DecryptHandle *decryptHandle = source->DrmInitialization();
if (decryptHandle != NULL) {
if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) {
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index 98d5b50..b8e75fd 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -60,6 +60,17 @@
delete[] mDrmBuf;
mDrmBuf = NULL;
}
+
+ if (mDecryptHandle != NULL) {
+ // To release mDecryptHandle
+ mDrmManagerClient->closeDecryptSession(mDecryptHandle);
+ mDecryptHandle = NULL;
+ }
+
+ if (mDrmManagerClient != NULL) {
+ delete mDrmManagerClient;
+ mDrmManagerClient = NULL;
+ }
}
status_t FileSource::initCheck() const {
@@ -113,11 +124,14 @@
return OK;
}
-DecryptHandle* FileSource::DrmInitialization(DrmManagerClient* client) {
- if (client == NULL) {
+DecryptHandle* FileSource::DrmInitialization() {
+ if (mDrmManagerClient == NULL) {
+ mDrmManagerClient = new DrmManagerClient();
+ }
+
+ if (mDrmManagerClient == NULL) {
return NULL;
}
- mDrmManagerClient = client;
if (mDecryptHandle == NULL) {
mDecryptHandle = mDrmManagerClient->openDecryptSession(
@@ -125,6 +139,7 @@
}
if (mDecryptHandle == NULL) {
+ delete mDrmManagerClient;
mDrmManagerClient = NULL;
}
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 741aa1c..c7b99b9 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -477,8 +477,8 @@
restartPrefetcherIfNecessary_l(true /* ignore low water threshold */);
}
-DecryptHandle* NuCachedSource2::DrmInitialization(DrmManagerClient* client) {
- return mSource->DrmInitialization(client);
+DecryptHandle* NuCachedSource2::DrmInitialization() {
+ return mSource->DrmInitialization();
}
void NuCachedSource2::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index 653c85e..af04f93 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -79,6 +79,16 @@
}
NuHTTPDataSource::~NuHTTPDataSource() {
+ if (mDecryptHandle != NULL) {
+ // To release mDecryptHandle
+ mDrmManagerClient->closeDecryptSession(mDecryptHandle);
+ mDecryptHandle = NULL;
+ }
+
+ if (mDrmManagerClient != NULL) {
+ delete mDrmManagerClient;
+ mDrmManagerClient = NULL;
+ }
}
status_t NuHTTPDataSource::connect(
@@ -486,11 +496,14 @@
}
}
-DecryptHandle* NuHTTPDataSource::DrmInitialization(DrmManagerClient* client) {
- if (client == NULL) {
+DecryptHandle* NuHTTPDataSource::DrmInitialization() {
+ if (mDrmManagerClient == NULL) {
+ mDrmManagerClient = new DrmManagerClient();
+ }
+
+ if (mDrmManagerClient == NULL) {
return NULL;
}
- mDrmManagerClient = client;
if (mDecryptHandle == NULL) {
/* Note if redirect occurs, mUri is the redirect uri instead of the
@@ -500,6 +513,7 @@
}
if (mDecryptHandle == NULL) {
+ delete mDrmManagerClient;
mDrmManagerClient = NULL;
}
diff --git a/media/libstagefright/include/DRMExtractor.h b/media/libstagefright/include/DRMExtractor.h
index cafc812..9881cc1 100644
--- a/media/libstagefright/include/DRMExtractor.h
+++ b/media/libstagefright/include/DRMExtractor.h
@@ -46,6 +46,7 @@
sp<MediaExtractor> mOriginalExtractor;
DecryptHandle* mDecryptHandle;
+ DrmManagerClient* mDrmManagerClient;
DRMExtractor(const DRMExtractor &);
DRMExtractor &operator=(const DRMExtractor &);
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 28840be..022804c 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -37,7 +37,7 @@
virtual status_t getSize(off64_t *size);
virtual uint32_t flags();
- virtual DecryptHandle* DrmInitialization(DrmManagerClient *client);
+ virtual DecryptHandle* DrmInitialization();
virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client);
virtual String8 getUri();
////////////////////////////////////////////////////////////////////////////
diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h
index c8e93be..a99e84a 100644
--- a/media/libstagefright/include/NuHTTPDataSource.h
+++ b/media/libstagefright/include/NuHTTPDataSource.h
@@ -31,7 +31,7 @@
// false otherwise.
bool estimateBandwidth(int32_t *bandwidth_bps);
- virtual DecryptHandle* DrmInitialization(DrmManagerClient *client);
+ virtual DecryptHandle* DrmInitialization();
virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client);
virtual String8 getUri();
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 25030d8..8ec1fd4 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -878,7 +878,8 @@
InstrumentedInputReader(const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputDispatcherInterface>& dispatcher) :
- InputReader(eventHub, policy, dispatcher) {
+ InputReader(eventHub, policy, dispatcher),
+ mNextDevice(NULL) {
}
virtual ~InstrumentedInputReader() {