1ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistpackage com.android.hotspot2.osu.service;
2ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
3ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.content.Context;
4ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.os.Handler;
5ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.util.Log;
6ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
7ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.Utils;
8ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.WifiNetworkAdapter;
9ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.osu.OSUManager;
10ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.pps.HomeSP;
11ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
12ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport org.xml.sax.SAXException;
13ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
14ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.io.IOException;
15ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Collection;
16ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.HashMap;
17ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Map;
18ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
19ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistpublic class SubscriptionTimer implements Runnable {
20ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private final Handler mHandler;
21ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private final OSUManager mOSUManager;
22ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private final WifiNetworkAdapter mWifiNetworkAdapter;
23ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private final Map<HomeSP, UpdateAction> mOutstanding = new HashMap<>();
24ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
25ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private static class UpdateAction {
26ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        private final long mRemediation;
27ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        private final long mPolicy;
28ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
29ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        private UpdateAction(HomeSP homeSP, long now) {
30ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            mRemediation = homeSP.getSubscriptionUpdate() != null ?
31ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    now + homeSP.getSubscriptionUpdate().getInterval() : -1;
32ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            mPolicy = homeSP.getPolicy() != null ?
33ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    now + homeSP.getPolicy().getPolicyUpdate().getInterval() : -1;
34ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
35ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            Log.d(OSUManager.TAG, "Timer set for " + homeSP.getFQDN() +
36ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    ", remediation: " + Utils.toUTCString(mRemediation) +
37ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    ", policy: " + Utils.toUTCString(mPolicy));
38ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
39ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
40ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        private boolean remediate(long now) {
41ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return mRemediation > 0 && now >= mRemediation;
42ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
43ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
44ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        private boolean policyUpdate(long now) {
45ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return mPolicy > 0 && now >= mPolicy;
46ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
47ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
48ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        private long nextExpiry(long now) {
49ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            long min = Long.MAX_VALUE;
50ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            if (mRemediation > now) {
51ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                min = mRemediation;
52ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            }
53ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            if (mPolicy > now) {
54ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                min = Math.min(min, mPolicy);
55ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            }
56ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return min;
57ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
58ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
59ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
60ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private static final String ACTION_TIMER =
61ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            "com.android.hotspot2.osu.service.SubscriptionTimer.action.TICK";
62ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
63ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public SubscriptionTimer(OSUManager osuManager,
64ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                             WifiNetworkAdapter wifiNetworkAdapter, Context context) {
65ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        mOSUManager = osuManager;
66ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        mWifiNetworkAdapter = wifiNetworkAdapter;
67ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        mHandler = new Handler();
68ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
69ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
70ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    @Override
71ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public void run() {
72ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        checkUpdates();
73ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
74ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
75ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public void checkUpdates() {
76ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        mHandler.removeCallbacks(this);
77ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        long now = System.currentTimeMillis();
78ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        long next = Long.MAX_VALUE;
79ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        Collection<HomeSP> homeSPs = mWifiNetworkAdapter.getLoadedSPs();
80ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (homeSPs.isEmpty()) {
81ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return;
82ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
83ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        for (HomeSP homeSP : homeSPs) {
84ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            UpdateAction updateAction = mOutstanding.get(homeSP);
85ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            try {
86ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                if (updateAction == null) {
87ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    updateAction = new UpdateAction(homeSP, now);
88ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    mOutstanding.put(homeSP, updateAction);
89ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                } else if (updateAction.remediate(now)) {
90ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    mOSUManager.remediate(homeSP, false);
91ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    mOutstanding.put(homeSP, new UpdateAction(homeSP, now));
92ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                } else if (updateAction.policyUpdate(now)) {
93ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    mOSUManager.remediate(homeSP, true);
94ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    mOutstanding.put(homeSP, new UpdateAction(homeSP, now));
95ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                }
96ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                next = Math.min(next, updateAction.nextExpiry(now));
97ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            } catch (IOException | SAXException e) {
98ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                Log.d(OSUManager.TAG, "Failed subscription update: " + e.getMessage());
99ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            }
100ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
101ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        setAlarm(next);
102ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
103ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
104ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private void setAlarm(long tod) {
105ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        long delay = tod - System.currentTimeMillis();
106ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        mHandler.postAtTime(this, Math.max(1, delay));
107ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
108ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist}
109