Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sched: Enable New Timezone Handling Code #8054

Merged
merged 1 commit into from
Jan 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions AnkiDroid/src/main/java/com/ichi2/anki/Preferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
import com.ichi2.compat.CompatHelper;
import com.ichi2.libanki.Collection;
import com.ichi2.libanki.Utils;
import com.ichi2.libanki.backend.exception.BackendNotSupportedException;
import com.ichi2.libanki.sched.AbstractSched;
import com.ichi2.preferences.NumberRangePreference;
import com.ichi2.themes.Themes;
import com.ichi2.ui.AppCompatPreferenceActivity;
Expand Down Expand Up @@ -586,6 +588,14 @@ private void initPreference(android.preference.Preference pref) {
Calendar calendar = col.crtGregorianCalendar();
((SeekBarPreference)pref).setValue(calendar.get(Calendar.HOUR_OF_DAY));
break;
case "newTimezoneHandling":
android.preference.CheckBoxPreference checkBox = (android.preference.CheckBoxPreference) pref;
checkBox.setChecked(col.getSched()._new_timezone_enabled());
if (col.schedVer() <= 1 || !col.isUsingRustBackend()) {
Timber.d("Disabled 'newTimezoneHandling' box");
checkBox.setEnabled(false);
}
break;
case "schedVer":
((android.preference.CheckBoxPreference)pref).setChecked(conf.optInt("schedVer", 1) == 2);
}
Expand Down Expand Up @@ -722,6 +732,25 @@ private void updatePreference(SharedPreferences prefs, String key, PreferenceCon
pm.setComponentEnabledSetting(providerName, state, PackageManager.DONT_KILL_APP);
break;
}
case "newTimezoneHandling" : {
if (getCol().schedVer() != 1 && getCol().isUsingRustBackend()) {
AbstractSched sched = getCol().getSched();
boolean was_enabled = sched._new_timezone_enabled();
boolean is_enabled = ((android.preference.CheckBoxPreference) pref).isChecked();
if (was_enabled != is_enabled) {
if (is_enabled) {
try {
sched.set_creation_offset();
} catch (BackendNotSupportedException e) {
throw e.alreadyUsingRustBackend();
}
} else {
sched.clear_creation_offset();
}
}
}
break;
}
case "schedVer": {
boolean wantNew = ((android.preference.CheckBoxPreference) pref).isChecked();
boolean haveNew = getCol().schedVer() == 2;
Expand Down
9 changes: 8 additions & 1 deletion AnkiDroid/src/main/java/com/ichi2/libanki/Collection.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabaseLockedException;
import android.os.Build;
import android.text.TextUtils;
import android.util.Pair;

Expand All @@ -37,6 +36,7 @@
import com.ichi2.libanki.backend.DroidBackend;
import com.ichi2.async.ProgressSender;
import com.ichi2.async.TaskManager;
import com.ichi2.libanki.backend.exception.BackendNotSupportedException;
import com.ichi2.libanki.exception.NoSuchDeckException;
import com.ichi2.libanki.exception.UnknownDatabaseVersionException;
import com.ichi2.libanki.hooks.ChessFilter;
Expand Down Expand Up @@ -246,6 +246,13 @@ private void _loadScheduler() {
mSched = new Sched(this);
} else if (ver == 2) {
mSched = new SchedV2(this);
if (!getServer() && isUsingRustBackend()) {
try {
getConf().put("localOffset", getSched()._current_timezone_offset());
} catch (BackendNotSupportedException e) {
throw e.alreadyUsingRustBackend();
}
}
}
}

Expand Down
6 changes: 5 additions & 1 deletion AnkiDroid/src/main/java/com/ichi2/libanki/Consts.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
****************************************************************************************/

package com.ichi2.libanki;
import net.ankiweb.rsdroid.RustCleanup;

import java.lang.annotation.Retention;

