Skip to content

Commit e42377c

Browse files
Merge pull request #520 from TakayukiHoshi1984/feature_copyright_protection
[DeviceConnectManager] 著作権保護用 API を追加
2 parents 99447f5 + 6ccced5 commit e42377c

19 files changed

Lines changed: 1224 additions & 18 deletions

File tree

dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/util/OverlayPermissionActivity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class OverlayPermissionActivity extends Activity implements SimpleDialogF
2424
private static final int REQUEST_CODE_OVERLAY = 1234;
2525

2626
/**
27-
* オーバーレイ許可設定画面を表示して良いかの確認ダイアンログのタグを定義.
27+
* オーバーレイ許可設定画面を表示して良いかの確認ダイアログのタグを定義.
2828
*/
2929
private static final String TAG_NO_PERMISSION_DIALOG = "overlay-permission";
3030

dConnectManager/dConnectManager/dconnect-manager-app/src/main/AndroidManifest.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,20 @@
240240
android:exported="false"
241241
android:taskAffinity=".permission"
242242
android:theme="@style/Theme.Dialog.Transparent"/>
243+
244+
<!-- コピーガード用オーバーレイ許可取得画面 -->
245+
<activity android:name=".protection.OverlayPermissionActivity"
246+
android:exported="false"
247+
android:excludeFromRecents="true"
248+
android:taskAffinity=".permission"
249+
android:theme="@style/Theme.Dialog.Transparent"/>
250+
251+
<!-- 開発者向けオプション表示確認画面 -->
252+
<activity android:name=".protection.DeveloperToolDialogActivity"
253+
android:exported="false"
254+
android:excludeFromRecents="true"
255+
android:taskAffinity=".permission"
256+
android:theme="@style/Theme.Dialog.Transparent"/>
243257
</application>
244258

245259
</manifest>

