16346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim/*
26346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim * Copyright (C) 2014 The Android Open Source Project
36346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim *
46346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim * Licensed under the Apache License, Version 2.0 (the "License");
56346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim * you may not use this file except in compliance with the License.
66346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim * You may obtain a copy of the License at
76346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim *
86346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim *      http://www.apache.org/licenses/LICENSE-2.0
96346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim *
106346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim * Unless required by applicable law or agreed to in writing, software
116346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim * distributed under the License is distributed on an "AS IS" BASIS,
126346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim * See the License for the specific language governing permissions and
146346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim * limitations under the License.
156346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim */
166346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim
176346155c5a48495944041e65ec279c88b0fa1391Jaewan Kimpackage com.android.server.net;
186346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim
196346155c5a48495944041e65ec279c88b0fa1391Jaewan Kimimport android.os.Handler;
206346155c5a48495944041e65ec279c88b0fa1391Jaewan Kimimport android.os.HandlerThread;
216346155c5a48495944041e65ec279c88b0fa1391Jaewan Kimimport android.text.TextUtils;
226346155c5a48495944041e65ec279c88b0fa1391Jaewan Kimimport android.util.Log;
236346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim
246346155c5a48495944041e65ec279c88b0fa1391Jaewan Kimimport java.io.BufferedOutputStream;
256346155c5a48495944041e65ec279c88b0fa1391Jaewan Kimimport java.io.DataOutputStream;
266346155c5a48495944041e65ec279c88b0fa1391Jaewan Kimimport java.io.FileOutputStream;
276346155c5a48495944041e65ec279c88b0fa1391Jaewan Kimimport java.io.IOException;
286346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim
296346155c5a48495944041e65ec279c88b0fa1391Jaewan Kimpublic class DelayedDiskWrite {
306346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim    private HandlerThread mDiskWriteHandlerThread;
316346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim    private Handler mDiskWriteHandler;
326346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim    /* Tracks multiple writes on the same thread */
336346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim    private int mWriteSequence = 0;
346346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim    private final String TAG = "DelayedDiskWrite";
356346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim
366346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim    public interface Writer {
376346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim        public void onWriteCalled(DataOutputStream out) throws IOException;
386346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim    }
396346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim
406346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim    public void write(final String filePath, final Writer w) {
41e5779d79eb46a6bacd33c54dbb28d99b07c16186Jan Nordqvist        write(filePath, w, true);
42e5779d79eb46a6bacd33c54dbb28d99b07c16186Jan Nordqvist    }
43e5779d79eb46a6bacd33c54dbb28d99b07c16186Jan Nordqvist
44e5779d79eb46a6bacd33c54dbb28d99b07c16186Jan Nordqvist    public void write(final String filePath, final Writer w, final boolean open) {
456346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim        if (TextUtils.isEmpty(filePath)) {
466346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim            throw new IllegalArgumentException("empty file path");
476346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim        }
486346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim
496346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim        /* Do a delayed write to disk on a separate handler thread */
506346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim        synchronized (this) {
516346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim            if (++mWriteSequence == 1) {
526346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim                mDiskWriteHandlerThread = new HandlerThread("DelayedDiskWriteThread");
536346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim                mDiskWriteHandlerThread.start();
546346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim                mDiskWriteHandler = new Handler(mDiskWriteHandlerThread.getLooper());
556346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim            }
566346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim        }
576346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim
586346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim        mDiskWriteHandler.post(new Runnable() {
596346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim            @Override
606346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim            public void run() {
61e5779d79eb46a6bacd33c54dbb28d99b07c16186Jan Nordqvist                doWrite(filePath, w, open);
626346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim            }
636346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim        });
646346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim    }
656346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim
66e5779d79eb46a6bacd33c54dbb28d99b07c16186Jan Nordqvist    private void doWrite(String filePath, Writer w, boolean open) {
676346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim        DataOutputStream out = null;
686346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim        try {
69e5779d79eb46a6bacd33c54dbb28d99b07c16186Jan Nordqvist            if (open) {
70e5779d79eb46a6bacd33c54dbb28d99b07c16186Jan Nordqvist                out = new DataOutputStream(new BufferedOutputStream(
716346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim                        new FileOutputStream(filePath)));
72e5779d79eb46a6bacd33c54dbb28d99b07c16186Jan Nordqvist            }
736346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim            w.onWriteCalled(out);
746346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim        } catch (IOException e) {
756346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim            loge("Error writing data file " + filePath);
766346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim        } finally {
776346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim            if (out != null) {
786346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim                try {
796346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim                    out.close();
806346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim                } catch (Exception e) {}
816346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim            }
826346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim
836346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim            // Quit if no more writes sent
846346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim            synchronized (this) {
856346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim                if (--mWriteSequence == 0) {
866346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim                    mDiskWriteHandler.getLooper().quit();
876346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim                    mDiskWriteHandler = null;
886346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim                    mDiskWriteHandlerThread = null;
896346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim                }
906346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim            }
916346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim        }
926346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim    }
936346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim
946346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim    private void loge(String s) {
956346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim        Log.e(TAG, s);
966346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim    }
976346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim}
986346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim
99