import androidx.annotation.IntDef;
Expand Down Expand Up @@ -124,7 +126,9 @@ public class Consts {
public static final int SYNC_ZIP_COUNT = 25;
public static final String SYNC_BASE = "https://sync%s.ankiweb.net/";
public static final Integer DEFAULT_HOST_NUM = null;
public static final int SYNC_VER = 9;
/* Note: 10 if using Rust backend, 9 if using Java. Set in BackendFactory.getInstance */
@RustCleanup("Use 10")
public static int SYNC_VER = 9;

public static final String HELP_SITE = "http://ankisrs.net/docs/manual.html";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package com.ichi2.libanki.backend;

import com.ichi2.libanki.DB;
import com.ichi2.libanki.backend.exception.BackendNotSupportedException;
import com.ichi2.libanki.backend.model.SchedTimingToday;

import androidx.annotation.VisibleForTesting;

Expand All @@ -34,4 +36,27 @@ public interface DroidBackend {

@VisibleForTesting(otherwise = VisibleForTesting.NONE)
void debugEnsureNoOpenPointers();

/**
* Obtains Timing information for the current day.
*
* @param createdSecs A UNIX timestamp of the collection creation time
* @param createdMinsWest The offset west of UTC at the time of creation (eg UTC+10 hours is -600)
* @param nowSecs timestamp of the current time
* @param nowMinsWest The current offset west of UTC
* @param rolloverHour The hour of the day the rollover happens (eg 4 for 4am)
* @return Timing information for the current day. See {@link SchedTimingToday}.
*/
SchedTimingToday sched_timing_today(long createdSecs, int createdMinsWest, long nowSecs, int nowMinsWest, int rolloverHour) throws BackendNotSupportedException;

/**
* For the given timestamp, return minutes west of UTC in the local timezone.<br/><br/>
*
* eg, Australia at +10 hours is -600.<br/>
* Includes the daylight savings offset if applicable.
*
* @param timestampSeconds The timestamp in seconds
* @return minutes west of UTC in the local timezone
*/
int local_minutes_west(long timestampSeconds) throws BackendNotSupportedException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
package com.ichi2.libanki.backend;

import com.ichi2.anki.AnkiDroidApp;
import com.ichi2.libanki.Consts;

import net.ankiweb.rsdroid.BackendFactory;
import net.ankiweb.rsdroid.RustBackendFailedException;
import net.ankiweb.rsdroid.RustCleanup;

import androidx.annotation.Nullable;
import timber.log.Timber;
Expand All @@ -36,6 +38,7 @@ private DroidBackendFactory() {
* Obtains an instance of a {@link DroidBackend}.
* Each call to this method will generate a separate instance which can handle a new Anki collection
*/
@RustCleanup("Change back to a constant SYNC_VER")
public static DroidBackend getInstance(boolean useBackend) {

BackendFactory backendFactory = null;
Expand All @@ -47,7 +50,11 @@ public static DroidBackend getInstance(boolean useBackend) {
AnkiDroidApp.sendExceptionReport(e, "DroidBackendFactory::getInstance");
}
}
return getInstance(backendFactory);

DroidBackend instance = getInstance(backendFactory);
// Update the Sync version if we can load the Rust
Consts.SYNC_VER = backendFactory == null ? 9 : 10;
return instance;
}

private static DroidBackend getInstance(@Nullable BackendFactory backendFactory) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package com.ichi2.libanki.backend;

import com.ichi2.libanki.DB;
import com.ichi2.libanki.backend.exception.BackendNotSupportedException;
import com.ichi2.libanki.backend.model.SchedTimingToday;

import net.ankiweb.rsdroid.RustCleanup;

Expand Down Expand Up @@ -56,4 +58,16 @@ public boolean isUsingRustBackend() {
public void debugEnsureNoOpenPointers() {
// no-op
}


@Override
public SchedTimingToday sched_timing_today(long createdSecs, int createdMinsWest, long nowSecs, int nowMinsWest, int rolloverHour) throws BackendNotSupportedException {
throw new BackendNotSupportedException();
}


@Override
public int local_minutes_west(long timestampSeconds) throws BackendNotSupportedException {
throw new BackendNotSupportedException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
package com.ichi2.libanki.backend;

import com.ichi2.libanki.DB;
import com.ichi2.libanki.backend.model.SchedTimingToday;
import com.ichi2.libanki.backend.model.SchedTimingTodayProto;

import net.ankiweb.rsdroid.BackendFactory;
import net.ankiweb.rsdroid.BackendUtils;

import BackendProto.AdBackend;
import timber.log.Timber;

/** The Backend in Rust */
public class RustDroidBackend implements DroidBackend {
Expand Down Expand Up @@ -69,4 +69,16 @@ public void debugEnsureNoOpenPointers() {
throw new IllegalStateException("Contained unclosed sequence numbers: " + numbers);
}
}

@Override
public SchedTimingToday sched_timing_today(long createdSecs, int createdMinsWest, long nowSecs, int nowMinsWest, int rolloverHour) {
AdBackend.SchedTimingTodayOut2 res = mBackend.getBackend().schedTimingTodayLegacy(createdSecs, createdMinsWest, nowSecs, nowMinsWest, rolloverHour);
return new SchedTimingTodayProto(res);
}


@Override
public int local_minutes_west(long timestampSeconds) {
return mBackend.getBackend().localMinutesWest(timestampSeconds).getVal();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2021 David Allison <[email protected]>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.ichi2.libanki.backend.exception;

import net.ankiweb.rsdroid.RustCleanup;

@RustCleanup("All of these should be removed when JavaBackend is removed")
public class BackendNotSupportedException extends Exception {
public RuntimeException alreadyUsingRustBackend() {
return new RuntimeException("A BackendNotSupportedException should not occur when using Rust backend", this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2021 David Allison <[email protected]>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.ichi2.libanki.backend.model;

public interface SchedTimingToday {
/** The number of days that have passed since the collection was created.<br/>
* uint32 upstream */
int days_elapsed();
/**
* Timestamp of the next day rollover.<br/>
* int64 upstream */
long next_day_at();
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2021 David Allison <[email protected]>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.ichi2.libanki.backend.model;

import BackendProto.AdBackend;

/**
* Adapter for SchedTimingTodayOut2 result from Rust
*/
public class SchedTimingTodayProto implements SchedTimingToday {

private final AdBackend.SchedTimingTodayOut2 mData;

public SchedTimingTodayProto(AdBackend.SchedTimingTodayOut2 data) {
mData = data;
}


@Override
public int days_elapsed() {
return mData.getDaysElapsed();
}


@Override
public long next_day_at() {
return mData.getNextDayAt();
}
}
14 changes: 12 additions & 2 deletions AnkiDroid/src/main/java/com/ichi2/libanki/sched/AbstractSched.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.ichi2.libanki.Deck;
import com.ichi2.libanki.DeckConfig;
import com.ichi2.libanki.Collection;
import com.ichi2.libanki.backend.exception.BackendNotSupportedException;

import java.lang.ref.WeakReference;
import java.util.List;
Expand All @@ -23,8 +24,6 @@
import androidx.annotation.VisibleForTesting;
import timber.log.Timber;

import androidx.annotation.NonNull;

/**
* In this documentation, I will call "normal use" the fact that between two successive calls to `getCard`, either the
* result of the first `getCard` is sent to `answerCard` or the scheduler is reset (through `reset` or `defer
Expand Down Expand Up @@ -518,4 +517,15 @@ protected static void leech(@NonNull Card card, @Nullable Activity activity) {
* @return The number of revlog in the collection
*/
public abstract int logCount();

public abstract int _current_timezone_offset() throws BackendNotSupportedException;

public abstract boolean _new_timezone_enabled();
/**
* Save the UTC west offset at the time of creation into the DB.
* Once stored, this activates the new timezone handling code.
*/
public abstract void set_creation_offset() throws BackendNotSupportedException;

public abstract void clear_creation_offset();
}
Loading