dConnectManager/dConnectManager/dconnect-manager-app/src/main/java/org/deviceconnect/android/manager/DConnectService.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.deviceconnect.android.manager.core.plugin.MessagingException;
3030
import org.deviceconnect.android.manager.core.util.DConnectUtil;
3131
import org.deviceconnect.android.manager.core.util.VersionName;
32+
import org.deviceconnect.android.manager.profile.DConnectSettingProfile;
3233
import org.deviceconnect.android.manager.setting.KeywordDialogActivity;
3334
import org.deviceconnect.android.manager.setting.SettingActivity;
3435
import org.deviceconnect.android.manager.util.NotificationUtil;
@@ -91,6 +92,11 @@ public class DConnectService extends Service {
9192
*/
9293
private DConnectManager mManager;
9394

95+
/**
96+
* Device Connect Manager 本体に設定する Setting プロファイル.
97+
*/
98+
private DConnectSettingProfile mSettingProfile;
99+
94100
/**
95101
* WakeLockのインスタンス.
96102
*/
@@ -132,6 +138,8 @@ public void onCreate() {
132138

133139
DConnectApplication app = (DConnectApplication) getApplication();
134140
mSettings = app.getSettings();
141+
mSettingProfile = new DConnectSettingProfile();
142+
mSettingProfile.start(this, R.drawable.on_icon);
135143
mManager = new DConnectManager(this, mSettings, app.getPluginManager()) {
136144
@Override
137145
public Class<? extends BroadcastReceiver> getDConnectBroadcastReceiverClass() {
@@ -148,6 +156,7 @@ public Class<? extends Activity> getKeywordActivityClass() {
148156
return SettingActivity.class;
149157
}
150158
};
159+
mManager.addProfile(mSettingProfile);
151160

152161
// Webサーバの起動フラグがONになっている場合には起動を行う
153162
if (mSettings.isManagerStartFlag()) {
@@ -190,6 +199,7 @@ public int onStartCommand(final Intent intent, final int flags, final int startI
190199
@Override
191200
public void onDestroy() {
192201
stopInternal();
202+
mSettingProfile.stop();
193203
mManager = null;
194204
super.onDestroy();
195205
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
/*
2+
DConnectSettingProfile.java
3+
Copyright (c) 2020 NTT DOCOMO,INC.
4+
Released under the MIT license
5+
http://opensource.org/licenses/mit-license.php
6+
*/
7+
package org.deviceconnect.android.manager.profile;
8+
9+
import android.content.ComponentName;
10+
import android.content.Context;
11+
import android.content.Intent;
12+
import android.os.Handler;
13+
import android.os.HandlerThread;
14+
import android.util.Log;
15+
16+
import org.deviceconnect.android.event.Event;
17+
import org.deviceconnect.android.event.EventError;
18+
import org.deviceconnect.android.event.EventManager;
19+
import org.deviceconnect.android.manager.protection.SimpleCopyGuard;
20+
import org.deviceconnect.android.message.MessageUtils;
21+
import org.deviceconnect.android.profile.DConnectProfile;
22+
import org.deviceconnect.android.profile.api.DeleteApi;
23+
import org.deviceconnect.android.profile.api.GetApi;
24+
import org.deviceconnect.android.profile.api.PutApi;
25+
import org.deviceconnect.message.DConnectMessage;
26+
import org.deviceconnect.message.intent.message.IntentDConnectMessage;
27+
28+
import java.util.List;
29+
30+
import static org.deviceconnect.android.manager.BuildConfig.DEBUG;
31+
32+
/**
33+
* Setting プロファイル.
34+
*
35+
* @author NTT DOCOMO, INC.
36+
*/
37+
public class DConnectSettingProfile extends DConnectProfile {
38+
39+
/**
40+
* インターフェース名: copyGuard
41+
*/
42+
private static final String INTERFACE_COPY_GUARD = "copyGuard";
43+
44+
/**
45+
* アトリビュート名: onChange
46+
*/
47+
private static final String ATTR_ON_CHANGE = "onChange";
48+
49+
/**
50+
* コピーガード機能管理クラス.
51+
*/
52+
private SimpleCopyGuard mCopyGuard;
53+
54+
/**
55+
* コピーガード機能のイベントを受信するスレッド.
56+
*/
57+
private HandlerThread mHandlerThread;
58+
59+
private static Intent createEventMessage(final Event event) {
60+
Intent message = MessageUtils.createEventIntent();
61+
message.putExtra(DConnectMessage.EXTRA_SERVICE_ID, event.getServiceId());
62+
message.putExtra(DConnectMessage.EXTRA_PROFILE, event.getProfile());
63+
message.putExtra(DConnectMessage.EXTRA_INTERFACE, event.getInterface());
64+
message.putExtra(DConnectMessage.EXTRA_ATTRIBUTE, event.getAttribute());
65+
message.putExtra(DConnectMessage.EXTRA_ACCESS_TOKEN, event.getAccessToken());
66+
String receiverName = event.getReceiverName();
67+
if (receiverName != null) {
68+
ComponentName cn = ComponentName.unflattenFromString(receiverName);
69+
message.setComponent(cn);
70+
}
71+
return message;
72+
}
73+
74+
public DConnectSettingProfile() {
75+
// GET /gotapi/setting/copyGuard
76+
addApi(new GetApi() {
77+
@Override
78+
public String getAttribute() {
79+
return "copyGuard";
80+
}
81+
82+
@Override
83+
public boolean onRequest(final Intent request, final Intent response) {
84+
setResult(response, DConnectMessage.RESULT_OK);
85+
response.putExtra("enabled", mCopyGuard.isEnabled());
86+
return true;
87+
}
88+
});
89+
90+
// PUT /gotapi/setting/copyGuard
91+
addApi(new PutApi() {
92+
@Override
93+
public String getAttribute() {
94+
return "copyGuard";
95+
}
96+
97+
@Override
98+
public boolean onRequest(final Intent request, final Intent response) {
99+
try {
100+
mCopyGuard.enable();
101+
setResult(response, DConnectMessage.RESULT_OK);
102+
return true;
103+
} catch (Throwable e) {
104+
MessageUtils.setUnknownError(response, "Failed to enable copy guard: " + e.getMessage());
105+
return true;
106+
}
107+
}
108+
});
109+
110+
// DELETE /gotapi/setting/copyGuard
111+
addApi(new DeleteApi() {
112+
@Override
113+
public String getAttribute() {
114+
return "copyGuard";
115+
}
116+
117+
@Override
118+
public boolean onRequest(final Intent request, final Intent response) {
119+
mCopyGuard.disable();
120+
setResult(response, DConnectMessage.RESULT_OK);
121+
return true;
122+
}
123+
});
124+
125+
// PUT /gotapi/setting/copyGuard/onChange
126+
addApi(new PutApi() {
127+
@Override
128+
public String getInterface() {
129+
return "copyGuard";
130+
}
131+
132+
@Override
133+
public String getAttribute() {
134+
return "onChange";
135+
}
136+
137+
@Override
138+
public boolean onRequest(final Intent request, final Intent response) {
139+
if (DEBUG) {
140+
Log.d("ABC", "PUT /gotapi/setting/copyGuard/onChange: receiver = " + request.getParcelableExtra("receiver"));
141+
}
142+
143+
setReceiverNameToRequest(request);
144+
EventError error = EventManager.INSTANCE.addEvent(request);
145+
switch (error) {
146+
case NONE:
147+
setResult(response, DConnectMessage.RESULT_OK);
148+
break;
149+
case INVALID_PARAMETER:
150+
MessageUtils.setInvalidRequestParameterError(response);
151+
break;
152+
default:
153+
MessageUtils.setUnknownError(response);
154+
break;
155+
}
156+
return true;
157+
}
158+
});
159+
160+
// DELETE /gotapi/setting/copyGuard/onChange
161+
addApi(new DeleteApi() {
162+
@Override
163+
public String getInterface() {
164+
return "copyGuard";
165+
}
166+
167+
@Override
168+
public String getAttribute() {
169+
return "onChange";
170+
}
171+
172+
@Override
173+
public boolean onRequest(final Intent request, final Intent response) {
174+
setReceiverNameToRequest(request);
175+
EventError error = EventManager.INSTANCE.removeEvent(request);
176+
switch (error) {
177+
case NONE:
178+
setResult(response, DConnectMessage.RESULT_OK);
179+
break;
180+
case INVALID_PARAMETER:
181+
MessageUtils.setInvalidRequestParameterError(response);
182+
break;
183+
case NOT_FOUND:
184+
MessageUtils.setUnknownError(response, "Event is not registered.");
185+
break;
186+
default:
187+
MessageUtils.setUnknownError(response);
188+
break;
189+
}
190+
return true;
191+
}
192+
});
193+
}
194+
195+
private void setReceiverNameToRequest(final Intent request) {
196+
// NOTE: プラグインSDK側でレシーバー名が設定されないことが考慮されていないため、
197+
// 暫定的措置として擬似的なレシーバー名を設定する.
198+
request.putExtra(IntentDConnectMessage.EXTRA_RECEIVER,
199+
new ComponentName(getContext(), "org.deviceconnect.android.manager.DConnectBroadcastReceiver"));
200+
}
201+
202+
public void start(final Context context, final int appIconId) {
203+
mHandlerThread = new HandlerThread("SettingProfileThread");
204+
mHandlerThread.start();
205+
mCopyGuard = new SimpleCopyGuard(context, appIconId);
206+
mCopyGuard.setEventListener(((setting, isEnabled) -> {
207+
List<Event> events = EventManager.INSTANCE.getEventList(null,
208+
getProfileName(),
209+
INTERFACE_COPY_GUARD,
210+
ATTR_ON_CHANGE);
211+
for (Event event : events) {
212+
Intent intent = createEventMessage(event);
213+
intent.putExtra("enabled", isEnabled);
214+
sendEvent(intent, event.getAccessToken());
215+
}
216+
}), new Handler(mHandlerThread.getLooper()));
217+
}
218+
219+
public void stop() {
220+
mCopyGuard.reset();
221+
mCopyGuard = null;
222+
mHandlerThread.quitSafely();
223+
mHandlerThread = null;
224+
}
225+
226+
@Override
227+
public String getProfileName() {
228+
return "setting";
229+
}
230+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
CopyGuardSetting.java
3+
Copyright (c) 2020 NTT DOCOMO,INC.
4+
Released under the MIT license
5+
http://opensource.org/licenses/mit-license.php
6+
*/
7+
package org.deviceconnect.android.manager.protection;
8+
9+
import android.content.Context;
10+
import android.content.Intent;
11+
import android.os.Build;
12+
import android.os.Handler;
13+
14+
import org.deviceconnect.android.manager.R;
15+
import org.deviceconnect.android.util.NotificationUtils;
16+
17+
/**
18+
* コピーガード設定の基底クラス.
19+
*
20+
* @author NTT DOCOMO, INC.
21+
*/
22+
public abstract class CopyGuardSetting {
23+
24+
public interface EventListener {
25+
void onSettingChange(CopyGuardSetting setting, boolean isEnabled);
26+
}
27+
28+
protected EventListener mEventListener;
29+
30+
public abstract boolean isAvailable();
31+
32+
public abstract boolean isEnabled();
33+
34+
public abstract void enable();
35+
36+
public abstract void disable();
37+
38+
public void reset() {
39+
}
40+
41+
public void setEventListener(final EventListener listener, final Handler handler) {
42+
mEventListener = new EventListenerHolder(listener, handler);
43+
}
44+
45+
protected void startActivity(final Context context,
46+
final Intent intent) {
47+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
48+
NotificationUtils.createNotificationChannel(context);
49+
NotificationUtils.notify(context, hashCode(), 0, intent,
50+
context.getString(R.string.copy_guard_notification_activity_warnning));
51+
} else {
52+
context.startActivity(intent);
53+
}
54+
}
55+
56+
protected void notifyOnSettingChange(final boolean isEnabled) {
57+
if (mEventListener != null) {
58+
mEventListener.onSettingChange(this, isEnabled);
59+
}
60+
}
61+
62+
private static class EventListenerHolder implements EventListener {
63+
private final EventListener mEventListener;
64+
private final Handler mHandler;
65+
66+
EventListenerHolder(final EventListener eventListener,
67+
final Handler handler) {
68+
mEventListener = eventListener;
69+
mHandler = handler;
70+
}
71+
72+
@Override
73+
public void onSettingChange(final CopyGuardSetting setting, final boolean isEnabled) {
74+
mHandler.post(() -> mEventListener.onSettingChange(setting, isEnabled));
75+
}
76+
}
77+
}

0 commit comments

Comments
 (0)