俺のAndroid端末がWidevine L3化されちゃった事件とその回避策

## はじめに
本記事では2020年のとあるタイミングで動画配信サービス界隈で発生してしまった
Widevine DRMに関するトラブル( **Widevine L3化されちゃった？事件** )と対処について解説します

※図と本文に誤記があったので微修正しました(2020/12/22)

## 自己紹介
ドコモでdTVやdアニメストア等の映像配信サービスの開発を担当してる岡田です。
主にDRM関連、プレイヤーSDKの開発を担当しています。

## Widevine L3化されちゃった？事件とは
これは私が勝手に呼んでるだけですが、、
2020年のとあるタイミングを境にAndroidの特定のデバイス（Nexusのあのモデルとか、あのデバイスとか）を使っている人で、
動画配信サービスが突然全く視聴できなくなる事象が発生しました。

もし該当のAndroidデバイスをお使いの方は、
このアプリで動画が全く視聴できなくなった（イライラ
という経験をされた方がいらっしゃったかなと思います。

実際に弊社サービスでも、動画視聴するとこんなエラー画面がでてしまい、
再起動してもアプリをアンインストールしても復帰することができませんでした。

こちらは我々が使っている開発/評価用のアプリのスクショですが、
メッセージ見てもUNKNOWNエラーな上にライセンスの取得に失敗したとあるだけで、
ユーザーが次にどうすることもできず、俗にいうイケてないパターンです。

![Error-2023.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877384/00b1ee95-2dbc-b0b7-7715-2b0f7da47b29.png)


動画配信サービスを利用してると、
デバイスの状態などによってまれにエラーが発生することはあるのですが、
この事件のときはWidevine DRMというGoogleが提供する著作権保護の仕組みが一部機種だけ正常に機能せず、
何度試してもエラーになってしまいました。
（ごくまれな一部機種でしか問題が発生しないケースは切り分け難しいので厄介なんですよね）

## そもそもDRMとは
一般的な動画配信サービス（特に有料のもの）ではコンテンツを保護するためにDRMという技術を使っています

メジャーなDRMの方式としては以下の3つがあります。

|DRM方式名|提供元|URL|
|:--|:--|:--|
|Widevine DRM|Google|https://www.widevine.com/ |
|FairPlay DRM|Apple|https://developer.apple.com/streaming/fps/ |
|PlayReady DRM|Microsoft|https://www.microsoft.com/playready/ |


- 動画ファイルを落として再生を試してみたけどなかなかうまくいかない
- ScreenRecordingで画面をキャプチャしようとしても黒塗りの画面になってしまった

といった経験をされたこと方もいらっしゃるかもしれませんが、、
いずれのDRM方式もコンテンツを適切に暗号化し、
ハッキングによる著作権侵害を防ぎながらコンテンツ配信する仕組みを提供し、
ユーザーが動画サービスを楽しむ裏でそれらの仕組みが機能しています。

