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) { 416346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim if (TextUtils.isEmpty(filePath)) { 426346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim throw new IllegalArgumentException("empty file path"); 436346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim } 446346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim 456346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim /* Do a delayed write to disk on a separate handler thread */ 466346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim synchronized (this) { 476346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim if (++mWriteSequence == 1) { 486346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim mDiskWriteHandlerThread = new HandlerThread("DelayedDiskWriteThread"); 496346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim mDiskWriteHandlerThread.start(); 506346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim mDiskWriteHandler = new Handler(mDiskWriteHandlerThread.getLooper()); 516346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim } 526346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim } 536346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim 546346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim mDiskWriteHandler.post(new Runnable() { 556346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim @Override 566346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim public void run() { 576346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim doWrite(filePath, w); 586346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim } 596346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim }); 606346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim } 616346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim 626346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim private void doWrite(String filePath, Writer w) { 636346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim DataOutputStream out = null; 646346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim try { 656346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim out = new DataOutputStream(new BufferedOutputStream( 666346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim new FileOutputStream(filePath))); 676346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim w.onWriteCalled(out); 686346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim } catch (IOException e) { 696346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim loge("Error writing data file " + filePath); 706346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim } finally { 716346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim if (out != null) { 726346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim try { 736346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim out.close(); 746346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim } catch (Exception e) {} 756346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim } 766346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim 776346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim // Quit if no more writes sent 786346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim synchronized (this) { 796346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim if (--mWriteSequence == 0) { 806346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim mDiskWriteHandler.getLooper().quit(); 816346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim mDiskWriteHandler = null; 826346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim mDiskWriteHandlerThread = null; 836346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim } 846346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim } 856346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim } 866346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim } 876346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim 886346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim private void loge(String s) { 896346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim Log.e(TAG, s); 906346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim } 916346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim} 926346155c5a48495944041e65ec279c88b0fa1391Jaewan Kim 93