Commit 15d6d805 authored by Nicolas Pomepuy's avatar Nicolas Pomepuy Committed by Geoffrey Métais
Browse files

Migrate root classes to kotlin

parent 31e490fb
......@@ -105,7 +105,7 @@ class MigrationTest {
@Test fun migrateFrom27() {
migrationTestHelper.createDatabase(TEST_DB_NAME, 27)
val preferences = Settings.getInstance(VLCApplication.getAppContext()).edit()
val preferences = Settings.getInstance(VLCApplication.appContext).edit()
val fakeCustomDirectories = TestUtil.createCustomDirectories(2)
// 27_28 migration rule moves the data from prefs to room
val prefCustomDirectories = fakeCustomDirectories.map { it.path }.reduce{ acc, path -> "$acc:$path" }
......
/*****************************************************************************
* DebugLogService.java
*****************************************************************************
* Copyright © 2015 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
package org.videolan.vlc;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.text.format.DateFormat;
import org.videolan.libvlc.util.AndroidUtil;
import org.videolan.vlc.gui.DebugLogActivity;
import org.videolan.vlc.gui.helpers.NotificationHelper;
import org.videolan.vlc.util.AndroidDevices;
import org.videolan.vlc.util.Logcat;
import org.videolan.vlc.util.Util;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.LinkedList;
import java.util.List;
import androidx.core.app.NotificationCompat;
public class DebugLogService extends Service implements Logcat.Callback, Runnable {
private static final int MSG_STARTED = 0;
private static final int MSG_STOPPED = 1;
private static final int MSG_ONLOG = 2;
private static final int MSG_SAVED = 3;
private static final int MAX_LINES = 20000;
private Logcat mLogcat = null;
private LinkedList<String> mLogList = new LinkedList<String>();
private Thread mSaveThread = null;
private final RemoteCallbackList<IDebugLogServiceCallback> mCallbacks = new RemoteCallbackList<IDebugLogServiceCallback>();
private final IBinder mBinder = new DebugLogServiceStub(this);
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
static class DebugLogServiceStub extends IDebugLogService.Stub {
private DebugLogService mService;
DebugLogServiceStub(DebugLogService service) {
mService = service;
}
@Override
public void start() {
mService.start();
}
@Override
public void stop() {
mService.stop();
}
@Override
public void clear() {
mService.clear();
}
@Override
public void save() {
mService.save();
}
@Override
public void registerCallback(IDebugLogServiceCallback cb) {
mService.registerCallback(cb);
}
@Override
public void unregisterCallback(IDebugLogServiceCallback cb) {
mService.unregisterCallback(cb);
}
}
private synchronized void sendMessage(int what, String str) {
int i = mCallbacks.beginBroadcast();
while (i > 0) {
i--;
final IDebugLogServiceCallback cb = mCallbacks.getBroadcastItem(i);
try {
switch (what) {
case MSG_STOPPED:
cb.onStopped();
break;
case MSG_STARTED: {
cb.onStarted(mLogList);
break;
}
case MSG_ONLOG:
cb.onLog(str);
break;
case MSG_SAVED:
cb.onSaved(str != null ? true : false, str);
break;
}
} catch (RemoteException e) {
}
}
mCallbacks.finishBroadcast();
}
@Override
public synchronized void onLog(String log) {
if (mLogList.size() > MAX_LINES)
mLogList.remove(0);
mLogList.add(log);
sendMessage(MSG_ONLOG, log);
}
public synchronized void start() {
if (mLogcat != null) return;
clear();
mLogcat = new Logcat();
mLogcat.start(this);
final Intent debugLogIntent = new Intent(this, DebugLogActivity.class);
debugLogIntent.setAction("android.intent.action.MAIN");
debugLogIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_CLEAR_TOP);
final PendingIntent pi = PendingIntent.getActivity(this, 0, debugLogIntent, 0);
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NotificationHelper.INSTANCE.getVLC_DEBUG_CHANNEL());
builder.setContentTitle(getResources().getString(R.string.log_service_title));
builder.setContentText(getResources().getString(R.string.log_service_text));
builder.setSmallIcon(R.drawable.ic_stat_vlc);
builder.setContentIntent(pi);
final Notification notification = builder.build();
startForeground(R.string.log_service_title, notification);
startService(new Intent(this, DebugLogService.class));
sendMessage(MSG_STARTED, null);
}
public synchronized void stop() {
mLogcat.stop();
mLogcat = null;
sendMessage(MSG_STOPPED, null);
stopForeground(true);
stopSelf();
}
public synchronized void clear() {
mLogList.clear();
}
/* mSaveThread */
@Override
public void run() {
final CharSequence timestamp = DateFormat.format(
"yyyyMMdd_kkmmss", System.currentTimeMillis());
final String filename = AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY + "/vlc_logcat_" + timestamp + ".log";
boolean saved = true;
FileOutputStream fos = null;
OutputStreamWriter output = null;
BufferedWriter bw = null;
try {
fos = new FileOutputStream(filename);
output = new OutputStreamWriter(fos);
bw = new BufferedWriter(output);
synchronized (this) {
for (String line : mLogList) {
bw.write(line);
bw.newLine();
}
}
} catch (FileNotFoundException e) {
saved = false;
} catch (IOException ioe) {
saved = false;
} finally {
saved &= Util.INSTANCE.close(bw);
saved &= Util.INSTANCE.close(output);
saved &= Util.INSTANCE.close(fos);
}
synchronized (this) {
mSaveThread = null;
sendMessage(MSG_SAVED, saved ? filename : null);
}
}
public synchronized void save() {
if (mSaveThread != null) {
try {
mSaveThread.join();
} catch (InterruptedException e) {}
mSaveThread = null;
}
mSaveThread = new Thread(this);
mSaveThread.start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
private void registerCallback(IDebugLogServiceCallback cb) {
if (cb != null) {
mCallbacks.register(cb);
sendMessage(mLogcat != null ? MSG_STARTED : MSG_STOPPED, null);
}
}
private void unregisterCallback(IDebugLogServiceCallback cb) {
if (cb != null)
mCallbacks.unregister(cb);
}
public static class Client {
public interface Callback {
void onStarted(List<String> lostList);
void onStopped();
void onLog(String msg);
void onSaved(boolean success, String path);
}
private boolean mBound = false;
private final Context mContext;
private Callback mCallback;
private IDebugLogService mIDebugLogService;
private Handler mHandler;
private final IDebugLogServiceCallback.Stub mICallback = new IDebugLogServiceCallback.Stub() {
@Override
public void onStopped() throws RemoteException {
mHandler.post(new Runnable() {
@Override
public void run() {
mCallback.onStopped();
}
});
}
@Override
public void onStarted(final List<String> logList) throws RemoteException {
mHandler.post(new Runnable() {
@Override
public void run() {
mCallback.onStarted(logList);
}
});
}
@Override
public void onLog(final String msg) throws RemoteException {
mHandler.post(new Runnable() {
@Override
public void run() {
mCallback.onLog(msg);
}
});
}
@Override
public void onSaved(final boolean success, final String path) throws RemoteException {
mHandler.post(new Runnable() {
@Override
public void run() {
mCallback.onSaved(success, path);
}
});
}
};
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (Client.this) {
mIDebugLogService = IDebugLogService.Stub.asInterface(service);
try {
mIDebugLogService.registerCallback(mICallback);
} catch (RemoteException e) {
release();
mContext.stopService(new Intent(mContext, DebugLogService.class));
mCallback.onStopped();
}
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
release();
mContext.stopService(new Intent(mContext, DebugLogService.class));
mCallback.onStopped();
}
};
public Client(Context context, Callback cb) throws IllegalArgumentException {
if (context == null | cb == null)
throw new IllegalArgumentException("Context and Callback can't be null");
mContext = context;
mCallback = cb;
mHandler = new Handler(Looper.getMainLooper());
mBound = mContext.bindService(new Intent(mContext, DebugLogService.class), mServiceConnection, Context.BIND_AUTO_CREATE);
}
public boolean start() {
synchronized (this) {
if (mIDebugLogService != null) {
try {
if (AndroidUtil.isOOrLater)
NotificationHelper.INSTANCE.createDebugServcieChannel(mContext.getApplicationContext());
mIDebugLogService.start();
return true;
} catch (RemoteException e) {
}
}
return false;
}
}
public boolean stop() {
synchronized (this) {
if (mIDebugLogService != null) {
try {
mIDebugLogService.stop();
return true;
} catch (RemoteException e) {
}
}
return false;
}
}
public boolean clear() {
synchronized (this) {
if (mIDebugLogService != null) {
try {
mIDebugLogService.clear();
return true;
} catch (RemoteException e) {
}
}
return false;
}
}
public boolean save() {
synchronized (this) {
if (mIDebugLogService != null) {
try {
mIDebugLogService.save();
return true;
} catch (RemoteException e) {
}
}
return false;
}
}
public void release() {
if (mBound) {
synchronized (this) {
if (mIDebugLogService != null && mICallback != null) {
try {
mIDebugLogService.unregisterCallback(mICallback);
} catch (RemoteException e) {
}
mIDebugLogService = null;
}
}
mBound = false;
mContext.unbindService(mServiceConnection);
}
mHandler.removeCallbacksAndMessages(null);
}
}
}
\ No newline at end of file
/*****************************************************************************
* DebugLogService.java
*
* Copyright © 2015 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*/
package org.videolan.vlc
import android.app.PendingIntent
import android.app.Service
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.os.RemoteCallbackList
import android.os.RemoteException
import android.text.format.DateFormat
import org.videolan.libvlc.util.AndroidUtil
import org.videolan.vlc.gui.DebugLogActivity
import org.videolan.vlc.gui.helpers.NotificationHelper
import org.videolan.vlc.util.AndroidDevices
import org.videolan.vlc.util.Logcat
import org.videolan.vlc.util.Util
import java.io.BufferedWriter
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import java.io.OutputStreamWriter
import java.util.LinkedList
import androidx.core.app.NotificationCompat
class DebugLogService : Service(), Logcat.Callback, Runnable {
private var logcat: Logcat? = null
private val logList = LinkedList<String>()
private var saveThread: Thread? = null
private val callbacks = RemoteCallbackList<IDebugLogServiceCallback>()
private val binder = DebugLogServiceStub(this)
override fun onBind(intent: Intent): IBinder? {
return binder
}
internal class DebugLogServiceStub(private val service: DebugLogService) : IDebugLogService.Stub() {
override fun start() {
service.start()
}
override fun stop() {
service.stop()
}
override fun clear() {
service.clear()
}
override fun save() {
service.save()
}
override fun registerCallback(cb: IDebugLogServiceCallback) {
service.registerCallback(cb)
}
override fun unregisterCallback(cb: IDebugLogServiceCallback) {
service.unregisterCallback(cb)
}
}
@Synchronized
private fun sendMessage(what: Int, str: String?) {
var i = callbacks.beginBroadcast()
while (i > 0) {
i--
val cb = callbacks.getBroadcastItem(i)
try {
when (what) {
MSG_STOPPED -> cb.onStopped()
MSG_STARTED -> {
cb.onStarted(logList)
}
MSG_ONLOG -> cb.onLog(str)
MSG_SAVED -> cb.onSaved(str != null, str)
}
} catch (e: RemoteException) {
}
}
callbacks.finishBroadcast()
}
@Synchronized
override fun onLog(log: String) {
if (logList.size > MAX_LINES)
logList.removeAt(0)
logList.add(log)
sendMessage(MSG_ONLOG, log)
}
@Synchronized
fun start() {
if (logcat != null) return
clear()
logcat = Logcat()
logcat!!.start(this)
val debugLogIntent = Intent(this, DebugLogActivity::class.java)
debugLogIntent.action = "android.intent.action.MAIN"
debugLogIntent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP
val pi = PendingIntent.getActivity(this, 0, debugLogIntent, 0)
val builder = NotificationCompat.Builder(this, NotificationHelper.VLC_DEBUG_CHANNEL)
builder.setContentTitle(resources.getString(R.string.log_service_title))
builder.setContentText(resources.getString(R.string.log_service_text))
builder.setSmallIcon(R.drawable.ic_stat_vlc)
builder.setContentIntent(pi)
val notification = builder.build()
startForeground(R.string.log_service_title, notification)
startService(Intent(this, DebugLogService::class.java))
sendMessage(MSG_STARTED, null)
}
@Synchronized
fun stop() {
logcat!!.stop()
logcat = null
sendMessage(MSG_STOPPED, null)
stopForeground(true)
stopSelf()
}
@Synchronized
fun clear() {
logList.clear()
}
/* saveThread */
override fun run() {
val timestamp = DateFormat.format(
"yyyyMMdd_kkmmss", System.currentTimeMillis())
val filename = AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY + "/vlc_logcat_" + timestamp + ".log"
var saved = true
var fos: FileOutputStream? = null
var output: OutputStreamWriter? = null
var bw: BufferedWriter? = null
try {
fos = FileOutputStream(filename)
output = OutputStreamWriter(fos)
bw = BufferedWriter(output)
synchronized(this) {
for (line in logList) {
bw.write(line)
bw.newLine()
}
}
} catch (e: FileNotFoundException) {
saved = false
} catch (ioe: IOException) {
saved = false
} finally {
saved = saved and Util.close(bw)