個人的にMicrosoftの[Compliance & Robustness Rules](https://www.microsoft.com/playready/licensing/compliance/ "Compliance & Robustness Rules")にコンテンツ保護に関する考え方がよくまとまっているので、興味のある方はそちらを参照していただければと思います。

## widevine DRMとは
- Googleが提供するDRMのエコシステムのことです。
- 世の中の数多ある動画配信サービスで利用されてます。
- ドコモでもdTVやdアニメストアなどといったサービスでも利用しています。
- AndroidOSは標準搭載でAndroid端末＝Widevine DRMサポート端末になります

ここにも特徴がかかれてるので参考まで
https://www.widevine.com/solutions/widevine-drm

## 原因は何だったのか
### 突然のACCESS_DENIED error
今回の事象はコンテンツを再生するのに必要なライセンスを発行するGoogleのサーバが、
ある日を境に特定のデバイスだけ以下のエラーを常に返すようになりました。

```

ACCESS_DENIED error(internal_status: 127)

```

。。。

これだけだと何のことかわかりません。
でもこのエラーコードに起因して視聴は全くできなくなってしまいました。
アプリもサーバもアップデートしてないのに。。（なんでー

図解するとこんな感じ

![fig_license_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877384/0f3d2a25-c0b8-6446-9cdd-1e2b6b254cb8.png)


### 日本だけじゃない
私たちだけに限らず、世界中のサービスプロバイダの人たちもおそらくですが困ってました。

Unable to play DRM or Encrypted Content on Asus Nexus 
https://github.com/google/ExoPlayer/issues/7986

Pixel C no longer plays Widevine content (and cannot be provisioned after factory reset)
https://github.com/google/ExoPlayer/issues/8075

・Googleのアナウンスを発見
ExoPlayerのIssue内でも議論されてますが、[こちら](https://www.widevine.com/news "widevine news" ) にGoogleが周知していた内容を発見しました。


>2020/07/08
>Device Revocation Override
>A new API has been added to allow license generation for revoked devices (response status code = 127).
>Widevine devices may be revoked due to non-compliance with our device robustness rules and rendered inactive. This feature is a prelude to the introduction of device security profiles, coming later in 2020.
>This API is added to both the cloud license service and the license SDK, please refer to the latest documentation (v16.3.1) where specific use-cases are allowed to override revocation.
>
>Device Status in License
>Widevine recommends that our partners use the device metadata returned in a license response (or request query) to determine content distribution eligibility per respective distribution rights.
>For example, it is not recommended to stream Level-1-quality content to a Level-3 platform.
>There are constant updates to the device database to reflect the health of the ecosystem. It is important to note that the database information may not match from what is reported by the device. The server is always correct source of information.

意訳の抜粋ですが
・widevineデバイスのいくつかはL1を破棄するよ
・破棄されたデバイスはstatus code = 127のエラーを返すよ

**ギャー。。これだーー。。！！**


### 原因サマリ
冒頭で触れた事件というのは、もともとL1のセキュリティレベルを担保してたデバイスが
**いつのまにかL3として扱われるようになってしまい**、
動画再生に必要なライセンスを取得できず、再生エラーになってしまいました。

#### ＜補足＞widevineのセキュリティレベル
- 大まかにL1とL3があります。
- セキュリティ強度はL1>L3です。
- 今回はデバイス発売以降の時間経過とともにセキュリティ強度が下がってるので、格下げしましたよ
ってことでした。

## 対処法
### 更なるアナウンス
Google Widevineの[ページ](https://www.widevine.com/news)によると


>There are constant updates to the device database to reflect the health of the ecosystem. It is important to note that the database information may not match from what is reported by the device. The server is always correct source of information.

何を言っているかというと、
- Googleのサーバがデバイスの管理をしてるよ
- 時々アップデートするしGoogleの管理サーバの内容が常に正だよ

です。

### 回避策
#### ①動画再生アプリ側で強制的にL3として再生させる
先ほど取り上げたOSSのExoPlayerのIssue内でも議論されていたのですが、
実は強制的にL3の仕組みを使って再生させる仕組みがあります。

ここですね。

https://github.com/google/ExoPlayer/blob/r2.12.2/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java

```

mediaDrm.setPropertyString("securityLevel", "L3");

```

事前にどのデバイスがL3になったかわかっていれば、このような対応でライセンス取得エラーにならずに回避することができます

![fig_force_L3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877384/731b7c8d-4b11-f219-16a9-fc9dcecce55b.png)


こちら試してみると、問題なく再生できました（やったー！
再生画像とか貼れたらよかったですが。。イメージが伝わりにくくてごめんなさい。。

#### ②ライセンスサーバ側でライセンスのoverrideをする
- さきほどの周知文に実はサーバ側でなんとかする **Device Revocation Override**というのが書かれてました。
- これはレスポンスエラーをサーバ側で上書きして、L3コンテンツだから再生許可を出させる、という対応です。

試してみると、こちらも問題なく再生できます。
やったー！！


![fig_override_r1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877384/5a826947-f655-f7b1-d0b5-14bf20fe506d.png)


どちらのやり方でも対応はできましたが、
実は、一つ目の方法がおすすめです。
理由や詳細をもっと紐解きたい場合は、後述のCWIPというパートナーになる必要があります

## まとめ
- 今回の記事では特定のデバイスでwidevineDRMの動画が視聴できなくなった事象とその対処方法について記載しました
- [CWIP(Certified Widevine Implementation Pertner)](https://www.widevine.com/training)というパートナーになればもっと詳しい情報を入手することができます。